From 6628bf059696c5f62b4c32194bb9184ad65c7272 Mon Sep 17 00:00:00 2001 From: Bobby Lat Date: Thu, 6 Nov 2025 17:58:10 +0800 Subject: [PATCH 1/3] feat: add new overload for methodSelector to support type only import --- src/application-spy.ts | 2 +- src/impl/c2c.ts | 4 +- src/impl/method-selector.ts | 72 +++++++++++++++++++------ src/test-transformer/node-factory.ts | 23 ++++++-- src/test-transformer/visitors.ts | 3 +- tests/arc4/method-selector.algo.spec.ts | 36 +++++++++++++ 6 files changed, 117 insertions(+), 23 deletions(-) diff --git a/src/application-spy.ts b/src/application-spy.ts index 7086d20..c284904 100644 --- a/src/application-spy.ts +++ b/src/application-spy.ts @@ -112,7 +112,7 @@ export class ApplicationSpy { ocas = metadata.allowActions?.map((action) => OnCompleteAction[action]) ?? [OnCompleteAction.NoOp] } - const selector = methodSelector(fn, spy.contract) + const selector = methodSelector({ method: fn, contract: spy.contract }) spy.onAbiCall(selector, ocas, callback) } }, diff --git a/src/impl/c2c.ts b/src/impl/c2c.ts index 67a1cd4..0c25674 100644 --- a/src/impl/c2c.ts +++ b/src/impl/c2c.ts @@ -34,7 +34,7 @@ export function compileArc4( call: new Proxy({} as unknown as TContract, { get: (_target, prop) => { return (methodArgs: TypedApplicationCallFields) => { - const selector = methodSelector(prop as string, contract) + const selector = methodSelector({ method: prop as string, contract }) const abiMetadata = getContractMethodAbiMetadata(contract, prop as string) const onCompleteActions = abiMetadata?.allowActions?.map((action) => OnCompleteAction[action]) const itxnContext = ApplicationCallInnerTxnContext.createFromTypedApplicationCallFields( @@ -95,7 +95,7 @@ export function getApplicationCallInnerTxnContext( { ...methodArgs, diff --git a/src/impl/method-selector.ts b/src/impl/method-selector.ts index 9d8e4a9..e3c555a 100644 --- a/src/impl/method-selector.ts +++ b/src/impl/method-selector.ts @@ -1,23 +1,65 @@ -import type { arc4, bytes } from '@algorandfoundation/algorand-typescript' +import type { bytes } from '@algorandfoundation/algorand-typescript' import { encodingUtil } from '@algorandfoundation/puya-ts' -import { getArc4Selector, getContractMethodAbiMetadata } from '../abi-metadata' -import type { Overloads } from '../typescript-helpers' +import { getArc4Selector, getContractByName, getContractMethodAbiMetadata } from '../abi-metadata' +import { CodeError, InternalError } from '../errors' +import type { InstanceMethod } from '../typescript-helpers' import type { Contract } from './contract' import { sha512_256 } from './crypto' import { Bytes } from './primitives' -/** @internal */ -export const methodSelector = ( - methodSignature: Parameters>[0], - contract?: TContract | { new (): TContract }, -): bytes => { - if (typeof methodSignature === 'string' && contract === undefined) { - return sha512_256(Bytes(encodingUtil.utf8ToUint8Array(methodSignature))).slice(0, 4) - } else { - const abiMetadata = getContractMethodAbiMetadata( - contract!, - typeof methodSignature === 'string' ? methodSignature : methodSignature.name, - ) +/** + * Computes the method selector for an ARC-4 contract method. + * + * Supports three invocation patterns: + * 1. `methodSelector('sink(string,uint8[])void')`: + * Direct method signature string (no contract): Returns SHA-512/256 hash of signature + * 2. `methodSelector()`: + * Contract name as string + method name as string: Looks up registered contract and returns ARC-4 selector + * 3. `methodSelector(SignaturesContract.prototype.sink)`: + * Contract class/instance + method instance/name: Returns ARC-4 selector from ABI metadata + * + * @internal + */ +export const methodSelector = ({ + method, + contract, +}: { + method?: string | InstanceMethod + contract?: string | TContract | { new (): TContract } +}): bytes => { + const isDirectSignature = typeof method === 'string' && contract === undefined + const isContractNameLookup = typeof contract === 'string' && typeof method === 'string' && contract && method + const isContractMethodLookup = typeof contract !== 'string' && contract && method + + // Pattern 1: Direct method signature string (e.g., "add(uint64,uint64)uint64") + if (isDirectSignature) { + const signatureBytes = Bytes(encodingUtil.utf8ToUint8Array(method as string)) + return sha512_256(signatureBytes).slice(0, 4) + } + + // Pattern 2: Contract name as string with method name + if (isContractNameLookup) { + const registeredContract = getContractByName(contract) + + if (registeredContract === undefined || typeof registeredContract !== 'function') { + throw new InternalError(`Unknown contract: ${contract}`) + } + + if (!Object.hasOwn(registeredContract.prototype, method)) { + throw new InternalError(`Unknown method: ${method} in contract: ${contract}`) + } + + const abiMetadata = getContractMethodAbiMetadata(registeredContract, method) return Bytes(getArc4Selector(abiMetadata)) } + + // Pattern 3: Contract class/instance with method signature or name + if (isContractMethodLookup) { + const methodName = typeof method === 'string' ? method : method.name + + const abiMetadata = getContractMethodAbiMetadata(contract, methodName) + return Bytes(getArc4Selector(abiMetadata)) + } + + throw new CodeError('Invalid arguments to methodSelector') } diff --git a/src/test-transformer/node-factory.ts b/src/test-transformer/node-factory.ts index cf99b7f..9077268 100644 --- a/src/test-transformer/node-factory.ts +++ b/src/test-transformer/node-factory.ts @@ -121,16 +121,31 @@ export const nodeFactory = { return factory.updateCallExpression(node, node.expression, node.typeArguments, [...typeInfoArgs, ...(node.arguments ?? [])]) }, - callMethodSelectorFunction(node: ts.CallExpression) { - if ( + callMethodSelectorFunction(node: ts.CallExpression, typeParams: ptypes.PType[]) { + if (typeParams.length === 1 && typeParams[0] instanceof ptypes.FunctionPType && typeParams[0].declaredIn) { + return factory.updateCallExpression(node, node.expression, node.typeArguments, [ + factory.createObjectLiteralExpression([ + factory.createPropertyAssignment('method', factory.createStringLiteral(typeParams[0].name)), + factory.createPropertyAssignment('contract', factory.createStringLiteral(typeParams[0].declaredIn.fullName)), + ]), + ]) + } else if ( node.arguments.length === 1 && ts.isPropertyAccessExpression(node.arguments[0]) && ts.isPropertyAccessExpression(node.arguments[0].expression) ) { const contractIdenifier = node.arguments[0].expression.expression - return factory.updateCallExpression(node, node.expression, node.typeArguments, [...node.arguments, contractIdenifier]) + return factory.updateCallExpression(node, node.expression, node.typeArguments, [ + factory.createObjectLiteralExpression([ + factory.createPropertyAssignment('method', node.arguments[0]), + factory.createPropertyAssignment('contract', contractIdenifier), + ]), + ]) + } else { + return factory.updateCallExpression(node, node.expression, node.typeArguments, [ + factory.createObjectLiteralExpression([factory.createPropertyAssignment('method', node.arguments[0])]), + ]) } - return node }, callAbiCallFunction(node: ts.CallExpression, typeParams: ptypes.PType[]) { diff --git a/src/test-transformer/visitors.ts b/src/test-transformer/visitors.ts index a2793e7..27afd69 100644 --- a/src/test-transformer/visitors.ts +++ b/src/test-transformer/visitors.ts @@ -213,7 +213,8 @@ class ExpressionVisitor { if (stubbedFunctionName) { if (isCallingMethodSelector(stubbedFunctionName)) { - updatedNode = nodeFactory.callMethodSelectorFunction(updatedNode) + const typeParams = this.helper.resolveTypeParameters(updatedNode) + updatedNode = nodeFactory.callMethodSelectorFunction(updatedNode, typeParams) } else if (isCallingAbiCall(stubbedFunctionName)) { const typeParams = this.helper.resolveTypeParameters(updatedNode) updatedNode = nodeFactory.callAbiCallFunction(updatedNode, typeParams) diff --git a/tests/arc4/method-selector.algo.spec.ts b/tests/arc4/method-selector.algo.spec.ts index 94c9c15..add5bc8 100644 --- a/tests/arc4/method-selector.algo.spec.ts +++ b/tests/arc4/method-selector.algo.spec.ts @@ -49,6 +49,8 @@ describe('methodSelector', async () => { .map((_, i) => txn.appArgs(i)) expect(appArgs).toEqual([appClient.getABIMethod('sink(string,uint8[])void').getSelector(), arg1.bytes, arg2.bytes]) expect(appArgs[0]).toEqual(arc4.methodSelector(SignaturesContract.prototype.sink)) + expect(appArgs[0]).toEqual(arc4.methodSelector()) + expect(appArgs[0]).toEqual(arc4.methodSelector('sink(string,uint8[])void')) }) test('app args is correct with alias', async ({ appClientSignaturesContract: appClient }) => { @@ -71,6 +73,8 @@ describe('methodSelector', async () => { .map((_, i) => txn.appArgs(i)) expect(appArgs).toEqual([appClient.getABIMethod('alias(string,uint8[])void').getSelector(), arg1.bytes, arg2.bytes]) expect(appArgs[0]).toEqual(arc4.methodSelector(SignaturesContract.prototype.sink2)) + expect(appArgs[0]).toEqual(arc4.methodSelector()) + expect(appArgs[0]).toEqual(arc4.methodSelector('alias(string,uint8[])void')) }) test('app args is correct with txn', async ({ appClientSignaturesContract: appClient, algorand }) => { @@ -99,6 +103,8 @@ describe('methodSelector', async () => { .map((_, i) => txn.appArgs(i)) expect(appArgs).toEqual([appClient.getABIMethod('withTxn(string,pay,uint8[])void').getSelector(), arg1.bytes, arg3.bytes]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.withTxn)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual(methodSelector('withTxn(string,pay,uint8[])void')) }) test('app args is correct with asset', async ({ appClientSignaturesContract: appClient, algorand }) => { @@ -133,6 +139,8 @@ describe('methodSelector', async () => { arg3.bytes, ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.withAsset)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual(methodSelector('withAsset(string,asset,uint8[])void')) }) test('app args is correct with account', async ({ appClientSignaturesContract: appClient, algorand }) => { @@ -166,6 +174,8 @@ describe('methodSelector', async () => { arg3.bytes, ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.withAcc)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual(methodSelector('withAcc(string,account,uint8[])void')) }) test('app args is correct with application', async ({ appClientSignaturesContract: appClient, appFactorySignaturesContract }) => { @@ -201,6 +211,8 @@ describe('methodSelector', async () => { arg4.bytes, ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.withApp)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual(methodSelector('withApp(string,application,uint64,uint8[])void')) expect(appForeignApps.map((a) => a.id)).toEqual([selfApp.id, otherAppId]) }) @@ -246,6 +258,12 @@ describe('methodSelector', async () => { five.bytes, ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.complexSig)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual( + methodSelector( + 'complexSig(((uint64,string),(uint64,string),uint128,uint128),pay,account,uint8[])((uint64,string),((uint64,string),(uint64,string),uint128,uint128))', + ), + ) expect(result[0].bytes).toEqual(struct.anotherStruct.bytes) expect(result[1].bytes).toEqual(struct.bytes) }) @@ -296,6 +314,12 @@ describe('methodSelector', async () => { Bytes.fromHex('01'), ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.echoResourceByIndex)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual( + methodSelector( + 'echoResourceByIndex(asset,application,account)(uint64,uint64,address)', + ), + ) expect(result).toEqual([asaId, otherAppId, encodeAddress(acc.publicKey)]) }) @@ -346,6 +370,12 @@ describe('methodSelector', async () => { toBytes(account), ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.echoResourceByValue)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual( + methodSelector( + 'echoResourceByValue(uint64,uint64,address)(uint64,uint64,address)', + ), + ) expect(result).toEqual([asaId, otherAppId, encodeAddress(acc.publicKey)]) }) @@ -404,5 +434,11 @@ describe('methodSelector', async () => { five.bytes, ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.complexSig)) + expect(appArgs[0]).toEqual(methodSelector()) + expect(appArgs[0]).toEqual( + methodSelector( + 'complexSig(((uint64,string),(uint64,string),uint128,uint128),pay,account,uint8[])((uint64,string),((uint64,string),(uint64,string),uint128,uint128))', + ), + ) }) }) From fcbf47356916c7563216122f95895e79170b1111 Mon Sep 17 00:00:00 2001 From: Bobby Lat Date: Fri, 7 Nov 2025 11:54:42 +0800 Subject: [PATCH 2/3] feat: add new overloads for `begin` and `next` methods of `ItxnCompose` to support type only import --- src/abi-metadata.ts | 21 +++++- src/impl/c2c.ts | 9 +-- src/impl/itxn-compose.ts | 65 ++++++++++++------- src/impl/method-selector.ts | 14 +--- src/test-transformer/node-factory.ts | 11 +++- src/test-transformer/visitors.ts | 3 +- tests/arc4/method-selector.algo.spec.ts | 12 +--- tests/artifacts/itxn-compose/contract.algo.ts | 4 +- 8 files changed, 85 insertions(+), 54 deletions(-) diff --git a/src/abi-metadata.ts b/src/abi-metadata.ts index 1b16d49..934d556 100644 --- a/src/abi-metadata.ts +++ b/src/abi-metadata.ts @@ -1,10 +1,11 @@ import type { arc4, OnCompleteActionStr } from '@algorandfoundation/algorand-typescript' import js_sha512 from 'js-sha512' import { ConventionalRouting } from './constants' +import { InternalError } from './errors' import { Arc4MethodConfigSymbol, Contract } from './impl/contract' import type { TypeInfo } from './impl/encoded-types' import { getArc4TypeName } from './impl/encoded-types' -import type { DeliberateAny } from './typescript-helpers' +import type { DeliberateAny, InstanceMethod } from './typescript-helpers' /** @internal */ export interface AbiMetadata { @@ -109,6 +110,24 @@ export const getArc4Selector = (metadata: AbiMetadata): Uint8Array => { return new Uint8Array(hash.slice(0, 4)) } +/** @internal */ +export const getContractMethod = (contractFullName: string, methodName: string) => { + const contract = getContractByName(contractFullName) + + if (contract === undefined || typeof contract !== 'function') { + throw new InternalError(`Unknown contract: ${contractFullName}`) + } + + if (!Object.hasOwn(contract.prototype, methodName)) { + throw new InternalError(`Unknown method: ${methodName} in contract: ${contractFullName}`) + } + + return { + method: contract.prototype[methodName] as InstanceMethod, + contract, + } +} + /** * Get routing properties inferred by conventional naming * @param methodName The name of the method diff --git a/src/impl/c2c.ts b/src/impl/c2c.ts index 0c25674..0a2ba52 100644 --- a/src/impl/c2c.ts +++ b/src/impl/c2c.ts @@ -4,9 +4,8 @@ import type { ContractProxy, TypedApplicationCallFields, } from '@algorandfoundation/algorand-typescript/arc4' -import { getContractByName, getContractMethodAbiMetadata } from '../abi-metadata' +import { getContractMethod, getContractMethodAbiMetadata } from '../abi-metadata' import { lazyContext } from '../context-helpers/internal-context' -import { InternalError } from '../errors' import type { ConstructorFor, DeliberateAny, InstanceMethod } from '../typescript-helpers' import type { ApplicationCallInnerTxn } from './inner-transactions' import { ApplicationCallInnerTxnContext } from './inner-transactions' @@ -111,11 +110,9 @@ export function abiCall( method: string, methodArgs: TypedApplicationCallFields, ): { itxn: ApplicationCallInnerTxn; returnValue: TReturn | undefined } { - const contract = getContractByName(contractFullName) - if (contract === undefined || typeof contract !== 'function') throw new InternalError(`Unknown contract: ${contractFullName}`) - if (!Object.hasOwn(contract.prototype, method)) throw new InternalError(`Unknown method: ${method} in contract: ${contractFullName}`) + const { method: methodInstance, contract: contractInstance } = getContractMethod(contractFullName, method) - const itxnContext = getApplicationCallInnerTxnContext(contract.prototype[method], methodArgs, contract) + const itxnContext = getApplicationCallInnerTxnContext(methodInstance, methodArgs, contractInstance) invokeAbiCall(itxnContext) diff --git a/src/impl/itxn-compose.ts b/src/impl/itxn-compose.ts index 3d43946..d4d8155 100644 --- a/src/impl/itxn-compose.ts +++ b/src/impl/itxn-compose.ts @@ -10,7 +10,8 @@ import type { KeyRegistrationComposeFields, PaymentComposeFields, } from '@algorandfoundation/algorand-typescript' -import type { TypedApplicationCallFields } from '@algorandfoundation/algorand-typescript/arc4' +import type { AbiCallOptions, TypedApplicationCallFields } from '@algorandfoundation/algorand-typescript/arc4' +import { getContractMethod } from '../abi-metadata' import { lazyContext } from '../context-helpers/internal-context' import type { DeliberateAny, InstanceMethod } from '../typescript-helpers' import { getApplicationCallInnerTxnContext } from './c2c' @@ -29,16 +30,9 @@ class ItxnCompose { fields: TypedApplicationCallFields, contract?: Contract | { new (): Contract }, ): void - begin(...args: unknown[]): void { - lazyContext.txn.activeGroup.constructingItxnGroup.push( - args.length === 1 - ? (args[0] as AnyTransactionComposeFields) - : getApplicationCallInnerTxnContext( - args[0] as InstanceMethod, - args[1] as TypedApplicationCallFields, - args[2] as Contract | { new (): Contract }, - ), - ) + begin(options: AbiCallOptions, contract: string, method: string): void + begin(...args: unknown[]): void { + this.addInnerTransaction(...args) } next(fields: PaymentComposeFields): void @@ -49,22 +43,49 @@ class ItxnCompose { next(fields: ApplicationCallComposeFields): void next(fields: AnyTransactionComposeFields): void next(fields: ComposeItxnParams): void - next(_method: InstanceMethod, _fields: TypedApplicationCallFields): void - next(...args: unknown[]): void { - lazyContext.txn.activeGroup.constructingItxnGroup.push( - args.length === 1 - ? (args[0] as AnyTransactionComposeFields) - : getApplicationCallInnerTxnContext( - args[0] as InstanceMethod, - args[1] as TypedApplicationCallFields, - args[2] as Contract | { new (): Contract }, - ), - ) + next( + _method: InstanceMethod, + _fields: TypedApplicationCallFields, + contract?: Contract | { new (): Contract }, + ): void + next(options: AbiCallOptions, contract: string, method: string): void + next(...args: unknown[]): void { + this.addInnerTransaction(...args) } submit(): void { lazyContext.txn.activeGroup.submitInnerTransactionGroup() } + + private addInnerTransaction(...args: unknown[]): void { + let innerTxnFields + + // Single argument: direct transaction fields + if (args.length === 1) { + innerTxnFields = args[0] as AnyTransactionComposeFields + } + // Three arguments with object fields (deprecated signature): + // e.g. `itxnCompose.begin(Hello.prototype.greet, { appId, args: ['ho'] })` + else if (args.length === 3 && typeof args[1] === 'object') { + innerTxnFields = getApplicationCallInnerTxnContext( + args[0] as InstanceMethod, + args[1] as TypedApplicationCallFields, + args[2] as Contract | { new (): Contract }, + ) + } + // Three arguments with string contract name: + // e.g. `itxnCompose.next({ method: Hello.prototype.greet, appId, args: ['ho'] })` + // or `itxnCompose.next({ appId, args: ['ho'] })` + else { + const contractFullName = args[1] as string + const methodName = args[2] as string + const { method, contract } = getContractMethod(contractFullName, methodName) + + innerTxnFields = getApplicationCallInnerTxnContext(method, args[0] as TypedApplicationCallFields, contract) + } + + lazyContext.txn.activeGroup.constructingItxnGroup.push(innerTxnFields) + } } /** @internal */ diff --git a/src/impl/method-selector.ts b/src/impl/method-selector.ts index e3c555a..607426c 100644 --- a/src/impl/method-selector.ts +++ b/src/impl/method-selector.ts @@ -1,7 +1,7 @@ import type { bytes } from '@algorandfoundation/algorand-typescript' import { encodingUtil } from '@algorandfoundation/puya-ts' -import { getArc4Selector, getContractByName, getContractMethodAbiMetadata } from '../abi-metadata' -import { CodeError, InternalError } from '../errors' +import { getArc4Selector, getContractMethod, getContractMethodAbiMetadata } from '../abi-metadata' +import { CodeError } from '../errors' import type { InstanceMethod } from '../typescript-helpers' import type { Contract } from './contract' import { sha512_256 } from './crypto' @@ -39,15 +39,7 @@ export const methodSelector = ({ // Pattern 2: Contract name as string with method name if (isContractNameLookup) { - const registeredContract = getContractByName(contract) - - if (registeredContract === undefined || typeof registeredContract !== 'function') { - throw new InternalError(`Unknown contract: ${contract}`) - } - - if (!Object.hasOwn(registeredContract.prototype, method)) { - throw new InternalError(`Unknown method: ${method} in contract: ${contract}`) - } + const { contract: registeredContract } = getContractMethod(contract, method) const abiMetadata = getContractMethodAbiMetadata(registeredContract, method) return Bytes(getArc4Selector(abiMetadata)) diff --git a/src/test-transformer/node-factory.ts b/src/test-transformer/node-factory.ts index 9077268..d77c295 100644 --- a/src/test-transformer/node-factory.ts +++ b/src/test-transformer/node-factory.ts @@ -159,7 +159,7 @@ export const nodeFactory = { return node }, - callItxnComposeFunction(node: ts.CallExpression) { + callItxnComposeFunction(node: ts.CallExpression, typeParams: ptypes.PType[]) { if ( node.arguments.length === 2 && ts.isPropertyAccessExpression(node.arguments[0]) && @@ -167,6 +167,15 @@ export const nodeFactory = { ) { const contractIdenifier = node.arguments[0].expression.expression return factory.updateCallExpression(node, node.expression, node.typeArguments, [...node.arguments, contractIdenifier]) + } else if ( + node.arguments.length === 1 && + typeParams.length === 1 && + typeParams[0] instanceof ptypes.FunctionPType && + typeParams[0].declaredIn + ) { + const contractIdentifier = factory.createStringLiteral(typeParams[0].declaredIn.fullName) + const methodName = factory.createStringLiteral(typeParams[0].name) + return factory.updateCallExpression(node, node.expression, node.typeArguments, [...node.arguments, contractIdentifier, methodName]) } return node }, diff --git a/src/test-transformer/visitors.ts b/src/test-transformer/visitors.ts index 27afd69..d3c6ca6 100644 --- a/src/test-transformer/visitors.ts +++ b/src/test-transformer/visitors.ts @@ -219,7 +219,8 @@ class ExpressionVisitor { const typeParams = this.helper.resolveTypeParameters(updatedNode) updatedNode = nodeFactory.callAbiCallFunction(updatedNode, typeParams) } else if (isCallingItxnCompose(stubbedFunctionName)) { - updatedNode = nodeFactory.callItxnComposeFunction(updatedNode) + const typeParams = this.helper.resolveTypeParameters(updatedNode) + updatedNode = nodeFactory.callItxnComposeFunction(updatedNode, typeParams) } else { updatedNode = nodeFactory.callStubbedFunction(updatedNode, infoArg) } diff --git a/tests/arc4/method-selector.algo.spec.ts b/tests/arc4/method-selector.algo.spec.ts index add5bc8..41195cc 100644 --- a/tests/arc4/method-selector.algo.spec.ts +++ b/tests/arc4/method-selector.algo.spec.ts @@ -315,11 +315,7 @@ describe('methodSelector', async () => { ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.echoResourceByIndex)) expect(appArgs[0]).toEqual(methodSelector()) - expect(appArgs[0]).toEqual( - methodSelector( - 'echoResourceByIndex(asset,application,account)(uint64,uint64,address)', - ), - ) + expect(appArgs[0]).toEqual(methodSelector('echoResourceByIndex(asset,application,account)(uint64,uint64,address)')) expect(result).toEqual([asaId, otherAppId, encodeAddress(acc.publicKey)]) }) @@ -371,11 +367,7 @@ describe('methodSelector', async () => { ]) expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.echoResourceByValue)) expect(appArgs[0]).toEqual(methodSelector()) - expect(appArgs[0]).toEqual( - methodSelector( - 'echoResourceByValue(uint64,uint64,address)(uint64,uint64,address)', - ), - ) + expect(appArgs[0]).toEqual(methodSelector('echoResourceByValue(uint64,uint64,address)(uint64,uint64,address)')) expect(result).toEqual([asaId, otherAppId, encodeAddress(acc.publicKey)]) }) diff --git a/tests/artifacts/itxn-compose/contract.algo.ts b/tests/artifacts/itxn-compose/contract.algo.ts index e3ff874..d42a56e 100644 --- a/tests/artifacts/itxn-compose/contract.algo.ts +++ b/tests/artifacts/itxn-compose/contract.algo.ts @@ -59,7 +59,7 @@ export class ItxnComposeAlgo extends Contract { }) } - itxnCompose.next(VerifierContract.prototype.verify, { + itxnCompose.next({ appId: verifier, }) @@ -79,7 +79,7 @@ export class ItxnComposeAlgo extends Contract { if (i === 0) { itxnCompose.begin(Hello.prototype.greet, { appId, args: ['ho'] }) } else { - itxnCompose.next(Hello.prototype.greet, { appId, args: ['ho'] }) + itxnCompose.next({ method: Hello.prototype.greet, appId, args: ['ho'] }) } } itxnCompose.submit() From d91efb2e4274af39ccadd13c2ed6c2c54c7d193e Mon Sep 17 00:00:00 2001 From: Bobby Lat Date: Wed, 12 Nov 2025 10:05:05 +0800 Subject: [PATCH 3/3] update puya-ts dependencies --- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3ec1880..1396794 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,8 @@ "name": "@algorandfoundation/algorand-typescript-testing", "version": "1.0.0", "dependencies": { - "@algorandfoundation/algorand-typescript": "1.0.1", - "@algorandfoundation/puya-ts": "1.0.1", + "@algorandfoundation/algorand-typescript": "1.1.0-beta.1", + "@algorandfoundation/puya-ts": "1.1.0-beta.1", "elliptic": "^6.6.1", "js-sha256": "^0.11.0", "js-sha3": "^0.9.3", @@ -76,17 +76,17 @@ } }, "node_modules/@algorandfoundation/algorand-typescript": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@algorandfoundation/algorand-typescript/-/algorand-typescript-1.0.1.tgz", - "integrity": "sha512-XRn1D2/wU66j878/MmSS2kIkq8M8EgECiMeLMzatFIztVZclh3R3z+4CvXbF/WzluWUXCC7cyYmRWttrvqfYTQ==", + "version": "1.1.0-beta.1", + "resolved": "https://registry.npmjs.org/@algorandfoundation/algorand-typescript/-/algorand-typescript-1.1.0-beta.1.tgz", + "integrity": "sha512-H4JwdSfs7lNA9kBdSw/3gCtPtt63BHWEqUAFR/KkqvQxM3u1DgicZR2Bcw5PY1lw7lAH4zbX3nroVU6UxjCdcg==", "peerDependencies": { "tslib": "^2.6.2" } }, "node_modules/@algorandfoundation/puya-ts": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@algorandfoundation/puya-ts/-/puya-ts-1.0.1.tgz", - "integrity": "sha512-rTDLzp8ER0O5ueVWb/rrDQ17qGXFaqi+QG/4bRg0gCoJkCYkRhH19XDFn4VlPTD/E2MUepPl5qWduZe+h1Zy3g==", + "version": "1.1.0-beta.1", + "resolved": "https://registry.npmjs.org/@algorandfoundation/puya-ts/-/puya-ts-1.1.0-beta.1.tgz", + "integrity": "sha512-Y0IaojQeNNTOu0mte25Jq504LEEv78OFhhq+Ab5T/cX+6R+V+FKEuc8MJrlaykd5wDSdCa+kOWxwuNEITI+H4w==", "bundleDependencies": [ "vscode-jsonrpc", "vscode-languageserver", @@ -95,7 +95,7 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@algorandfoundation/algorand-typescript": "1.0.1", + "@algorandfoundation/algorand-typescript": "1.1.0-beta.1", "arcsecond": "^5.0.0", "argparse": "^2.0.1", "chalk": "^5.4.1", diff --git a/package.json b/package.json index 78f1cd2..bfc0f57 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,8 @@ "vitest": "3.2.4" }, "dependencies": { - "@algorandfoundation/algorand-typescript": "1.0.1", - "@algorandfoundation/puya-ts": "1.0.1", + "@algorandfoundation/algorand-typescript": "1.1.0-beta.1", + "@algorandfoundation/puya-ts": "1.1.0-beta.1", "elliptic": "^6.6.1", "js-sha256": "^0.11.0", "js-sha3": "^0.9.3",