diff --git a/docs/code/subcontexts/contract-context/classes/ContractContext.md b/docs/code/subcontexts/contract-context/classes/ContractContext.md index 0aef89e..05bd9b9 100644 --- a/docs/code/subcontexts/contract-context/classes/ContractContext.md +++ b/docs/code/subcontexts/contract-context/classes/ContractContext.md @@ -6,7 +6,7 @@ # Class: ContractContext -Defined in: [src/subcontexts/contract-context.ts:122](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/contract-context.ts#L122) +Defined in: [src/subcontexts/contract-context.ts:138](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/contract-context.ts#L138) Provides a context for creating contracts and registering created contract instances with test execution context. @@ -27,7 +27,7 @@ with test execution context. > **create**\<`T`\>(`type`, ...`args`): `T` -Defined in: [src/subcontexts/contract-context.ts:134](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/contract-context.ts#L134) +Defined in: [src/subcontexts/contract-context.ts:150](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/contract-context.ts#L150) Creates a new contract instance and register the created instance with test execution context. @@ -70,7 +70,7 @@ const contract = ctx.contract.create(MyContract); > `static` **createMethodCallTxns**\<`TParams`\>(`contract`, `abiMetadata`, ...`args`): `Transaction`[] -Defined in: [src/subcontexts/contract-context.ts:156](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/contract-context.ts#L156) +Defined in: [src/subcontexts/contract-context.ts:172](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/contract-context.ts#L172) **`Internal`** diff --git a/docs/code/subcontexts/ledger-context/classes/LedgerContext.md b/docs/code/subcontexts/ledger-context/classes/LedgerContext.md index 272d8db..047a301 100644 --- a/docs/code/subcontexts/ledger-context/classes/LedgerContext.md +++ b/docs/code/subcontexts/ledger-context/classes/LedgerContext.md @@ -134,7 +134,7 @@ The contract to add. > **boxExists**(`app`, `key`): `boolean` -Defined in: [src/subcontexts/ledger-context.ts:379](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L379) +Defined in: [src/subcontexts/ledger-context.ts:377](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L377) Checks if a box exists for an application by key. @@ -164,7 +164,7 @@ True if the box exists, false otherwise. > **deleteBox**(`app`, `key`): `boolean` -Defined in: [src/subcontexts/ledger-context.ts:367](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L367) +Defined in: [src/subcontexts/ledger-context.ts:365](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L365) Deletes a box for an application by key. @@ -194,7 +194,7 @@ True if the box was deleted, false otherwise. > **getAccount**(`address`): `Account` -Defined in: [src/subcontexts/ledger-context.ts:60](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L60) +Defined in: [src/subcontexts/ledger-context.ts:59](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L59) Retrieves an account by address. @@ -202,27 +202,23 @@ Retrieves an account by address. ##### address -`Account` - The account address. +`StubBytesCompat` | `Account` + #### Returns `Account` The account. -#### Throws - -If the account is unknown. - *** ### getApplication() > **getApplication**(`applicationId`): `Application` -Defined in: [src/subcontexts/ledger-context.ts:86](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L86) +Defined in: [src/subcontexts/ledger-context.ts:82](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L82) Retrieves an application by application ID. @@ -250,7 +246,7 @@ If the application is unknown. > **getApplicationForApprovalProgram**(`approvalProgram`): `undefined` \| `Application` -Defined in: [src/subcontexts/ledger-context.ts:115](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L115) +Defined in: [src/subcontexts/ledger-context.ts:111](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L111) Retrieves an application for a given approval program. @@ -274,7 +270,7 @@ The application or undefined if not found. > **getApplicationForContract**(`contract`): `Application` -Defined in: [src/subcontexts/ledger-context.ts:99](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L99) +Defined in: [src/subcontexts/ledger-context.ts:95](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L95) Retrieves an application for a given contract. @@ -302,7 +298,7 @@ If the contract is unknown. > **getAsset**(`assetId`): `Asset` -Defined in: [src/subcontexts/ledger-context.ts:73](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L73) +Defined in: [src/subcontexts/ledger-context.ts:69](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L69) Retrieves an asset by asset ID. @@ -330,7 +326,7 @@ If the asset is unknown. > **getBlockData**(`index`): `BlockData` -Defined in: [src/subcontexts/ledger-context.ts:249](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L249) +Defined in: [src/subcontexts/ledger-context.ts:245](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L245) Retrieves block data by index. @@ -358,7 +354,7 @@ If the block is not set. > **getBox**(`app`, `key`): `Uint8Array` -Defined in: [src/subcontexts/ledger-context.ts:342](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L342) +Defined in: [src/subcontexts/ledger-context.ts:340](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L340) Retrieves a box for an application by key. @@ -388,7 +384,7 @@ The box data. > **getGlobalState**(`app`, `key`): \[`GlobalStateCls`\<`unknown`\>, `true`\] \| \[`undefined`, `false`\] -Defined in: [src/subcontexts/ledger-context.ts:263](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L263) +Defined in: [src/subcontexts/ledger-context.ts:259](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L259) Retrieves global state for an application by key. @@ -418,7 +414,7 @@ The global state and a boolean indicating if it was found. > **getLocalState**(`app`, `account`, `key`): \[`undefined`, `false`\] \| \[`LocalStateForAccount`\<`unknown`\>, `true`\] -Defined in: [src/subcontexts/ledger-context.ts:298](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L298) +Defined in: [src/subcontexts/ledger-context.ts:294](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L294) Retrieves local state for an application and account by key. @@ -428,7 +424,7 @@ Retrieves local state for an application and account by key. The application. -`Application` | `BaseContract` +`uint64` | `Application` | `BaseContract` ##### account @@ -454,7 +450,7 @@ The local state and a boolean indicating if it was found. > **patchAccountData**(`account`, `data`): `void` -Defined in: [src/subcontexts/ledger-context.ts:171](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L171) +Defined in: [src/subcontexts/ledger-context.ts:167](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L167) Patches account data with the provided partial data. @@ -482,7 +478,7 @@ The partial account data. > **patchApplicationData**(`app`, `data`): `void` -Defined in: [src/subcontexts/ledger-context.ts:188](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L188) +Defined in: [src/subcontexts/ledger-context.ts:184](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L184) Patches application data with the provided partial data. @@ -510,7 +506,7 @@ The partial application data. > **patchAssetData**(`asset`, `data`): `void` -Defined in: [src/subcontexts/ledger-context.ts:208](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L208) +Defined in: [src/subcontexts/ledger-context.ts:204](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L204) Patches asset data with the provided partial data. @@ -536,7 +532,7 @@ The partial asset data. > **patchBlockData**(`index`, `data`): `void` -Defined in: [src/subcontexts/ledger-context.ts:234](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L234) +Defined in: [src/subcontexts/ledger-context.ts:230](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L230) Patches block data with the provided partial data. @@ -564,7 +560,7 @@ The partial block data. > **patchGlobalData**(`data`): `void` -Defined in: [src/subcontexts/ledger-context.ts:159](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L159) +Defined in: [src/subcontexts/ledger-context.ts:155](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L155) Patches global data with the provided partial data. @@ -586,7 +582,7 @@ The partial global data. > **patchVoterData**(`account`, `data`): `void` -Defined in: [src/subcontexts/ledger-context.ts:221](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L221) +Defined in: [src/subcontexts/ledger-context.ts:217](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L217) Patches voter data with the provided partial data. @@ -614,7 +610,7 @@ The partial voter data. > **setBox**(`app`, `key`, `value`): `void` -Defined in: [src/subcontexts/ledger-context.ts:354](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L354) +Defined in: [src/subcontexts/ledger-context.ts:352](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L352) Sets a box for an application by key. @@ -648,7 +644,7 @@ The box data. > **setGlobalState**(`app`, `key`, `value`): `void` -Defined in: [src/subcontexts/ledger-context.ts:278](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L278) +Defined in: [src/subcontexts/ledger-context.ts:274](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L274) Sets global state for an application by key. @@ -680,19 +676,23 @@ The value (optional). ### setLocalState() -> **setLocalState**(`app`, `account`, `key`, `value`): `void` +> **setLocalState**\<`T`\>(`app`, `account`, `key`, `value`): `void` -Defined in: [src/subcontexts/ledger-context.ts:319](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L319) +Defined in: [src/subcontexts/ledger-context.ts:316](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L316) Sets local state for an application and account by key. +#### Type Parameters + +• **T** + #### Parameters ##### app The application. -`Application` | `BaseContract` +`uint64` | `Application` | `BaseContract` ##### account @@ -710,7 +710,7 @@ The key. The value (optional). -`undefined` | `StubBytesCompat` | `StubUint64Compat` +`undefined` | `T` #### Returns @@ -722,7 +722,7 @@ The value (optional). > **updateAssetHolding**(`account`, `assetId`, `balance`?, `frozen`?): `void` -Defined in: [src/subcontexts/ledger-context.ts:145](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L145) +Defined in: [src/subcontexts/ledger-context.ts:141](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/ledger-context.ts#L141) Update asset holdings for account, only specified values will be updated. AccountType will also be opted-in to asset diff --git a/docs/code/subcontexts/transaction-context/classes/DeferredAppCall.md b/docs/code/subcontexts/transaction-context/classes/DeferredAppCall.md index 7707327..a6cde11 100644 --- a/docs/code/subcontexts/transaction-context/classes/DeferredAppCall.md +++ b/docs/code/subcontexts/transaction-context/classes/DeferredAppCall.md @@ -6,7 +6,7 @@ # Class: DeferredAppCall\ -Defined in: [src/subcontexts/transaction-context.ts:60](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L60) +Defined in: [src/subcontexts/transaction-context.ts:59](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L59) Represents a deferred application call. @@ -22,7 +22,7 @@ Represents a deferred application call. > **new DeferredAppCall**\<`TParams`, `TReturn`\>(`appId`, `txns`, `method`, `abiMetadata`, `args`): [`DeferredAppCall`](DeferredAppCall.md)\<`TParams`, `TReturn`\> -Defined in: [src/subcontexts/transaction-context.ts:61](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L61) +Defined in: [src/subcontexts/transaction-context.ts:60](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L60) #### Parameters @@ -56,7 +56,7 @@ Defined in: [src/subcontexts/transaction-context.ts:61](https://github.com/algor > `readonly` **txns**: `Transaction`[] -Defined in: [src/subcontexts/transaction-context.ts:63](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L63) +Defined in: [src/subcontexts/transaction-context.ts:62](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L62) ## Methods @@ -64,7 +64,7 @@ Defined in: [src/subcontexts/transaction-context.ts:63](https://github.com/algor > **submit**(): `TReturn` -Defined in: [src/subcontexts/transaction-context.ts:73](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L73) +Defined in: [src/subcontexts/transaction-context.ts:72](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L72) Submits the deferred application call. diff --git a/docs/code/subcontexts/transaction-context/classes/ItxnGroup.md b/docs/code/subcontexts/transaction-context/classes/ItxnGroup.md index ab494ac..b63bb38 100644 --- a/docs/code/subcontexts/transaction-context/classes/ItxnGroup.md +++ b/docs/code/subcontexts/transaction-context/classes/ItxnGroup.md @@ -6,7 +6,7 @@ # Class: ItxnGroup -Defined in: [src/subcontexts/transaction-context.ts:475](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L475) +Defined in: [src/subcontexts/transaction-context.ts:485](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L485) Represents a group of inner transactions. @@ -16,7 +16,7 @@ Represents a group of inner transactions. > **new ItxnGroup**(`itxns`): [`ItxnGroup`](ItxnGroup.md) -Defined in: [src/subcontexts/transaction-context.ts:477](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L477) +Defined in: [src/subcontexts/transaction-context.ts:487](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L487) #### Parameters @@ -34,7 +34,7 @@ Defined in: [src/subcontexts/transaction-context.ts:477](https://github.com/algo > **itxns**: `InnerTxn`[] = `[]` -Defined in: [src/subcontexts/transaction-context.ts:476](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L476) +Defined in: [src/subcontexts/transaction-context.ts:486](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L486) ## Methods @@ -42,7 +42,7 @@ Defined in: [src/subcontexts/transaction-context.ts:476](https://github.com/algo > **getApplicationInnerTxn**(`index`?): `ApplicationInnerTxn` -Defined in: [src/subcontexts/transaction-context.ts:486](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L486) +Defined in: [src/subcontexts/transaction-context.ts:496](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L496) Gets an application inner transaction by index. @@ -66,7 +66,7 @@ The application inner transaction. > **getAssetConfigInnerTxn**(`index`?): `AssetConfigInnerTxn` -Defined in: [src/subcontexts/transaction-context.ts:495](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L495) +Defined in: [src/subcontexts/transaction-context.ts:505](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L505) Gets an asset configuration inner transaction by index. @@ -90,7 +90,7 @@ The asset configuration inner transaction. > **getAssetFreezeInnerTxn**(`index`?): `AssetFreezeInnerTxn` -Defined in: [src/subcontexts/transaction-context.ts:513](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L513) +Defined in: [src/subcontexts/transaction-context.ts:523](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L523) Gets an asset freeze inner transaction by index. @@ -114,7 +114,7 @@ The asset freeze inner transaction. > **getAssetTransferInnerTxn**(`index`?): `AssetTransferInnerTxn` -Defined in: [src/subcontexts/transaction-context.ts:504](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L504) +Defined in: [src/subcontexts/transaction-context.ts:514](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L514) Gets an asset transfer inner transaction by index. @@ -138,7 +138,7 @@ The asset transfer inner transaction. > **getInnerTxn**(`index`?): `InnerTxn` -Defined in: [src/subcontexts/transaction-context.ts:540](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L540) +Defined in: [src/subcontexts/transaction-context.ts:550](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L550) Gets an inner transaction by index. @@ -162,7 +162,7 @@ The inner transaction. > **getKeyRegistrationInnerTxn**(`index`?): `KeyRegistrationInnerTxn` -Defined in: [src/subcontexts/transaction-context.ts:522](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L522) +Defined in: [src/subcontexts/transaction-context.ts:532](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L532) Gets a key registration inner transaction by index. @@ -186,7 +186,7 @@ The key registration inner transaction. > **getPaymentInnerTxn**(`index`?): `PaymentInnerTxn` -Defined in: [src/subcontexts/transaction-context.ts:531](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L531) +Defined in: [src/subcontexts/transaction-context.ts:541](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L541) Gets a payment inner transaction by index. diff --git a/docs/code/subcontexts/transaction-context/classes/TransactionContext.md b/docs/code/subcontexts/transaction-context/classes/TransactionContext.md index 2cfa8cc..da359b5 100644 --- a/docs/code/subcontexts/transaction-context/classes/TransactionContext.md +++ b/docs/code/subcontexts/transaction-context/classes/TransactionContext.md @@ -6,7 +6,7 @@ # Class: TransactionContext -Defined in: [src/subcontexts/transaction-context.ts:82](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L82) +Defined in: [src/subcontexts/transaction-context.ts:81](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L81) Manages transaction contexts and groups. @@ -26,7 +26,7 @@ Manages transaction contexts and groups. > `readonly` **groups**: [`TransactionGroup`](TransactionGroup.md)[] = `[]` -Defined in: [src/subcontexts/transaction-context.ts:83](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L83) +Defined in: [src/subcontexts/transaction-context.ts:82](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L82) ## Accessors @@ -36,7 +36,7 @@ Defined in: [src/subcontexts/transaction-context.ts:83](https://github.com/algor > **get** **activeGroup**(): [`TransactionGroup`](TransactionGroup.md) -Defined in: [src/subcontexts/transaction-context.ts:139](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L139) +Defined in: [src/subcontexts/transaction-context.ts:148](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L148) Gets the active transaction group. @@ -58,7 +58,7 @@ The active transaction group. > **get** **lastActive**(): `Transaction` -Defined in: [src/subcontexts/transaction-context.ts:162](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L162) +Defined in: [src/subcontexts/transaction-context.ts:171](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L171) Gets the last active transaction. @@ -76,7 +76,7 @@ The last active transaction. > **get** **lastGroup**(): [`TransactionGroup`](TransactionGroup.md) -Defined in: [src/subcontexts/transaction-context.ts:151](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L151) +Defined in: [src/subcontexts/transaction-context.ts:160](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L160) Gets the last transaction group. @@ -96,7 +96,7 @@ The last transaction group. > **appendLog**(`value`): `void` -Defined in: [src/subcontexts/transaction-context.ts:172](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L172) +Defined in: [src/subcontexts/transaction-context.ts:181](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L181) **`Internal`** @@ -124,7 +124,7 @@ If the active transaction is not an application call. > **createScope**(`group`, `activeTransactionIndex`?): `ExecutionScope` -Defined in: [src/subcontexts/transaction-context.ts:92](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L92) +Defined in: [src/subcontexts/transaction-context.ts:91](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L91) Creates a new execution scope for a group of transactions. @@ -154,7 +154,7 @@ The execution scope. > **deferAppCall**\<`TContract`, `TParams`, `TReturn`\>(`contract`, `method`, `methodName`, ...`args`): [`DeferredAppCall`](DeferredAppCall.md)\<`TParams`, `TReturn`\> -Defined in: [src/subcontexts/transaction-context.ts:188](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L188) +Defined in: [src/subcontexts/transaction-context.ts:197](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L197) Defers an application call. @@ -204,7 +204,7 @@ The deferred application call. > **ensureScope**(`group`, `activeTransactionIndex`?): `ExecutionScope` -Defined in: [src/subcontexts/transaction-context.ts:123](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L123) +Defined in: [src/subcontexts/transaction-context.ts:132](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L132) **`Internal`** @@ -236,7 +236,7 @@ The execution scope. > **exportLogs**\<`T`\>(`appId`, ...`decoding`): `DecodedLogs`\<`T`\> -Defined in: [src/subcontexts/transaction-context.ts:206](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L206) +Defined in: [src/subcontexts/transaction-context.ts:215](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L215) Exports logs for the given application ID. diff --git a/docs/code/subcontexts/transaction-context/classes/TransactionGroup.md b/docs/code/subcontexts/transaction-context/classes/TransactionGroup.md index 1f07469..b290a8c 100644 --- a/docs/code/subcontexts/transaction-context/classes/TransactionGroup.md +++ b/docs/code/subcontexts/transaction-context/classes/TransactionGroup.md @@ -6,7 +6,7 @@ # Class: TransactionGroup -Defined in: [src/subcontexts/transaction-context.ts:224](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L224) +Defined in: [src/subcontexts/transaction-context.ts:233](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L233) Represents a group of transactions. @@ -16,7 +16,7 @@ Represents a group of transactions. > **new TransactionGroup**(`transactions`, `activeTransactionIndex`?): [`TransactionGroup`](TransactionGroup.md) -Defined in: [src/subcontexts/transaction-context.ts:231](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L231) +Defined in: [src/subcontexts/transaction-context.ts:240](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L240) #### Parameters @@ -38,7 +38,7 @@ Defined in: [src/subcontexts/transaction-context.ts:231](https://github.com/algo > **activeTransactionIndex**: `number` -Defined in: [src/subcontexts/transaction-context.ts:225](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L225) +Defined in: [src/subcontexts/transaction-context.ts:234](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L234) *** @@ -46,7 +46,7 @@ Defined in: [src/subcontexts/transaction-context.ts:225](https://github.com/algo > **constructingItxnGroup**: `InnerTxnFields`[] = `[]` -Defined in: [src/subcontexts/transaction-context.ts:229](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L229) +Defined in: [src/subcontexts/transaction-context.ts:238](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L238) *** @@ -54,7 +54,7 @@ Defined in: [src/subcontexts/transaction-context.ts:229](https://github.com/algo > **itxnGroups**: [`ItxnGroup`](ItxnGroup.md)[] = `[]` -Defined in: [src/subcontexts/transaction-context.ts:228](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L228) +Defined in: [src/subcontexts/transaction-context.ts:237](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L237) *** @@ -62,7 +62,7 @@ Defined in: [src/subcontexts/transaction-context.ts:228](https://github.com/algo > **latestTimestamp**: `number` -Defined in: [src/subcontexts/transaction-context.ts:226](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L226) +Defined in: [src/subcontexts/transaction-context.ts:235](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L235) *** @@ -70,7 +70,7 @@ Defined in: [src/subcontexts/transaction-context.ts:226](https://github.com/algo > **transactions**: `Transaction`[] -Defined in: [src/subcontexts/transaction-context.ts:227](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L227) +Defined in: [src/subcontexts/transaction-context.ts:236](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L236) ## Accessors @@ -80,7 +80,7 @@ Defined in: [src/subcontexts/transaction-context.ts:227](https://github.com/algo > **get** **activeApplicationId**(): `uint64` -Defined in: [src/subcontexts/transaction-context.ts:254](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L254) +Defined in: [src/subcontexts/transaction-context.ts:263](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L263) Gets the active application ID. @@ -102,7 +102,7 @@ The active application ID. > **get** **activeTransaction**(): `Transaction` -Defined in: [src/subcontexts/transaction-context.ts:245](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L245) +Defined in: [src/subcontexts/transaction-context.ts:254](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L254) Gets the active transaction. @@ -120,7 +120,7 @@ The active transaction. > **get** **constructingItxn**(): `InnerTxnFields` -Defined in: [src/subcontexts/transaction-context.ts:263](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L263) +Defined in: [src/subcontexts/transaction-context.ts:273](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L273) ##### Returns @@ -132,7 +132,7 @@ Defined in: [src/subcontexts/transaction-context.ts:263](https://github.com/algo > **addInnerTransactionGroup**(...`itxns`): `void` -Defined in: [src/subcontexts/transaction-context.ts:302](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L302) +Defined in: [src/subcontexts/transaction-context.ts:312](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L312) **`Internal`** @@ -156,7 +156,7 @@ The inner transactions. > **appendInnerTransactionGroup**(): `void` -Defined in: [src/subcontexts/transaction-context.ts:327](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L327) +Defined in: [src/subcontexts/transaction-context.ts:337](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L337) **`Internal`** @@ -176,7 +176,7 @@ If there is no inner transaction group being constructed. > **beginInnerTransactionGroup**(): `void` -Defined in: [src/subcontexts/transaction-context.ts:311](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L311) +Defined in: [src/subcontexts/transaction-context.ts:321](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L321) **`Internal`** @@ -196,7 +196,7 @@ If there is already an inner transaction group being constructed or the active t > **getApplicationTransaction**(`index`?): `ApplicationTransaction` -Defined in: [src/subcontexts/transaction-context.ts:384](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L384) +Defined in: [src/subcontexts/transaction-context.ts:394](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L394) Gets an application transaction by index. @@ -220,7 +220,7 @@ The application transaction. > **getAssetConfigTransaction**(`index`?): `AssetConfigTransaction` -Defined in: [src/subcontexts/transaction-context.ts:393](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L393) +Defined in: [src/subcontexts/transaction-context.ts:403](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L403) Gets an asset configuration transaction by index. @@ -244,7 +244,7 @@ The asset configuration transaction. > **getAssetFreezeTransaction**(`index`?): `AssetFreezeTransaction` -Defined in: [src/subcontexts/transaction-context.ts:411](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L411) +Defined in: [src/subcontexts/transaction-context.ts:421](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L421) Gets an asset freeze transaction by index. @@ -268,7 +268,7 @@ The asset freeze transaction. > **getAssetTransferTransaction**(`index`?): `AssetTransferTransaction` -Defined in: [src/subcontexts/transaction-context.ts:402](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L402) +Defined in: [src/subcontexts/transaction-context.ts:412](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L412) Gets an asset transfer transaction by index. @@ -292,7 +292,7 @@ The asset transfer transaction. > **getItxnGroup**(`index`?): [`ItxnGroup`](ItxnGroup.md) -Defined in: [src/subcontexts/transaction-context.ts:366](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L366) +Defined in: [src/subcontexts/transaction-context.ts:376](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L376) Gets an inner transaction group by index. @@ -320,7 +320,7 @@ If the index is invalid or there are no previous inner transactions. > **getKeyRegistrationTransaction**(`index`?): `KeyRegistrationTransaction` -Defined in: [src/subcontexts/transaction-context.ts:420](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L420) +Defined in: [src/subcontexts/transaction-context.ts:430](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L430) Gets a key registration transaction by index. @@ -344,7 +344,7 @@ The key registration transaction. > **getPaymentTransaction**(`index`?): `PaymentTransaction` -Defined in: [src/subcontexts/transaction-context.ts:429](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L429) +Defined in: [src/subcontexts/transaction-context.ts:439](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L439) Gets a payment transaction by index. @@ -368,7 +368,7 @@ The payment transaction. > **getScratchSlot**(`index`): `bytes` \| `uint64` -Defined in: [src/subcontexts/transaction-context.ts:283](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L283) +Defined in: [src/subcontexts/transaction-context.ts:293](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L293) Gets the scratch slot of the active transaction. @@ -392,7 +392,7 @@ The scratch slot value. > **getScratchSpace**(): (`bytes` \| `uint64`)[] -Defined in: [src/subcontexts/transaction-context.ts:274](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L274) +Defined in: [src/subcontexts/transaction-context.ts:284](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L284) Gets the scratch space of the active transaction. @@ -408,7 +408,7 @@ The scratch space. > **getTransaction**(`index`?): `Transaction` -Defined in: [src/subcontexts/transaction-context.ts:438](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L438) +Defined in: [src/subcontexts/transaction-context.ts:448](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L448) Gets a transaction by index. @@ -432,7 +432,7 @@ The transaction. > **lastItxnGroup**(): [`ItxnGroup`](ItxnGroup.md) -Defined in: [src/subcontexts/transaction-context.ts:356](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L356) +Defined in: [src/subcontexts/transaction-context.ts:366](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L366) Gets the last inner transaction group. @@ -448,7 +448,7 @@ The last inner transaction group. > **patchActiveTransactionFields**(`fields`): `void` -Defined in: [src/subcontexts/transaction-context.ts:291](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L291) +Defined in: [src/subcontexts/transaction-context.ts:301](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L301) Patches the fields of the active transaction. @@ -470,7 +470,7 @@ The fields to patch. > **submitInnerTransactionGroup**(): `void` -Defined in: [src/subcontexts/transaction-context.ts:339](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L339) +Defined in: [src/subcontexts/transaction-context.ts:349](https://github.com/algorandfoundation/algorand-typescript-testing/blob/main/src/subcontexts/transaction-context.ts#L349) **`Internal`** diff --git a/examples/precompiled/contract.algo.ts b/examples/precompiled/contract.algo.ts index abce1ec..c440d63 100644 --- a/examples/precompiled/contract.algo.ts +++ b/examples/precompiled/contract.algo.ts @@ -6,10 +6,9 @@ import { Hello, HelloTemplate, HelloTemplateCustomPrefix, LargeProgram, Terrible export class HelloFactory extends Contract { test_compile_contract() { const compiled = compile(Hello) - const helloApp = itxn .applicationCall({ - appArgs: [methodSelector('create(string)void'), encodeArc4('hello')], + appArgs: [methodSelector(Hello.prototype.create), encodeArc4('hello')], approvalProgram: compiled.approvalProgram, clearStateProgram: compiled.clearStateProgram, globalNumBytes: 1, @@ -18,7 +17,7 @@ export class HelloFactory extends Contract { const txn = itxn .applicationCall({ - appArgs: [methodSelector('greet(string)string'), encodeArc4('world')], + appArgs: [methodSelector(Hello.prototype.greet), encodeArc4('world')], appId: helloApp, }) .submit() @@ -29,7 +28,7 @@ export class HelloFactory extends Contract { itxn .applicationCall({ appId: helloApp, - appArgs: [methodSelector('delete()void')], + appArgs: [methodSelector(Hello.prototype.delete)], onCompletion: OnCompleteAction.DeleteApplication, }) .submit() diff --git a/examples/precompiled/precompiled-apps.algo.ts b/examples/precompiled/precompiled-apps.algo.ts index bdec103..8f06158 100644 --- a/examples/precompiled/precompiled-apps.algo.ts +++ b/examples/precompiled/precompiled-apps.algo.ts @@ -15,7 +15,7 @@ abstract class HelloBase extends Contract { } export class Hello extends HelloBase { - @abimethod({ onCreate: 'require' }) + @abimethod({ name: 'helloCreate', onCreate: 'require' }) create(greeting: string) { this.greeting.value = greeting } diff --git a/package-lock.json b/package-lock.json index b3471e8..5a37cd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "1.0.0", "hasInstallScript": true, "dependencies": { - "@algorandfoundation/algorand-typescript": "^1.0.0-beta.18", - "@algorandfoundation/puya-ts": "^1.0.0-beta.25", + "@algorandfoundation/algorand-typescript": "^1.0.0-beta.20", + "@algorandfoundation/puya-ts": "^1.0.0-beta.30", "elliptic": "^6.5.7", "js-sha256": "^0.11.0", "js-sha3": "^0.9.3", @@ -78,17 +78,17 @@ } }, "node_modules/@algorandfoundation/algorand-typescript": { - "version": "1.0.0-beta.18", - "resolved": "https://registry.npmjs.org/@algorandfoundation/algorand-typescript/-/algorand-typescript-1.0.0-beta.18.tgz", - "integrity": "sha512-R3vCPOvWECvowlQKVWxYlXDLs0NQvY0icG0fGYMvR3OQi6RAE4Tatqbk254hIZ9/pFs1IDqPzHgqqtgnhrrOig==", + "version": "1.0.0-beta.20", + "resolved": "https://registry.npmjs.org/@algorandfoundation/algorand-typescript/-/algorand-typescript-1.0.0-beta.20.tgz", + "integrity": "sha512-W/QSCUP7QFCdCsD6PYDyuPf+SnTL7wO0xbzRM52eWTQ7m0T8v8uWJ0obbntQqRXY5QJDdgkLN+Zrq6KBRNNzBg==", "peerDependencies": { "tslib": "^2.6.2" } }, "node_modules/@algorandfoundation/puya-ts": { - "version": "1.0.0-beta.25", - "resolved": "https://registry.npmjs.org/@algorandfoundation/puya-ts/-/puya-ts-1.0.0-beta.25.tgz", - "integrity": "sha512-Nqv4bvIVivBeDB4ibExf+68sqnMLCBj1diFLJWRPf+WL06rlVsvPGFd2D0xSYPKnRTD7HxIQxrOSXbYt+LrsSA==", + "version": "1.0.0-beta.30", + "resolved": "https://registry.npmjs.org/@algorandfoundation/puya-ts/-/puya-ts-1.0.0-beta.30.tgz", + "integrity": "sha512-ZCm2OAOrRZQQt4Cm4ZKJ3jteWuQfq9t0CyXvmAPv8IYT2ki6bIOAuf8JWqK7CJwZ/aFB4LWieO/CMy1SCRgpYg==", "bundleDependencies": [ "typescript" ], diff --git a/package.json b/package.json index c0f68f4..d67f500 100644 --- a/package.json +++ b/package.json @@ -71,8 +71,8 @@ "tslib": "^2.6.2" }, "dependencies": { - "@algorandfoundation/algorand-typescript": "^1.0.0-beta.18", - "@algorandfoundation/puya-ts": "^1.0.0-beta.25", + "@algorandfoundation/algorand-typescript": "^1.0.0-beta.20", + "@algorandfoundation/puya-ts": "^1.0.0-beta.30", "elliptic": "^6.5.7", "js-sha256": "^0.11.0", "js-sha3": "^0.9.3", diff --git a/src/abi-metadata.ts b/src/abi-metadata.ts index 775ebed..edb7bb4 100644 --- a/src/abi-metadata.ts +++ b/src/abi-metadata.ts @@ -1,70 +1,62 @@ -import type { BaseContract, Contract } from '@algorandfoundation/algorand-typescript' -import type { AbiMethodConfig, BareMethodConfig, CreateOptions, OnCompleteActionStr } from '@algorandfoundation/algorand-typescript/arc4' +import type { CreateOptions, OnCompleteActionStr } from '@algorandfoundation/algorand-typescript/arc4' import js_sha512 from 'js-sha512' import type { TypeInfo } from './encoders' +import { Arc4MethodConfigSymbol, Contract } from './impl/contract' import { getArc4TypeName as getArc4TypeNameForARC4Encoded } from './impl/encoded-types' import type { DeliberateAny } from './typescript-helpers' export interface AbiMetadata { methodName: string + name?: string methodSignature: string | undefined argTypes: string[] returnType: string onCreate?: CreateOptions allowActions?: OnCompleteActionStr[] } -const AbiMetaSymbol = Symbol('AbiMetadata') -export const isContractProxy = Symbol('isContractProxy') + +const metadataStore: WeakMap<{ new (): Contract }, Record> = new WeakMap() export const attachAbiMetadata = (contract: { new (): Contract }, methodName: string, metadata: AbiMetadata): void => { - const metadatas: Record = (AbiMetaSymbol in contract ? contract[AbiMetaSymbol] : {}) as Record - metadatas[methodName] = metadata - if (!(AbiMetaSymbol in contract)) { - Object.defineProperty(contract, AbiMetaSymbol, { - value: metadatas, - writable: true, - enumerable: false, - }) + if (!metadataStore.has(contract)) { + metadataStore.set(contract, {}) } + const metadatas: Record = metadataStore.get(contract) as Record + metadatas[methodName] = metadata } -export const copyAbiMetadatas = (sourceContract: T, targetContract: T): void => { - const metadatas = getContractAbiMetadata(sourceContract) - Object.defineProperty(targetContract, AbiMetaSymbol, { - value: metadatas, - writable: true, - enumerable: false, - }) -} +export const getContractAbiMetadata = (contract: T | { new (): T }): Record => { + // Initialize result object to store merged metadata + const result: Record = {} -export const captureMethodConfig = ( - contract: T, - methodName: string, - config?: AbiMethodConfig | BareMethodConfig, -): void => { - const metadata = getContractMethodAbiMetadata(contract, methodName) - metadata.onCreate = config?.onCreate ?? 'disallow' - metadata.allowActions = ([] as OnCompleteActionStr[]).concat(config?.allowActions ?? 'NoOp') -} + // Get the contract's class + let currentClass = contract instanceof Contract ? (contract.constructor as { new (): T }) : contract -export const hasAbiMetadata = (contract: T): boolean => { - const contractClass = contract.constructor as { new (): T } - return ( - Object.getOwnPropertySymbols(contractClass).some((s) => s.toString() === AbiMetaSymbol.toString()) || AbiMetaSymbol in contractClass - ) -} -export const getContractAbiMetadata = (contract: T): Record => { - if ((contract as DeliberateAny)[isContractProxy]) { - return (contract as DeliberateAny)[AbiMetaSymbol] as Record + // Walk up the prototype chain + while (currentClass && currentClass.prototype) { + // Find metadata for current class + const currentMetadata = metadataStore.get(currentClass) + + if (currentMetadata) { + // Merge metadata with existing result (don't override existing entries) + const classMetadata = currentMetadata + for (const [methodName, metadata] of Object.entries(classMetadata)) { + if (!(methodName in result)) { + result[methodName] = { + ...metadata, + ...(currentClass.prototype as DeliberateAny)?.[methodName]?.[Arc4MethodConfigSymbol], + } + } + } + } + + // Move up the prototype chain + currentClass = Object.getPrototypeOf(currentClass) } - const contractClass = contract.constructor as { new (): T } - const s = Object.getOwnPropertySymbols(contractClass).find((s) => s.toString() === AbiMetaSymbol.toString()) - const metadatas: Record = ( - s ? (contractClass as DeliberateAny)[s] : AbiMetaSymbol in contractClass ? contractClass[AbiMetaSymbol] : {} - ) as Record - return metadatas + + return result } -export const getContractMethodAbiMetadata = (contract: T, methodName: string): AbiMetadata => { +export const getContractMethodAbiMetadata = (contract: T, methodName: string): AbiMetadata => { const metadatas = getContractAbiMetadata(contract) return metadatas[methodName] } @@ -73,7 +65,7 @@ export const getArc4Signature = (metadata: AbiMetadata): string => { if (metadata.methodSignature === undefined) { const argTypes = metadata.argTypes.map((t) => JSON.parse(t) as TypeInfo).map(getArc4TypeName) const returnType = getArc4TypeName(JSON.parse(metadata.returnType) as TypeInfo) - metadata.methodSignature = `${metadata.methodName}(${argTypes.join(',')})${returnType}` + metadata.methodSignature = `${metadata.name ?? metadata.methodName}(${argTypes.join(',')})${returnType}` } return metadata.methodSignature } diff --git a/src/impl/contract.ts b/src/impl/contract.ts index 8988c6d..f6e3768 100644 --- a/src/impl/contract.ts +++ b/src/impl/contract.ts @@ -1,10 +1,7 @@ -import type { arc4, bytes } from '@algorandfoundation/algorand-typescript' -import { encodingUtil } from '@algorandfoundation/puya-ts' -import { captureMethodConfig } from '../abi-metadata' +import type { arc4 } from '@algorandfoundation/algorand-typescript' +import type { OnCompleteActionStr } from '@algorandfoundation/algorand-typescript/arc4' import type { DeliberateAny } from '../typescript-helpers' import { BaseContract } from './base-contract' -import { sha512_256 } from './crypto' -import { Bytes } from './primitives' export class Contract extends BaseContract { static isArc4 = true @@ -14,30 +11,29 @@ export class Contract extends BaseContract { } } +export const Arc4MethodConfigSymbol = Symbol('Arc4MethodConfig') export function abimethod(config?: arc4.AbiMethodConfig) { return function ( - target: (this: TContract, ...args: TArgs) => TReturn, - ctx: ClassMethodDecoratorContext, + target: { [Arc4MethodConfigSymbol]: arc4.AbiMethodConfig } & ((this: TContract, ...args: TArgs) => TReturn), ): (this: TContract, ...args: TArgs) => TReturn { - ctx.addInitializer(function () { - captureMethodConfig(this, target.name, config) - }) + target[Arc4MethodConfigSymbol] = { + ...config, + onCreate: config?.onCreate ?? 'disallow', + allowActions: ([] as OnCompleteActionStr[]).concat(config?.allowActions ?? 'NoOp'), + } return target } } export function baremethod(config?: arc4.BareMethodConfig) { return function ( - target: (this: TContract, ...args: TArgs) => TReturn, - ctx: ClassMethodDecoratorContext, + target: { [Arc4MethodConfigSymbol]: arc4.AbiMethodConfig } & ((this: TContract, ...args: TArgs) => TReturn), ): (this: TContract, ...args: TArgs) => TReturn { - ctx.addInitializer(function () { - captureMethodConfig(this, target.name, config) - }) + target[Arc4MethodConfigSymbol] = { + ...config, + onCreate: config?.onCreate ?? 'disallow', + allowActions: ([] as OnCompleteActionStr[]).concat(config?.allowActions ?? 'NoOp'), + } return target } } - -export const methodSelector: typeof arc4.methodSelector = (methodSignature: string): bytes => { - return sha512_256(Bytes(encodingUtil.utf8ToUint8Array(methodSignature))).slice(0, 4) -} diff --git a/src/impl/encoded-types.ts b/src/impl/encoded-types.ts index 2b7b9ae..a7f52ee 100644 --- a/src/impl/encoded-types.ts +++ b/src/impl/encoded-types.ts @@ -346,7 +346,7 @@ export class StaticArrayImpl constructor(typeInfo: TypeInfo | string, ...items: TItem[] & { length: TLength }) constructor(typeInfo: TypeInfo | string, ...items: TItem[]) constructor(typeInfo: TypeInfo | string, ...items: TItem[] & { length: TLength }) { - super(...items) + super(...(items as DeliberateAny)) this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo this.genericArgs = this.typeInfo.genericArgs as StaticArrayGenericArgs @@ -536,7 +536,7 @@ export class DynamicArrayImpl extends DynamicArray( + methodSignature: Parameters[0], + contract?: TContract, +): bytes => { + if (typeof methodSignature === 'string') { + return sha512_256(Bytes(encodingUtil.utf8ToUint8Array(methodSignature))).slice(0, 4) + } else { + const abiMetadata = getContractMethodAbiMetadata(contract!, methodSignature.name) + return Bytes(getArc4Selector(abiMetadata)) + } +} diff --git a/src/impl/transactions.ts b/src/impl/transactions.ts index 55cd9bb..dc007a3 100644 --- a/src/impl/transactions.ts +++ b/src/impl/transactions.ts @@ -243,10 +243,11 @@ export class ApplicationTransaction extends TransactionBase implements gtxn.Appl #approvalProgramPages: Array #clearStateProgramPages: Array #appLogs: Array + #appId: ApplicationType protected constructor(fields: ApplicationTransactionFields) { super(fields) - this.appId = fields.appId ?? Application() + this.#appId = fields.appId ?? Application() this.onCompletion = fields.onCompletion ?? 'NoOp' this.globalNumUint = fields.globalNumUint ?? Uint64(0) this.globalNumBytes = fields.globalNumBytes ?? Uint64(0) @@ -264,7 +265,20 @@ export class ApplicationTransaction extends TransactionBase implements gtxn.Appl Object.entries(fields.scratchSpace ?? {}).forEach(([k, v]) => this.setScratchSlot(Number(k), v)) } - readonly appId: ApplicationType + get backingAppId(): ApplicationType { + return this.#appId + } + + get appId(): ApplicationType { + if (asNumber(this.#appId.id) === 0) { + return this.#appId + } + const appData = lazyContext.getApplicationData(this.#appId.id) + if (appData && appData.isCreating) { + return Application(0) + } + return this.#appId + } readonly onCompletion: arc4.OnCompleteActionStr readonly globalNumUint: uint64 readonly globalNumBytes: uint64 diff --git a/src/internal/arc4.ts b/src/internal/arc4.ts index 1a80311..6edbc3f 100644 --- a/src/internal/arc4.ts +++ b/src/internal/arc4.ts @@ -1,2 +1,3 @@ export * from '@algorandfoundation/algorand-typescript/arc4' -export { abimethod, baremethod, Contract, methodSelector } from '../impl/contract' +export { abimethod, baremethod, Contract } from '../impl/contract' +export { methodSelector } from '../impl/method-selector' diff --git a/src/subcontexts/contract-context.ts b/src/subcontexts/contract-context.ts index 0b0223c..f53e053 100644 --- a/src/subcontexts/contract-context.ts +++ b/src/subcontexts/contract-context.ts @@ -1,13 +1,15 @@ -import type { Account, Application, Asset, bytes, contract, LocalState } from '@algorandfoundation/algorand-typescript' +import type { Account, Application, Asset, contract, LocalState } from '@algorandfoundation/algorand-typescript' +import type { ARC4Encoded } from '@algorandfoundation/algorand-typescript/arc4' import type { AbiMetadata } from '../abi-metadata' -import { copyAbiMetadatas, getArc4Selector, getContractAbiMetadata, getContractMethodAbiMetadata, isContractProxy } from '../abi-metadata' +import { getArc4Selector, getContractAbiMetadata, getContractMethodAbiMetadata } from '../abi-metadata' import { BytesMap } from '../collections/custom-key-map' import { checkRoutingConditions } from '../context-helpers/context-util' import { lazyContext } from '../context-helpers/internal-context' -import { toBytes, type TypeInfo } from '../encoders' +import { type TypeInfo } from '../encoders' import { CodeError } from '../errors' import { BaseContract, ContractOptionsSymbol } from '../impl/base-contract' import { Contract } from '../impl/contract' +import { getArc4Encoded, UintNImpl } from '../impl/encoded-types' import { Bytes } from '../impl/primitives' import { AccountCls, ApplicationCls, AssetCls } from '../impl/reference' import { BoxCls, BoxMapCls, BoxRefCls, GlobalStateCls } from '../impl/state' @@ -22,7 +24,6 @@ import { } from '../impl/transactions' import { getGenericTypeInfo } from '../runtime-helpers' import type { DeliberateAny, IConstructor } from '../typescript-helpers' - type ContractOptionsParameter = Parameters[0] type StateTotals = Pick @@ -80,28 +81,43 @@ const extractStates = (contract: BaseContract, contractOptions: ContractOptionsP return states } +const getUintN8Impl = (value: number) => new UintNImpl({ name: 'UintN<8>', genericArgs: [{ name: '8' }] }, value) + const extractArraysFromArgs = (app: Application, methodSelector: Uint8Array, args: DeliberateAny[]) => { const transactions: Transaction[] = [] - const accounts: Account[] = [] + const accounts: Account[] = [lazyContext.defaultSender] const apps: Application[] = [app] const assets: Asset[] = [] - const appArgs: bytes[] = [] + let appArgs: ARC4Encoded[] = [] for (const arg of args) { if (isTransaction(arg)) { transactions.push(arg) } else if (arg instanceof AccountCls) { - appArgs.push(toBytes(accounts.length)) + appArgs.push(getUintN8Impl(accounts.length)) accounts.push(arg as Account) } else if (arg instanceof ApplicationCls) { - appArgs.push(toBytes(apps.length)) + appArgs.push(getUintN8Impl(apps.length)) apps.push(arg as Application) } else if (arg instanceof AssetCls) { - appArgs.push(toBytes(assets.length)) + appArgs.push(getUintN8Impl(assets.length)) assets.push(arg as Asset) + } else { + appArgs.push(arg) } } - return { accounts, apps, assets, transactions, appArgs: [Bytes(methodSelector), ...appArgs] } + + if (appArgs.length > 15) { + const packed = getArc4Encoded(appArgs.slice(14)) + appArgs = [...appArgs.slice(0, 14), packed] + } + return { + accounts, + apps, + assets, + transactions, + appArgs: [Bytes(methodSelector), ...appArgs.filter((a) => a !== undefined).map((a) => a.bytes)], + } } function isTransaction(obj: unknown): obj is Transaction { @@ -213,14 +229,12 @@ export class ContractContext { lazyContext.txn.ensureScope([txn]).execute(() => { t = new target(...args) }) - appData.isCreating = hasCreateMethods(t!) + appData.isCreating = isArc4 && hasCreateMethods(t! as Contract) const instance = new Proxy(t!, { get(target, prop, receiver) { - if (prop === isContractProxy) { - return true - } const orig = Reflect.get(target, prop, receiver) - const abiMetadata = getContractMethodAbiMetadata(target, prop as string) + const abiMetadata = + isArc4 && typeof orig === 'function' ? getContractMethodAbiMetadata(target as Contract, orig.name) : undefined const isProgramMethod = prop === 'approvalProgram' || prop === 'clearStateProgram' const isAbiMethod = isArc4 && abiMetadata if (isAbiMethod || isProgramMethod) { @@ -245,8 +259,6 @@ export class ContractContext { onConstructed(application, instance, getContractOptions(t!)) - copyAbiMetadatas(t!, instance) - return instance }, } @@ -258,7 +270,7 @@ const getContractOptions = (contract: BaseContract): ContractOptionsParameter | return contractClass[ContractOptionsSymbol] as ContractOptionsParameter } -const hasCreateMethods = (contract: BaseContract) => { +const hasCreateMethods = (contract: Contract) => { const metadatas = getContractAbiMetadata(contract) return Object.values(metadatas).some((metadata) => (metadata.onCreate ?? 'disallow') !== 'disallow') } diff --git a/src/subcontexts/ledger-context.ts b/src/subcontexts/ledger-context.ts index 311f52d..f44447a 100644 --- a/src/subcontexts/ledger-context.ts +++ b/src/subcontexts/ledger-context.ts @@ -55,13 +55,9 @@ export class LedgerContext { * Retrieves an account by address. * @param address - The account address. * @returns The account. - * @throws If the account is unknown. */ - getAccount(address: AccountType): AccountType { - if (this.accountDataMap.has(address)) { - return new AccountCls(address.bytes) - } - throw new InternalError('Unknown account, check correct testing context is active') + getAccount(address: AccountType | StubBytesCompat): AccountType { + return new AccountCls(address instanceof AccountCls ? address.bytes : asBytes(address as StubBytesCompat)) } /** diff --git a/src/subcontexts/transaction-context.ts b/src/subcontexts/transaction-context.ts index 17fabfe..17b130b 100644 --- a/src/subcontexts/transaction-context.ts +++ b/src/subcontexts/transaction-context.ts @@ -1,7 +1,6 @@ import type { bytes, Contract, uint64 } from '@algorandfoundation/algorand-typescript' import { TransactionType } from '@algorandfoundation/algorand-typescript' -import type { AbiMetadata } from '../abi-metadata' -import { getContractMethodAbiMetadata } from '../abi-metadata' +import { getContractAbiMetadata, type AbiMetadata } from '../abi-metadata' import { TRANSACTION_GROUP_MAX_SIZE } from '../constants' import { checkRoutingConditions } from '../context-helpers/context-util' import { lazyContext } from '../context-helpers/internal-context' @@ -93,8 +92,18 @@ export class TransactionContext { group: Array>, activeTransactionIndex?: number, ): ExecutionScope { + let activeIndex = activeTransactionIndex const transactions = group.map((t) => (t instanceof DeferredAppCall ? t.txns : [t])).flat() - const transactionGroup = new TransactionGroup(transactions, activeTransactionIndex) + if (activeIndex === undefined) { + const lastAppCall = group + .filter((t) => t instanceof DeferredAppCall) + .at(-1) + ?.txns.at(-1) + if (lastAppCall) { + activeIndex = transactions.indexOf(lastAppCall) + } + } + const transactionGroup = new TransactionGroup(transactions, activeIndex) this.#activeGroup = transactionGroup @@ -192,7 +201,7 @@ export class TransactionContext { ...args: TParams ): DeferredAppCall { const appId = lazyContext.ledger.getApplicationForContract(contract) - const abiMetadata = getContractMethodAbiMetadata(contract, methodName as string) + const abiMetadata = getContractAbiMetadata(contract)[methodName as string] const txns = ContractContext.createMethodCallTxns(contract, abiMetadata, ...args) return new DeferredAppCall(appId.id, txns, method, abiMetadata, args) } @@ -252,11 +261,12 @@ export class TransactionGroup { * @throws If there are no transactions in the group or the active transaction is not an application call. */ get activeApplicationId() { + // this should return the true app_id and not 0 if the app is in the creation phase if (this.transactions.length === 0) { throw new InternalError('No transactions in the group') } testInvariant(this.activeTransaction.type === TransactionType.ApplicationCall, 'No app_id found in the active transaction') - return this.activeTransaction.appId.id + return (this.activeTransaction as ApplicationTransaction).backingAppId.id } /* @internal */ diff --git a/src/test-transformer/node-factory.ts b/src/test-transformer/node-factory.ts index 5e51fa7..708c3fb 100644 --- a/src/test-transformer/node-factory.ts +++ b/src/test-transformer/node-factory.ts @@ -107,4 +107,16 @@ export const nodeFactory = { [typeInfoArg, ...(node.arguments ?? [])].filter((arg) => !!arg), ) }, + + callMethodSelectorFunction(node: ts.CallExpression) { + 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 node + }, } satisfies Record ts.Node> diff --git a/src/test-transformer/visitors.ts b/src/test-transformer/visitors.ts index 806f0c0..38424d7 100644 --- a/src/test-transformer/visitors.ts +++ b/src/test-transformer/visitors.ts @@ -162,13 +162,17 @@ class ExpressionVisitor { let infoArg = info if (isCallingEmit(stubbedFunctionName)) { infoArg = this.helper.resolveTypeParameters(updatedNode).map(getGenericTypeInfo)[0] - } - if (isCallingDecodeArc4(stubbedFunctionName)) { + } else if (isCallingDecodeArc4(stubbedFunctionName)) { const targetType = ptypes.ptypeToArc4EncodedType(type, this.helper.sourceLocation(node)) const targetTypeInfo = getGenericTypeInfo(targetType) infoArg = targetTypeInfo } - updatedNode = stubbedFunctionName ? nodeFactory.callStubbedFunction(stubbedFunctionName, updatedNode, infoArg) : updatedNode + + updatedNode = stubbedFunctionName + ? isCallingMethodSelector(stubbedFunctionName) + ? nodeFactory.callMethodSelectorFunction(updatedNode) + : nodeFactory.callStubbedFunction(stubbedFunctionName, updatedNode, infoArg) + : updatedNode } return needsToCaptureTypeInfo ? nodeFactory.captureGenericTypeInfo(ts.visitEachChild(updatedNode, this.visit, this.context), JSON.stringify(info)) @@ -204,7 +208,6 @@ class FunctionOrMethodVisitor { constructor( protected context: ts.TransformationContext, protected helper: VisitorHelper, - private isFunction?: boolean, ) {} protected visit = (node: ts.Node): ts.Node => { return ts.visitEachChild(this.updateNode(node), this.visit, this.context) @@ -279,7 +282,7 @@ class FunctionLikeDecVisitor extends FunctionOrMethodVisitor { helper: VisitorHelper, private funcNode: ts.SignatureDeclaration, ) { - super(context, helper, true) + super(context, helper) } public result(): ts.SignatureDeclaration { @@ -417,9 +420,10 @@ const tryGetStubbedFunctionName = (node: ts.CallExpression, helper: VisitorHelpe if (sourceFileName && !algotsModulePaths.some((s) => sourceFileName.includes(s))) return undefined } const functionName = functionSymbol?.getName() ?? identityExpression.text - const stubbedFunctionNames = ['interpretAsArc4', 'decodeArc4', 'encodeArc4', 'emit'] + const stubbedFunctionNames = ['interpretAsArc4', 'decodeArc4', 'encodeArc4', 'emit', 'methodSelector'] return stubbedFunctionNames.includes(functionName) ? functionName : undefined } const isCallingDecodeArc4 = (functionName: string | undefined): boolean => ['decodeArc4', 'encodeArc4'].includes(functionName ?? '') const isCallingEmit = (functionName: string | undefined): boolean => 'emit' === (functionName ?? '') +const isCallingMethodSelector = (functionName: string | undefined): boolean => 'methodSelector' === (functionName ?? '') diff --git a/tests/arc4/dynamic-array.spec.ts b/tests/arc4/dynamic-array.spec.ts index 4336d79..e470cc0 100644 --- a/tests/arc4/dynamic-array.spec.ts +++ b/tests/arc4/dynamic-array.spec.ts @@ -233,12 +233,14 @@ const uint256DynamicArrayOfStaticArray = { return [uint256DynamicArray.nativeValues(), uint256DynamicArray.nativeValues().reverse()] }, abiValues() { - return this.nativeValues().map((a) => new StaticArray, 10>(...a.map((v) => new UintN<256>(v)))) + return this.nativeValues().map((a) => new StaticArray, 10>(...(a.map((v) => new UintN<256>(v)) as []))) }, array(isEmpty = false) { return isEmpty ? new DynamicArray, 10>>() - : new DynamicArray, 10>>(...this.abiValues().map((a) => new StaticArray, 10>(...a))) + : new DynamicArray, 10>>( + ...this.abiValues().map((a) => new StaticArray, 10>(...(a as DeliberateAny))), + ) }, create(value: StubBytesCompat) { return interpretAsArc4, 10>>>(asBytes(value)) @@ -328,7 +330,7 @@ const tupleDynamicArray = { addressDynamicArray.abiValues()[5], ), boolDynamicArray.abiValues()[3], - new StaticArray, 3>(...uint256DynamicArray.abiValues().slice(4, 7)), + new StaticArray, 3>(...(uint256DynamicArray.abiValues().slice(4, 7) as [])), ], ), ) diff --git a/tests/arc4/method-selector.spec.ts b/tests/arc4/method-selector.spec.ts new file mode 100644 index 0000000..6c68df6 --- /dev/null +++ b/tests/arc4/method-selector.spec.ts @@ -0,0 +1,307 @@ +import { AlgoAmount } from '@algorandfoundation/algokit-utils/types/amount' +import type { gtxn } from '@algorandfoundation/algorand-typescript' +import { arc4, Bytes, Global, Uint64 } from '@algorandfoundation/algorand-typescript' +import { TestExecutionContext } from '@algorandfoundation/algorand-typescript-testing' +import { DynamicArray, methodSelector } from '@algorandfoundation/algorand-typescript/arc4' +import { encodingUtil } from '@algorandfoundation/puya-ts' +import { afterEach, beforeAll, describe, expect } from 'vitest' +import { AnotherStruct, MyStruct, SignaturesContract } from '../artifacts/arc4-abi-method/contract.algo' +import { getAvmResult } from '../avm-invoker' +import { createArc4TestFixture } from '../test-fixture' + +const _FUNDED_ACCOUNT_SPENDING = Uint64(1234) + +describe('methodSelector', async () => { + const ctx = new TestExecutionContext() + const [test, localnetFixture] = createArc4TestFixture('tests/artifacts/arc4-abi-method/contract.algo.ts', { + SignaturesContract: { + deployParams: { createParams: { extraProgramPages: undefined, method: 'create' } }, + funding: new AlgoAmount({ microAlgos: Global.minBalance + _FUNDED_ACCOUNT_SPENDING }), + }, + }) + + beforeAll(async () => { + await localnetFixture.newScope() + }) + + afterEach(() => { + ctx.reset() + }) + + test('app args is correct with simple args', async ({ appClientSignaturesContract: appClient }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + const arg1 = new arc4.Str('hello') + const arg2 = new arc4.DynamicArray(new arc4.UintN8(1), new arc4.UintN8(2)) + + // act + // ensure same execution in AVM runs without errors + await getAvmResult({ appClient }, 'sink', 'hello', [1, 2]) + // then run inside emulator + contract.sink(arg1, arg2) + + // assert + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .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)) + }) + + test('app args is correct with alias', async ({ appClientSignaturesContract: appClient }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + const arg1 = new arc4.Str('hello') + const arg2 = new arc4.DynamicArray(new arc4.UintN8(1), new arc4.UintN8(2)) + + // act + // ensure same execution in AVM runs without errors + await getAvmResult({ appClient }, 'alias', 'hello', [1, 2]) + // then run inside emulator + contract.sink2(arg1, arg2) + + // assert + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .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)) + }) + + test('app args is correct with txn', async ({ appClientSignaturesContract: appClient, algorand }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + + const arg1 = new arc4.Str('hello') + const arg3 = new arc4.DynamicArray(new arc4.UintN8(1), new arc4.UintN8(2)) + const localnetCreator = await algorand.account.localNetDispenser() + const paymentTxn = await algorand.createTransaction.payment({ + sender: localnetCreator, + receiver: localnetCreator, + amount: new AlgoAmount({ microAlgo: 123 }), + signer: algorand.account.getSigner(localnetCreator), + }) + + // act + await getAvmResult({ appClient }, 'withTxn', 'hello', paymentTxn, [1, 2]) + contract.withTxn(arg1, ctx.any.txn.payment({ amount: Uint64(123) }), arg3) + + // asset + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .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)) + }) + + test('app args is correct with asset', async ({ appClientSignaturesContract: appClient, algorand }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + + const arg1 = new arc4.Str('hello') + const arg3 = new arc4.DynamicArray(new arc4.UintN8(1), new arc4.UintN8(2)) + const localnetCreator = await algorand.account.localNetDispenser() + const asaId = ( + await algorand.send.assetCreate({ + sender: localnetCreator, + total: 123n, + }) + ).confirmation.assetIndex + + // act + await getAvmResult({ appClient }, 'withAsset', 'hello', asaId, [1, 2]) + contract.withAsset(arg1, ctx.any.asset({ total: 123 }), arg3) + + // assert + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .map((_, i) => txn.appArgs(i)) + + expect(appArgs).toEqual([ + appClient.getABIMethod('withAsset(string,asset,uint8[])void').getSelector(), + arg1.bytes, + Bytes.fromHex('00'), + arg3.bytes, + ]) + expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.withAsset)) + }) + + test('app args is correct with account', async ({ appClientSignaturesContract: appClient, algorand }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + const arg1 = new arc4.Str('hello') + const arg3 = new arc4.DynamicArray(new arc4.UintN8(1), new arc4.UintN8(2)) + + const account = algorand.account.random() + await algorand.account.ensureFundedFromEnvironment(account, new AlgoAmount({ microAlgo: _FUNDED_ACCOUNT_SPENDING })) + // ensure context has the same account with matching balance + ctx.any.account({ + address: Bytes(account.publicKey), + balance: Global.minBalance + _FUNDED_ACCOUNT_SPENDING, + }) + + // act + contract.withAcc(arg1, ctx.ledger.getAccount(Bytes(account.publicKey)), arg3) + await getAvmResult({ appClient }, 'withAcc', 'hello', account.publicKey, [1, 2]) + + // assert + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .map((_, i) => txn.appArgs(i)) + expect(appArgs).toEqual([ + appClient.getABIMethod('withAcc(string,account,uint8[])void').getSelector(), + arg1.bytes, + Bytes.fromHex('01'), + arg3.bytes, + ]) + expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.withAcc)) + }) + + test('app args is correct with application', async ({ appClientSignaturesContract: appClient, appFactorySignaturesContract }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + const arg1 = new arc4.Str('hello') + const arg4 = new arc4.DynamicArray(new arc4.UintN8(1), new arc4.UintN8(2)) + + const selfApp = ctx.ledger.getApplicationForContract(contract) + const otherApp = await appFactorySignaturesContract.send.create({ method: 'create' }) + const otherAppId = otherApp.appClient.appId + ctx.any.application({ applicationId: otherAppId }) + + // act + await getAvmResult({ appClient }, 'withApp', 'hello', otherAppId, otherAppId, [1, 2]) + contract.withApp(arg1, ctx.ledger.getApplication(otherAppId), new arc4.UintN64(otherAppId), arg4) + + // assert + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .map((_, i) => txn.appArgs(i)) + const appForeignApps = Array(Number(txn.numApps)) + .fill(0) + .map((_, i) => txn.apps(i)) + + expect(appArgs).toEqual([ + appClient.getABIMethod('withApp(string,application,uint64,uint8[])void').getSelector(), + arg1.bytes, + Bytes.fromHex('01'), // 0th index is the app being called + encodingUtil.bigIntToUint8Array(otherAppId, 8), // app id as bytes + arg4.bytes, + ]) + expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.withApp)) + expect(appForeignApps.map((a) => a.id)).toEqual([selfApp.id, otherAppId]) + }) + + test('app args is correct with complex', async ({ appClientSignaturesContract: appClient, algorand }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + + const avmAccount = algorand.account.random() + await algorand.account.ensureFundedFromEnvironment(avmAccount, new AlgoAmount({ microAlgo: _FUNDED_ACCOUNT_SPENDING })) + // ensure context has the same account with matching balance + const account = ctx.any.account({ + address: Bytes(avmAccount.publicKey), + balance: Global.minBalance + _FUNDED_ACCOUNT_SPENDING, + }) + + const payment = ctx.any.txn.payment() + const struct = new MyStruct({ + three: new arc4.UintN128(3), + four: new arc4.UintN128(4), + anotherStruct: new AnotherStruct({ one: new arc4.UintN64(1), two: new arc4.Str('2') }), + anotherStructAlias: new AnotherStruct({ one: new arc4.UintN64(1), two: new arc4.Str('2') }), + }) + const five = new DynamicArray(new arc4.UintN8(5)) + + // act + const result = contract.complexSig(struct, payment, account, five) + + // assert + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .map((_, i) => txn.appArgs(i)) + + expect(appArgs).toEqual([ + appClient + .getABIMethod( + 'complexSig(((uint64,string),(uint64,string),uint128,uint128),pay,account,uint8[])((uint64,string),((uint64,string),(uint64,string),uint128,uint128))', + ) + .getSelector(), + struct.bytes, + Bytes.fromHex('01'), // 0th index is the sender + five.bytes, + ]) + expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.complexSig)) + expect(result[0].bytes).toEqual(struct.anotherStruct.bytes) + expect(result[1].bytes).toEqual(struct.bytes) + }) + + test('prepare txns with complex', async ({ appClientSignaturesContract: appClient, algorand }) => { + // arrange + const contract = ctx.contract.create(SignaturesContract) + contract.create() + + const avmAccount = algorand.account.random() + await algorand.account.ensureFundedFromEnvironment(avmAccount, new AlgoAmount({ microAlgo: _FUNDED_ACCOUNT_SPENDING })) + // ensure context has the same account with matching balance + const account = ctx.any.account({ + address: Bytes(avmAccount.publicKey), + balance: Global.minBalance + _FUNDED_ACCOUNT_SPENDING, + }) + + const struct = new MyStruct({ + three: new arc4.UintN128(3), + four: new arc4.UintN128(4), + anotherStruct: new AnotherStruct({ one: new arc4.UintN64(1), two: new arc4.Str('2') }), + anotherStructAlias: new AnotherStruct({ one: new arc4.UintN64(1), two: new arc4.Str('2') }), + }) + const five = new DynamicArray(new arc4.UintN8(5)) + + const deferredAppCall = ctx.txn.deferAppCall(contract, contract.complexSig, 'complexSig', struct, ctx.any.txn.payment(), account, five) + const localnetCreator = await algorand.account.localNetDispenser() + const paymentTxn = await algorand.createTransaction.payment({ + sender: localnetCreator, + receiver: localnetCreator, + amount: new AlgoAmount({ microAlgo: 123 }), + signer: algorand.account.getSigner(localnetCreator), + }) + + // # act + await getAvmResult({ appClient }, 'complexSig', [[1, '2'], [1, '2'], 3, 4], paymentTxn, avmAccount.publicKey, [5]) + ctx.txn.createScope([ctx.any.txn.payment(), deferredAppCall, ctx.any.txn.payment()]).execute(() => { + const result = deferredAppCall.submit() + expect(result[0].bytes).toEqual(struct.anotherStruct.bytes) + expect(result[1].bytes).toEqual(struct.bytes) + }) + + // assert + const txn = ctx.txn.lastActive as gtxn.ApplicationTxn + const appArgs = Array(Number(txn.numAppArgs)) + .fill(0) + .map((_, i) => txn.appArgs(i)) + expect(appArgs).toEqual([ + appClient + .getABIMethod( + 'complexSig(((uint64,string),(uint64,string),uint128,uint128),pay,account,uint8[])((uint64,string),((uint64,string),(uint64,string),uint128,uint128))', + ) + .getSelector(), + struct.bytes, + Bytes.fromHex('01'), // 0th index is the sender + five.bytes, + ]) + expect(appArgs[0]).toEqual(methodSelector(SignaturesContract.prototype.complexSig)) + }) +}) diff --git a/tests/arc4/static-array.spec.ts b/tests/arc4/static-array.spec.ts index e4d304a..efcdea7 100644 --- a/tests/arc4/static-array.spec.ts +++ b/tests/arc4/static-array.spec.ts @@ -40,7 +40,7 @@ const addressStaticArray = { return this.nativeValues().map((v) => new Address(Bytes(v))) }, array() { - return new StaticArray(...this.abiValues()) + return new StaticArray(...(this.abiValues() as [])) }, create(value: StubBytesCompat) { return interpretAsArc4>(asBytes(value)) @@ -61,7 +61,7 @@ const boolStaticArray = { return this.nativeValues().map((v) => new Bool(v)) }, array() { - return new StaticArray(...this.abiValues()) + return new StaticArray(...(this.abiValues() as [])) }, create(value: StubBytesCompat) { return interpretAsArc4>(asBytes(value)) @@ -82,7 +82,7 @@ const uint256StaticArray = { return this.nativeValues().map((v) => new UintN<256>(v)) }, array() { - return new StaticArray, 10>(...this.abiValues()) + return new StaticArray, 10>(...(this.abiValues() as [])) }, create(value: StubBytesCompat) { return interpretAsArc4, 10>>(asBytes(value)) @@ -114,7 +114,7 @@ const ufixednxmStaticArray = { ] }, array() { - return new StaticArray, 10>(...this.abiValues()) + return new StaticArray, 10>(...(this.abiValues() as [])) }, create(value: StubBytesCompat) { return interpretAsArc4, 10>>(asBytes(value)) @@ -146,7 +146,7 @@ const stringStaticArray = { return this.nativeValues().map((v) => new Str(v)) }, array() { - return new StaticArray(...this.abiValues()) + return new StaticArray(...(this.abiValues() as [])) }, create(value: StubBytesCompat) { return interpretAsArc4>(asBytes(value)) @@ -164,10 +164,12 @@ const addressStaticArrayOfArray = { return [addressStaticArray.nativeValues(), addressStaticArray.nativeValues().reverse()] }, abiValues() { - return this.nativeValues().map((a) => new StaticArray(...a.map((v) => new Address(Bytes(v))))) + return this.nativeValues().map((a) => new StaticArray(...(a.map((v) => new Address(Bytes(v))) as []))) }, array() { - return new StaticArray, 2>(...this.abiValues().map((a) => new StaticArray(...a))) + return new StaticArray, 2>( + ...(this.abiValues().map((a) => new StaticArray(...(a as DeliberateAny))) as []), + ) }, create(value: StubBytesCompat) { return interpretAsArc4, 2>>(asBytes(value)) @@ -185,10 +187,12 @@ const boolStaticArrayOfArray = { return [boolStaticArray.nativeValues(), boolStaticArray.nativeValues().reverse()] }, abiValues() { - return this.nativeValues().map((a) => new StaticArray(...a.map((v) => new Bool(v)))) + return this.nativeValues().map((a) => new StaticArray(...(a.map((v) => new Bool(v)) as []))) }, array() { - return new StaticArray, 2>(...this.abiValues().map((a) => new StaticArray(...a))) + return new StaticArray, 2>( + ...(this.abiValues().map((a) => new StaticArray(...(a as DeliberateAny))) as []), + ) }, create(value: StubBytesCompat) { return interpretAsArc4, 2>>(asBytes(value)) @@ -206,10 +210,12 @@ const uint256StaticArrayOfArray = { return [uint256StaticArray.nativeValues(), uint256StaticArray.nativeValues().reverse()] }, abiValues() { - return this.nativeValues().map((a) => new StaticArray, 10>(...a.map((v) => new UintN<256>(v)))) + return this.nativeValues().map((a) => new StaticArray, 10>(...(a.map((v) => new UintN<256>(v)) as []))) }, array() { - return new StaticArray, 10>, 2>(...this.abiValues().map((a) => new StaticArray, 10>(...a))) + return new StaticArray, 10>, 2>( + ...(this.abiValues().map((a) => new StaticArray, 10>(...(a as DeliberateAny))) as []), + ) }, create(value: StubBytesCompat) { return interpretAsArc4, 10>, 2>>(asBytes(value)) @@ -230,7 +236,7 @@ const uint256StaticArrayOfDynamicArray = { return this.nativeValues().map((a) => new DynamicArray>(...a.map((v) => new UintN<256>(v)))) }, array() { - return new StaticArray>, 2>(...this.abiValues().map((a) => new DynamicArray>(...a))) + return new StaticArray>, 2>(...(this.abiValues().map((a) => new DynamicArray>(...a)) as [])) }, create(value: StubBytesCompat) { return interpretAsArc4>, 2>>(asBytes(value)) @@ -248,10 +254,12 @@ const stringStaticArrayOfArray = { return [stringStaticArray.nativeValues(), stringStaticArray.nativeValues().reverse()] }, abiValues() { - return this.nativeValues().map((a) => new StaticArray(...a.map((v) => new Str(v)))) + return this.nativeValues().map((a) => new StaticArray(...(a.map((v) => new Str(v)) as []))) }, array() { - return new StaticArray, 2>(...this.abiValues().map((a) => new StaticArray(...a))) + return new StaticArray, 2>( + ...(this.abiValues().map((a) => new StaticArray(...(a as DeliberateAny))) as []), + ) }, create(value: StubBytesCompat) { return interpretAsArc4, 2>>(asBytes(value)) @@ -273,12 +281,13 @@ const stringStaticArrayOfArrayOfArray = { }, abiValues() { return this.nativeValues().map( - (x) => new StaticArray, 3>(...x.map((y) => new StaticArray(...y.map((v) => new Str(v))))), + (x) => + new StaticArray, 3>(...(x.map((y) => new StaticArray(...(y.map((v) => new Str(v)) as []))) as [])), ) }, array() { return new StaticArray, 3>, 2>( - ...this.abiValues().map((x) => new StaticArray, 3>(...x)), + ...(this.abiValues().map((x) => new StaticArray, 3>(...(x as DeliberateAny))) as []), ) }, create(value: StubBytesCompat) { @@ -318,7 +327,7 @@ const tupleStaticArray = { addressStaticArray.abiValues()[5], ), boolStaticArray.abiValues()[3], - new StaticArray, 3>(...uint256StaticArray.abiValues().slice(4, 7)), + new StaticArray, 3>(...(uint256StaticArray.abiValues().slice(4, 7) as [])), ], ), ) @@ -327,7 +336,7 @@ const tupleStaticArray = { return new StaticArray< Tuple<[DynamicArray, Tuple<[DynamicArray, Str, UintN<256>, Address]>, Bool, StaticArray, 3>]>, 2 - >(...this.abiValues()) + >(...(this.abiValues() as [])) }, create(value: StubBytesCompat) { return interpretAsArc4< @@ -390,7 +399,7 @@ const structStaticArray = { ) }, array() { - return new StaticArray(...this.abiValues()) + return new StaticArray(...(this.abiValues() as [])) }, create(value: StubBytesCompat) { return interpretAsArc4>(asBytes(value)) diff --git a/tests/artifacts/arc4-abi-method/contract.algo.ts b/tests/artifacts/arc4-abi-method/contract.algo.ts new file mode 100644 index 0000000..e9bcdf2 --- /dev/null +++ b/tests/artifacts/arc4-abi-method/contract.algo.ts @@ -0,0 +1,104 @@ +type UInt8Array = arc4.DynamicArray +type MyAlias = arc4.UintN<128> + +import type { Account, Application, Asset } from '@algorandfoundation/algorand-typescript' +import { arc4, assert, gtxn, op, Txn } from '@algorandfoundation/algorand-typescript' + +export class AnotherStruct extends arc4.Struct<{ + one: arc4.UintN64 + two: arc4.Str +}> {} + +type MyStructAlias = AnotherStruct + +export class MyStruct extends arc4.Struct<{ + anotherStruct: AnotherStruct + anotherStructAlias: MyStructAlias + three: arc4.UintN128 + four: MyAlias +}> {} + +export class SignaturesContract extends arc4.Contract { + @arc4.abimethod({ onCreate: 'require' }) + create() { + const appTxn = gtxn.ApplicationTxn(0) + assert(op.Global.currentApplicationId.id !== 0, 'expected global to have app id') + assert(op.Global.currentApplicationAddress !== op.Global.zeroAddress, 'expected global to have app address') + assert(appTxn.appId.id === 0, 'expected txn to have 0') + assert(Txn.applicationId.id === 0, 'expected txn to have 0') + } + + @arc4.abimethod() + sink(value: arc4.Str, arr: UInt8Array) { + assert(value.native) + assert(arr.length) + } + + @arc4.abimethod({ name: 'alias' }) + sink2(value: arc4.Str, arr: UInt8Array) { + assert(value.native) + assert(arr.length) + } + + @arc4.abimethod() + withTxn(value: arc4.Str, pay: gtxn.PaymentTxn, arr: UInt8Array) { + assert(value.native) + assert(arr.length) + assert(pay.groupIndex === 0) + assert(Txn.groupIndex === 1) + assert(pay.amount === 123) + } + + @arc4.abimethod() + withAsset(value: arc4.Str, asset: Asset, arr: UInt8Array) { + assert(value.native) + assert(arr.length) + assert(asset.total === 123) + assert(Txn.assets(0) === asset) + } + + @arc4.abimethod() + withApp(value: arc4.Str, app: Application, appId: arc4.UintN64, arr: UInt8Array) { + assert(value.native) + assert(arr.length) + assert(app.id === appId.native, 'expected app id to match provided app id') + assert(app.creator === op.Global.creatorAddress, 'expected other app to have same creator') + const appTxn = gtxn.ApplicationTxn(0) + assert(appTxn.apps(0) === op.Global.currentApplicationId) + assert(Txn.applications(0) === op.Global.currentApplicationId) + assert(appTxn.apps(1) === app) + assert(Txn.applications(1) === app) + } + + @arc4.abimethod() + withAcc(value: arc4.Str, acc: Account, arr: UInt8Array) { + assert(value.native) + assert(arr.length) + assert(acc.balance === acc.minBalance + 1234) + assert(Txn.accounts(0) === Txn.sender) + assert(Txn.accounts(1) === acc) + } + + @arc4.abimethod() + complexSig(struct1: MyStruct, txn: gtxn.PaymentTxn, acc: Account, five: UInt8Array): readonly [MyStructAlias, MyStruct] { + assert(Txn.numAppArgs === 4) + + // struct + assert(struct1.anotherStruct.one.native === 1) + assert(struct1.anotherStruct.two.native === '2') + assert(struct1.anotherStructAlias.one.native === 1) + assert(struct1.anotherStructAlias.two.native === '2') + assert(struct1.three.native === 3n) + assert(struct1.four.native === 4n) + + // txn + assert(txn.groupIndex === Txn.groupIndex - 1) + + // acc + assert(Txn.applicationArgs(2) === new arc4.UintN8(1).bytes) // acc array ref + assert(acc.balance === acc.minBalance + 1234) + assert(five[0].native === 5) + + return [struct1.anotherStruct, struct1] + } +} diff --git a/tests/avm-invoker.ts b/tests/avm-invoker.ts index 8645f6a..3f76888 100644 --- a/tests/avm-invoker.ts +++ b/tests/avm-invoker.ts @@ -8,11 +8,13 @@ export type ABIValue = boolean | number | bigint | string | Uint8Array | ABIValu export const INITIAL_BALANCE_MICRO_ALGOS = Number(20e6) +type MethodArgs = Exclude[0]['args'], undefined> + const invokeMethod = async ( appClient: AppClient, method: string, sendParams?: Partial[0]>, - ...methodArgs: ABIValue[] + ...methodArgs: MethodArgs ): ReturnType => { const response = await appClient.send.call({ method, args: methodArgs, note: randomUUID(), ...sendParams }) return response @@ -21,7 +23,7 @@ const invokeMethod = async ( export const getAvmResult = async ( { appClient, sendParams }: { appClient: AppClient; sendParams?: Partial[0]> }, method: string, - ...methodArgs: ABIValue[] + ...methodArgs: MethodArgs ): Promise => { const result = await invokeMethod(appClient, method, sendParams, ...methodArgs) if (result.returns?.at(-1)?.decodeError) { @@ -33,7 +35,7 @@ export const getAvmResult = async ( export const getAvmResultLog = async ( { appClient, sendParams }: { appClient: AppClient; sendParams?: Partial[0]> }, method: string, - ...methodArgs: ABIValue[] + ...methodArgs: MethodArgs ): Promise => { const result = await invokeMethod(appClient, method, sendParams, ...methodArgs) return result?.confirmation?.logs @@ -42,7 +44,7 @@ export const getAvmResultLog = async ( export const getAvmResultRaw = async ( { appClient, sendParams }: { appClient: AppClient; sendParams?: Partial[0]> }, method: string, - ...methodArgs: ABIValue[] + ...methodArgs: MethodArgs ): Promise => { const result = await invokeMethod(appClient, method, sendParams, ...methodArgs) return result?.returns?.at(-1)?.rawReturnValue diff --git a/tests/state-op-codes.spec.ts b/tests/state-op-codes.spec.ts index 7015045..e072ff7 100644 --- a/tests/state-op-codes.spec.ts +++ b/tests/state-op-codes.spec.ts @@ -458,10 +458,10 @@ describe('State op codes', async () => { test('should be able to invoke demo contract', async () => { const contract = ctx.contract.create(ItxnDemoContract) - ctx.txn.createScope([ctx.any.txn.applicationCall({ appArgs: [Bytes('test1')] })]).execute(() => { + ctx.txn.createScope([ctx.any.txn.applicationCall({ appId: contract, appArgs: [Bytes('test1')] })]).execute(() => { contract.approvalProgram() }) - ctx.txn.createScope([ctx.any.txn.applicationCall({ appArgs: [Bytes('test2')] })]).execute(() => { + ctx.txn.createScope([ctx.any.txn.applicationCall({ appId: contract, appArgs: [Bytes('test2')] })]).execute(() => { contract.approvalProgram() }) }) diff --git a/tests/test-fixture.ts b/tests/test-fixture.ts index 35c3d72..601c0f0 100644 --- a/tests/test-fixture.ts +++ b/tests/test-fixture.ts @@ -1,6 +1,7 @@ import type { AlgorandClient } from '@algorandfoundation/algokit-utils' import { Config, microAlgos } from '@algorandfoundation/algokit-utils' import { algorandFixture } from '@algorandfoundation/algokit-utils/testing' +import type { AlgoAmount } from '@algorandfoundation/algokit-utils/types/amount' import type { SendAppTransactionResult } from '@algorandfoundation/algokit-utils/types/app' import type { Arc56Contract } from '@algorandfoundation/algokit-utils/types/app-arc56' import type { AppClient } from '@algorandfoundation/algokit-utils/types/app-client' @@ -139,6 +140,7 @@ type Arc4FixtureContextFor = { type ContractConfig = { deployParams?: AppFactoryDeployParams + funding?: AlgoAmount } export function createArc4TestFixture( @@ -203,6 +205,7 @@ export function createArc4TestFixture( appSpec: appSpec!, }) const { appClient } = await appFactory.deploy(config.deployParams ?? {}) + if (config.funding) await appClient.fundAppAccount({ amount: config.funding }) await use(appClient) } } @@ -248,10 +251,9 @@ async function compilePath( outputDestructuredIr: false, outputMemoryIr: false, - matchAlgodBytecode: false, debugLevel: 1, targetAvmVersion: 10, - cliTemplateDefinitions: [], + cliTemplateDefinitions: {}, templateVarsPrefix: 'TMPL_', localsCoalescingStrategy: 'root_operand' as Parameters[0]['localsCoalescingStrategy'],