Skip to content

Commit d0e38f4

Browse files
authored
Merge pull request #72 from algorandfoundation/feat/box-array-5
feat: implement stubs for Box create, no arg ctors, and encode/decode native arrays
2 parents eb2a40b + 2a69a0d commit d0e38f4

File tree

18 files changed

+602
-92
lines changed

18 files changed

+602
-92
lines changed

examples/auction/contract.algo.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ export class Auction extends Contract {
2626

2727
claimableAmount = LocalState<uint64>()
2828

29-
@abimethod({ allowActions: 'NoOp', onCreate: 'require' })
3029
public createApplication(): void {
3130
this.auctionEnd.value = 0
3231
this.previousBid.value = 0

package-lock.json

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@
6666
"vitest": "3.0.9"
6767
},
6868
"dependencies": {
69-
"@algorandfoundation/algorand-typescript": "1.0.0-beta.65",
70-
"@algorandfoundation/puya-ts": "1.0.0-beta.65",
69+
"@algorandfoundation/algorand-typescript": "1.0.0-alpha.49",
70+
"@algorandfoundation/puya-ts": "1.0.0-alpha.49",
7171
"elliptic": "^6.6.1",
7272
"js-sha256": "^0.11.0",
7373
"js-sha3": "^0.9.3",

src/abi-metadata.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { OnCompleteActionStr } from '@algorandfoundation/algorand-typescript'
22
import type { CreateOptions } from '@algorandfoundation/algorand-typescript/arc4'
33
import js_sha512 from 'js-sha512'
4+
import { ConventionalRouting } from './constants'
45
import type { TypeInfo } from './encoders'
56
import { Arc4MethodConfigSymbol, Contract } from './impl/contract'
67
import { getArc4TypeName as getArc4TypeNameForARC4Encoded } from './impl/encoded-types'
@@ -22,7 +23,12 @@ export const attachAbiMetadata = (contract: { new (): Contract }, methodName: st
2223
metadataStore.set(contract, {})
2324
}
2425
const metadatas: Record<string, AbiMetadata> = metadataStore.get(contract) as Record<string, AbiMetadata>
25-
metadatas[methodName] = metadata
26+
const conventionalRoutingConfig = getConventionalRoutingConfig(methodName)
27+
metadatas[methodName] = {
28+
...metadata,
29+
allowActions: metadata.allowActions ?? conventionalRoutingConfig?.allowActions,
30+
onCreate: metadata.onCreate ?? conventionalRoutingConfig?.onCreate,
31+
}
2632
}
2733

2834
export const getContractAbiMetadata = <T extends Contract>(contract: T | { new (): T }): Record<string, AbiMetadata> => {
@@ -110,3 +116,36 @@ const getArc4TypeName = (t: TypeInfo): string => {
110116
}
111117
return entry
112118
}
119+
120+
/**
121+
* Get routing properties inferred by conventional naming
122+
* @param methodName The name of the method
123+
*/
124+
const getConventionalRoutingConfig = (methodName: string): Pick<AbiMetadata, 'allowActions' | 'onCreate'> | undefined => {
125+
switch (methodName) {
126+
case ConventionalRouting.methodNames.closeOutOfApplication:
127+
return {
128+
allowActions: ['CloseOut'],
129+
onCreate: 'disallow',
130+
}
131+
case ConventionalRouting.methodNames.createApplication:
132+
return {
133+
onCreate: 'require',
134+
}
135+
case ConventionalRouting.methodNames.deleteApplication:
136+
return {
137+
allowActions: ['DeleteApplication'],
138+
}
139+
case ConventionalRouting.methodNames.optInToApplication:
140+
return {
141+
allowActions: ['OptIn'],
142+
}
143+
case ConventionalRouting.methodNames.updateApplication:
144+
return {
145+
allowActions: ['UpdateApplication'],
146+
onCreate: 'disallow',
147+
}
148+
default:
149+
return undefined
150+
}
151+
}

src/constants.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,13 @@ export enum OnApplicationComplete {
6666
UpdateApplicationOC = 4,
6767
DeleteApplicationOC = 5,
6868
}
69+
70+
export const ConventionalRouting = {
71+
methodNames: {
72+
closeOutOfApplication: 'closeOutOfApplication',
73+
createApplication: 'createApplication',
74+
deleteApplication: 'deleteApplication',
75+
optInToApplication: 'optInToApplication',
76+
updateApplication: 'updateApplication',
77+
},
78+
}

src/encoders.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { ARC4Encoded } from '@algorandfoundation/algorand-typescript/arc4'
33
import { encodingUtil } from '@algorandfoundation/puya-ts'
44
import { InternalError } from './errors'
55
import { BytesBackedCls, Uint64BackedCls } from './impl/base'
6-
import { arc4Encoders, encodeArc4Impl, getArc4Encoder } from './impl/encoded-types'
6+
import { arc4Encoders, encodeArc4Impl, getArc4Encoder, tryArc4EncodedLengthImpl } from './impl/encoded-types'
77
import { BigUint, Uint64, type StubBytesCompat } from './impl/primitives'
88
import { AccountCls, ApplicationCls, AssetCls } from './impl/reference'
99
import type { DeliberateAny } from './typescript-helpers'
@@ -63,7 +63,7 @@ export const getEncoder = <T>(typeInfo: TypeInfo): fromBytes<T> => {
6363
}
6464

6565
export const toBytes = (val: unknown): bytes => {
66-
const uint64Val = asMaybeUint64Cls(val)
66+
const uint64Val = asMaybeUint64Cls(val, false)
6767
if (uint64Val !== undefined) {
6868
return uint64Val.toBytes().asAlgoTs()
6969
}
@@ -85,7 +85,12 @@ export const toBytes = (val: unknown): bytes => {
8585
return val.bytes
8686
}
8787
if (Array.isArray(val) || typeof val === 'object') {
88-
return encodeArc4Impl('', val)
88+
return encodeArc4Impl(undefined, val)
8989
}
9090
throw new InternalError(`Invalid type for bytes: ${nameOfType(val)}`)
9191
}
92+
93+
export const minLengthForType = (typeInfo: TypeInfo): number => {
94+
const minArc4StaticLength = tryArc4EncodedLengthImpl(typeInfo)
95+
return minArc4StaticLength ?? 0
96+
}

src/impl/c2c.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,15 @@ export function abiCall<TArgs extends DeliberateAny[], TReturn>(
8989
methodArgs: TypedApplicationCallFields<TArgs>,
9090
contract?: Contract | { new (): Contract },
9191
): { itxn: ApplicationCallInnerTxn; returnValue: TReturn | undefined } {
92+
const abiMetadata = contract ? getContractMethodAbiMetadata(contract, method.name) : undefined
9293
const selector = methodSelector(method, contract)
93-
const itxnContext = ApplicationCallInnerTxnContext.createFromTypedApplicationCallFields<TReturn>(methodArgs, selector)
94+
const itxnContext = ApplicationCallInnerTxnContext.createFromTypedApplicationCallFields<TReturn>(
95+
{
96+
...methodArgs,
97+
onCompletion: methodArgs.onCompletion ?? abiMetadata?.allowActions?.map((action) => OnCompleteAction[action])[0],
98+
},
99+
selector,
100+
)
94101
invokeCallback(itxnContext)
95102

96103
return {

0 commit comments

Comments
 (0)