@algorandfoundation/algorand-typescript-testing 1.0.0-alpha.11 → 1.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abi-metadata.d.ts +6 -2
- package/context-helpers/context-util.d.ts +3 -0
- package/context-helpers/internal-context.d.ts +2 -2
- package/impl/encoded-types.d.ts +11 -1
- package/impl/inner-transactions.d.ts +2 -2
- package/impl/transactions.d.ts +1 -1
- package/index.mjs +85 -31
- package/index.mjs.map +1 -1
- package/package.json +3 -3
- package/{runtime-helpers-DlIX78iw.js → runtime-helpers-D6TF197l.js} +141 -49
- package/runtime-helpers-D6TF197l.js.map +1 -0
- package/runtime-helpers.mjs +1 -1
- package/subcontexts/contract-context.d.ts +2 -1
- package/subcontexts/transaction-context.d.ts +7 -3
- package/test-execution-context.d.ts +1 -1
- package/test-transformer/index.mjs +7 -6
- package/test-transformer/index.mjs.map +1 -1
- package/test-transformer/node-factory.d.ts +1 -1
- package/util.d.ts +1 -1
- package/runtime-helpers-DlIX78iw.js.map +0 -1
package/abi-metadata.d.ts
CHANGED
|
@@ -2,15 +2,19 @@ import { BaseContract, Contract } from '@algorandfoundation/algorand-typescript'
|
|
|
2
2
|
import { AbiMethodConfig, BareMethodConfig, CreateOptions, OnCompleteActionStr } from '@algorandfoundation/algorand-typescript/arc4';
|
|
3
3
|
export interface AbiMetadata {
|
|
4
4
|
methodName: string;
|
|
5
|
-
|
|
5
|
+
methodSignature: string | undefined;
|
|
6
6
|
argTypes: string[];
|
|
7
7
|
returnType: string;
|
|
8
8
|
onCreate?: CreateOptions;
|
|
9
9
|
allowActions?: OnCompleteActionStr[];
|
|
10
10
|
}
|
|
11
|
+
export declare const isContractProxy: unique symbol;
|
|
11
12
|
export declare const attachAbiMetadata: (contract: {
|
|
12
13
|
new (): Contract;
|
|
13
14
|
}, methodName: string, metadata: AbiMetadata) => void;
|
|
15
|
+
export declare const copyAbiMetadatas: <T extends BaseContract>(sourceContract: T, targetContract: T) => void;
|
|
14
16
|
export declare const captureMethodConfig: <T extends Contract>(contract: T, methodName: string, config?: AbiMethodConfig<T> | BareMethodConfig) => void;
|
|
15
17
|
export declare const hasAbiMetadata: <T extends Contract>(contract: T) => boolean;
|
|
16
|
-
export declare const
|
|
18
|
+
export declare const getContractAbiMetadata: <T extends BaseContract>(contract: T) => Record<string, AbiMetadata>;
|
|
19
|
+
export declare const getContractMethodAbiMetadata: <T extends BaseContract>(contract: T, methodName: string) => AbiMetadata;
|
|
20
|
+
export declare const getArc4Signature: (metadata: AbiMetadata) => string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Account, internal } from '@algorandfoundation/algorand-typescript';
|
|
1
|
+
import { Account, BaseContract, internal } from '@algorandfoundation/algorand-typescript';
|
|
2
2
|
import { AccountData } from '../impl/account';
|
|
3
3
|
import { ApplicationData } from '../impl/application';
|
|
4
4
|
import { AssetData } from '../impl/asset';
|
|
@@ -20,7 +20,7 @@ declare class InternalContext {
|
|
|
20
20
|
get activeGroup(): TransactionGroup;
|
|
21
21
|
getAccountData(account: Account): AccountData;
|
|
22
22
|
getAssetData(id: internal.primitives.StubUint64Compat): AssetData;
|
|
23
|
-
getApplicationData(id: internal.primitives.StubUint64Compat): ApplicationData;
|
|
23
|
+
getApplicationData(id: internal.primitives.StubUint64Compat | BaseContract): ApplicationData;
|
|
24
24
|
}
|
|
25
25
|
export declare const lazyContext: InternalContext;
|
|
26
26
|
export {};
|
package/impl/encoded-types.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export declare class UintNImpl<N extends BitSize> extends UintN<N> {
|
|
|
13
13
|
equals(other: this): boolean;
|
|
14
14
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): UintNImpl<BitSize>;
|
|
15
15
|
static getMaxBitsLength(typeInfo: TypeInfo): BitSize;
|
|
16
|
+
static getArc4TypeName: (t: TypeInfo) => string;
|
|
16
17
|
}
|
|
17
18
|
export declare class UFixedNxMImpl<N extends BitSize, M extends number> extends UFixedNxM<N, M> {
|
|
18
19
|
private value;
|
|
@@ -25,6 +26,7 @@ export declare class UFixedNxMImpl<N extends BitSize, M extends number> extends
|
|
|
25
26
|
equals(other: this): boolean;
|
|
26
27
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): UFixedNxM<BitSize, number>;
|
|
27
28
|
static getMaxBitsLength(typeInfo: TypeInfo): BitSize;
|
|
29
|
+
static getArc4TypeName: (t: TypeInfo) => string;
|
|
28
30
|
}
|
|
29
31
|
export declare class ByteImpl extends Byte {
|
|
30
32
|
private value;
|
|
@@ -73,6 +75,7 @@ export declare class StaticArrayImpl<TItem extends ARC4Encoded, TLength extends
|
|
|
73
75
|
copy(): StaticArrayImpl<TItem, TLength>;
|
|
74
76
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): StaticArrayImpl<ARC4Encoded, number>;
|
|
75
77
|
static getMaxBytesLength(typeInfo: TypeInfo): number;
|
|
78
|
+
static getArc4TypeName: (t: TypeInfo) => string;
|
|
76
79
|
}
|
|
77
80
|
export declare class AddressImpl extends Address {
|
|
78
81
|
private typeInfo;
|
|
@@ -105,6 +108,7 @@ export declare class DynamicArrayImpl<TItem extends ARC4Encoded> extends Dynamic
|
|
|
105
108
|
push(...values: TItem[]): void;
|
|
106
109
|
pop(): TItem;
|
|
107
110
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): DynamicArrayImpl<ARC4Encoded>;
|
|
111
|
+
static getArc4TypeName: (t: TypeInfo) => string;
|
|
108
112
|
private encodeWithLength;
|
|
109
113
|
}
|
|
110
114
|
export declare class TupleImpl<TTuple extends [ARC4Encoded, ...ARC4Encoded[]]> extends Tuple<TTuple> {
|
|
@@ -121,10 +125,12 @@ export declare class TupleImpl<TTuple extends [ARC4Encoded, ...ARC4Encoded[]]> e
|
|
|
121
125
|
private get items();
|
|
122
126
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): TupleImpl<[ARC4Encoded, ...ARC4Encoded[]]>;
|
|
123
127
|
static getMaxBytesLength(typeInfo: TypeInfo): number;
|
|
128
|
+
static getArc4TypeName: (t: TypeInfo) => string;
|
|
124
129
|
}
|
|
125
130
|
type StructConstraint = Record<string, ARC4Encoded>;
|
|
126
|
-
declare const StructImpl_base:
|
|
131
|
+
declare const StructImpl_base: DeliberateAny;
|
|
127
132
|
export declare class StructImpl<T extends StructConstraint> extends StructImpl_base {
|
|
133
|
+
static [x: string]: any;
|
|
128
134
|
private uint8ArrayValue?;
|
|
129
135
|
private typeInfo;
|
|
130
136
|
genericArgs: Record<string, TypeInfo>;
|
|
@@ -133,6 +139,7 @@ export declare class StructImpl<T extends StructConstraint> extends StructImpl_b
|
|
|
133
139
|
get items(): T;
|
|
134
140
|
private decodeAsProperties;
|
|
135
141
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): StructImpl<StructConstraint>;
|
|
142
|
+
static getArc4TypeName: (t: TypeInfo) => string;
|
|
136
143
|
}
|
|
137
144
|
export declare class DynamicBytesImpl extends DynamicBytes {
|
|
138
145
|
private typeInfo;
|
|
@@ -145,6 +152,7 @@ export declare class DynamicBytesImpl extends DynamicBytes {
|
|
|
145
152
|
get items(): ByteImpl[];
|
|
146
153
|
setItem(_index: number, _value: ByteImpl): void;
|
|
147
154
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): DynamicBytesImpl;
|
|
155
|
+
static getArc4TypeName: (_t: TypeInfo) => string;
|
|
148
156
|
}
|
|
149
157
|
export declare class StaticBytesImpl extends StaticBytes {
|
|
150
158
|
private value;
|
|
@@ -158,8 +166,10 @@ export declare class StaticBytesImpl extends StaticBytes {
|
|
|
158
166
|
setItem(_index: number, _value: ByteImpl): void;
|
|
159
167
|
static fromBytesImpl(value: internal.primitives.StubBytesCompat | Uint8Array, typeInfo: string | TypeInfo, prefix?: 'none' | 'log'): StaticBytesImpl;
|
|
160
168
|
static getMaxBytesLength(typeInfo: TypeInfo): number;
|
|
169
|
+
static getArc4TypeName: (t: TypeInfo) => string;
|
|
161
170
|
}
|
|
162
171
|
export declare function interpretAsArc4Impl<T extends ARC4Encoded>(typeInfoString: string, bytes: internal.primitives.StubBytesCompat, prefix?: 'none' | 'log'): T;
|
|
163
172
|
export declare const arc4Encoders: Record<string, fromBytes<DeliberateAny>>;
|
|
164
173
|
export declare const getArc4Encoder: <T>(typeInfo: TypeInfo, encoders?: Record<string, fromBytes<DeliberateAny>>) => fromBytes<T>;
|
|
174
|
+
export declare const getArc4TypeName: (typeInfo: TypeInfo) => string | undefined;
|
|
165
175
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { arc4, itxn, TransactionType, uint64 } from '@algorandfoundation/algorand-typescript';
|
|
2
|
-
import { ApplicationTransaction, AssetConfigTransaction, AssetFreezeTransaction, AssetTransferTransaction, KeyRegistrationTransaction, PaymentTransaction } from './transactions';
|
|
3
|
-
import { InnerTxn, InnerTxnFields } from './itxn';
|
|
4
2
|
import { Mutable } from '../typescript-helpers';
|
|
3
|
+
import { InnerTxn, InnerTxnFields } from './itxn';
|
|
4
|
+
import { ApplicationTransaction, AssetConfigTransaction, AssetFreezeTransaction, AssetTransferTransaction, KeyRegistrationTransaction, PaymentTransaction } from './transactions';
|
|
5
5
|
export declare class PaymentInnerTxn extends PaymentTransaction implements itxn.PaymentInnerTxn {
|
|
6
6
|
readonly isItxn?: true;
|
|
7
7
|
static create(fields: itxn.PaymentFields): PaymentInnerTxn;
|
package/impl/transactions.d.ts
CHANGED
|
@@ -91,7 +91,7 @@ export declare class AssetFreezeTransaction extends TransactionBase implements g
|
|
|
91
91
|
readonly typeBytes: bytes;
|
|
92
92
|
}
|
|
93
93
|
export type ApplicationTransactionFields = TxnFields<gtxn.ApplicationTxn> & Partial<{
|
|
94
|
-
appArgs: Array<
|
|
94
|
+
appArgs: Array<unknown>;
|
|
95
95
|
accounts: Array<Account>;
|
|
96
96
|
assets: Array<Asset>;
|
|
97
97
|
apps: Array<Application>;
|
package/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { internal, Bytes, Uint64, Account, arc4, Ecdsa, op, Base64, TransactionType, Asset, Application, BigUint,
|
|
2
|
-
import algosdk from 'algosdk';
|
|
3
|
-
import { a as asMaybeUint64Cls, b as asUint64, c as asBytes,
|
|
1
|
+
import { internal, BaseContract, Bytes, Uint64, Account, arc4, Ecdsa, op, Base64, TransactionType, Asset, Application, BigUint, Contract } from '@algorandfoundation/algorand-typescript';
|
|
2
|
+
import algosdk, { ABIMethod } from 'algosdk';
|
|
3
|
+
import { a as asMaybeUint64Cls, b as asUint64, c as asBytes, t as toBytes, d as asNumber, M as MAX_BOX_SIZE, e as asBytesCls, f as asUint8Array, g as conactUint8Arrays, L as LOGIC_DATA_PREFIX, h as asBigInt, i as getObjectReference, j as MIN_TXN_FEE, D as DEFAULT_ACCOUNT_MIN_BALANCE, k as DEFAULT_MAX_TXN_LIFE, Z as ZERO_ADDRESS, l as DEFAULT_ASSET_CREATE_MIN_BALANCE, m as DEFAULT_ASSET_OPT_IN_MIN_BALANCE, n as DEFAULT_GLOBAL_GENESIS_HASH, o as asUint64Cls, p as asMaybeBytesCls, q as asBigUint, B as BITS_IN_BYTE, r as MAX_BYTES_SIZE, s as MAX_UINT8, u as binaryStringToBytes, U as UINT64_SIZE, v as MAX_UINT64, w as Uint64BackedCls, A as ALWAYS_APPROVE_TEAL_PROGRAM, x as BytesBackedCls, y as combineIntoMaxBytePages, z as MAX_ITEMS_IN_LOG, C as ABI_RETURN_VALUE_LOG_PREFIX, E as getRandomBytes, F as getArc4Encoder, G as arc4Encoders, H as getGenericTypeInfo, I as getArc4Signature, J as isContractProxy, K as getContractMethodAbiMetadata, N as copyAbiMetadatas, O as getContractAbiMetadata, P as iterBigInt, Q as getRandomBigInt, R as captureMethodConfig } from './runtime-helpers-D6TF197l.js';
|
|
4
4
|
import { ec } from 'elliptic';
|
|
5
5
|
import { sha256 as sha256$1 } from 'js-sha256';
|
|
6
6
|
import { sha3_256 as sha3_256$1, keccak256 as keccak256$1 } from 'js-sha3';
|
|
@@ -57,7 +57,8 @@ class InternalContext {
|
|
|
57
57
|
return data;
|
|
58
58
|
}
|
|
59
59
|
getApplicationData(id) {
|
|
60
|
-
const
|
|
60
|
+
const uint64Id = id instanceof BaseContract ? this.ledger.getApplicationForContract(id).id : internal.primitives.Uint64Cls.fromCompat(id);
|
|
61
|
+
const data = this.ledger.applicationDataMap.get(uint64Id);
|
|
61
62
|
if (!data) {
|
|
62
63
|
throw internal.errors.internalError('Unknown application, check correct testing context is active');
|
|
63
64
|
}
|
|
@@ -221,7 +222,7 @@ const AppGlobal = {
|
|
|
221
222
|
if (!exists) {
|
|
222
223
|
return [Bytes(), false];
|
|
223
224
|
}
|
|
224
|
-
return [state.value, exists];
|
|
225
|
+
return [toBytes(state.value), exists];
|
|
225
226
|
},
|
|
226
227
|
getExUint64(a, b) {
|
|
227
228
|
const app = getApp(a);
|
|
@@ -263,7 +264,7 @@ const AppLocal = {
|
|
|
263
264
|
if (!exists) {
|
|
264
265
|
return [Bytes(), false];
|
|
265
266
|
}
|
|
266
|
-
return [state.value, exists];
|
|
267
|
+
return [toBytes(state.value), exists];
|
|
267
268
|
},
|
|
268
269
|
getExUint64: function (a, b, c) {
|
|
269
270
|
const app = getApp(b);
|
|
@@ -3145,7 +3146,7 @@ class ApplicationTransaction extends TransactionBase {
|
|
|
3145
3146
|
return this.#appLogs.at(-1) ?? lazyContext.getApplicationData(this.appId.id).appLogs.at(-1) ?? Bytes();
|
|
3146
3147
|
}
|
|
3147
3148
|
appArgs(index) {
|
|
3148
|
-
return this.#appArgs[asNumber(index)];
|
|
3149
|
+
return toBytes(this.#appArgs[asNumber(index)]);
|
|
3149
3150
|
}
|
|
3150
3151
|
accounts(index) {
|
|
3151
3152
|
return this.#accounts[asNumber(index)];
|
|
@@ -3295,7 +3296,7 @@ class ApplicationInnerTxn extends ApplicationTransaction {
|
|
|
3295
3296
|
approvalProgramPages: Array.isArray(approvalProgram) ? approvalProgram : undefined,
|
|
3296
3297
|
clearStateProgram: Array.isArray(clearStateProgram) ? undefined : clearStateProgram,
|
|
3297
3298
|
clearStateProgramPages: Array.isArray(clearStateProgram) ? clearStateProgram : undefined,
|
|
3298
|
-
appArgs: appArgs?.map((x) =>
|
|
3299
|
+
appArgs: appArgs?.map((x) => x),
|
|
3299
3300
|
accounts: accounts?.map((x) => x),
|
|
3300
3301
|
assets: assets?.map((x) => x),
|
|
3301
3302
|
apps: apps?.map((x) => x),
|
|
@@ -3755,12 +3756,27 @@ function BoxRef(options) {
|
|
|
3755
3756
|
return new BoxRefCls(options?.key);
|
|
3756
3757
|
}
|
|
3757
3758
|
|
|
3759
|
+
const checkRoutingConditions$1 = (appId, metadata) => {
|
|
3760
|
+
const appData = lazyContext.getApplicationData(appId);
|
|
3761
|
+
const isCreating = appData.isCreating;
|
|
3762
|
+
if (isCreating && metadata.onCreate === 'disallow') {
|
|
3763
|
+
throw new internal.errors.CodeError('method can not be called while creating');
|
|
3764
|
+
}
|
|
3765
|
+
if (!isCreating && metadata.onCreate === 'require') {
|
|
3766
|
+
throw new internal.errors.CodeError('method can only be called while creating');
|
|
3767
|
+
}
|
|
3768
|
+
const txn = lazyContext.activeGroup.activeTransaction;
|
|
3769
|
+
if (txn instanceof ApplicationTransaction && metadata.allowActions && !metadata.allowActions.includes(txn.onCompletion)) {
|
|
3770
|
+
throw new internal.errors.CodeError(`method can only be called with one of the following on_completion values: ${metadata.allowActions.join(', ')}`);
|
|
3771
|
+
}
|
|
3772
|
+
};
|
|
3773
|
+
|
|
3758
3774
|
const isUint64GenericType = (typeInfo) => {
|
|
3759
3775
|
if (!Array.isArray(typeInfo?.genericArgs) || !typeInfo?.genericArgs?.length)
|
|
3760
3776
|
return false;
|
|
3761
3777
|
return typeInfo.genericArgs.some((t) => t.name.toLocaleLowerCase() === 'uint64');
|
|
3762
3778
|
};
|
|
3763
|
-
const extractStates = (contract) => {
|
|
3779
|
+
const extractStates = (contract, contractOptions) => {
|
|
3764
3780
|
const stateTotals = { globalNumBytes: 0, globalNumUint: 0, localNumBytes: 0, localNumUint: 0 };
|
|
3765
3781
|
const states = {
|
|
3766
3782
|
globalStates: new BytesMap(),
|
|
@@ -3796,34 +3812,36 @@ const extractStates = (contract) => {
|
|
|
3796
3812
|
stateTotals.localNumBytes += isLocalState && !isUint64State ? 1 : 0;
|
|
3797
3813
|
}
|
|
3798
3814
|
});
|
|
3815
|
+
stateTotals.globalNumUint = contractOptions?.stateTotals?.globalUints ?? stateTotals.globalNumUint;
|
|
3816
|
+
stateTotals.globalNumBytes = contractOptions?.stateTotals?.globalBytes ?? stateTotals.globalNumBytes;
|
|
3817
|
+
stateTotals.localNumUint = contractOptions?.stateTotals?.localUints ?? stateTotals.localNumUint;
|
|
3818
|
+
stateTotals.localNumBytes = contractOptions?.stateTotals?.localBytes ?? stateTotals.localNumBytes;
|
|
3799
3819
|
return states;
|
|
3800
3820
|
};
|
|
3801
|
-
const extractArraysFromArgs = (app, args) => {
|
|
3821
|
+
const extractArraysFromArgs = (app, methodSelector, args) => {
|
|
3802
3822
|
const transactions = [];
|
|
3803
3823
|
const accounts = [];
|
|
3804
3824
|
const apps = [app];
|
|
3805
3825
|
const assets = [];
|
|
3806
3826
|
const appArgs = [];
|
|
3807
|
-
// TODO: replace `asUint64Cls(accounts.length).toBytes().asAlgoTs()` with `arc4.Uint8(account.length).toBytes().asAlgoTs()`
|
|
3808
3827
|
for (const arg of args) {
|
|
3809
3828
|
if (isTransaction(arg)) {
|
|
3810
3829
|
transactions.push(arg);
|
|
3811
3830
|
}
|
|
3812
3831
|
else if (arg instanceof AccountCls) {
|
|
3813
|
-
appArgs.push(
|
|
3832
|
+
appArgs.push(toBytes(accounts.length));
|
|
3814
3833
|
accounts.push(arg);
|
|
3815
3834
|
}
|
|
3816
3835
|
else if (arg instanceof ApplicationCls) {
|
|
3817
|
-
appArgs.push(
|
|
3836
|
+
appArgs.push(toBytes(apps.length));
|
|
3818
3837
|
apps.push(arg);
|
|
3819
3838
|
}
|
|
3820
3839
|
else if (arg instanceof AssetCls) {
|
|
3821
|
-
appArgs.push(
|
|
3840
|
+
appArgs.push(toBytes(assets.length));
|
|
3822
3841
|
assets.push(arg);
|
|
3823
3842
|
}
|
|
3824
3843
|
}
|
|
3825
|
-
|
|
3826
|
-
return { accounts, apps, assets, transactions, appArgs: [Bytes('method_selector'), ...appArgs] };
|
|
3844
|
+
return { accounts, apps, assets, transactions, appArgs: [Bytes(methodSelector), ...appArgs] };
|
|
3827
3845
|
};
|
|
3828
3846
|
function isTransaction(obj) {
|
|
3829
3847
|
return (obj instanceof PaymentTransaction ||
|
|
@@ -3838,10 +3856,10 @@ class ContractContext {
|
|
|
3838
3856
|
const proxy = new Proxy(type, this.getContractProxyHandler(this.isArc4(type)));
|
|
3839
3857
|
return new proxy(...args);
|
|
3840
3858
|
}
|
|
3841
|
-
static createMethodCallTxns(contract,
|
|
3842
|
-
const abiMetadata = getAbiMetadata(contract, method.name);
|
|
3859
|
+
static createMethodCallTxns(contract, abiMetadata, ...args) {
|
|
3843
3860
|
const app = lazyContext.ledger.getApplicationForContract(contract);
|
|
3844
|
-
const
|
|
3861
|
+
const methodSelector = abiMetadata ? ABIMethod.fromSignature(getArc4Signature(abiMetadata)).getSelector() : new Uint8Array();
|
|
3862
|
+
const { transactions, ...appCallArgs } = extractArraysFromArgs(app, methodSelector, args);
|
|
3845
3863
|
const appTxn = lazyContext.any.txn.applicationCall({
|
|
3846
3864
|
appId: app,
|
|
3847
3865
|
...appCallArgs,
|
|
@@ -3865,8 +3883,8 @@ class ContractContext {
|
|
|
3865
3883
|
return this.isArc4(proto);
|
|
3866
3884
|
}
|
|
3867
3885
|
getContractProxyHandler(isArc4) {
|
|
3868
|
-
const onConstructed = (application, instance) => {
|
|
3869
|
-
const states = extractStates(instance);
|
|
3886
|
+
const onConstructed = (application, instance, conrtactOptions) => {
|
|
3887
|
+
const states = extractStates(instance, conrtactOptions);
|
|
3870
3888
|
const applicationData = lazyContext.ledger.applicationDataMap.getOrFail(application.id);
|
|
3871
3889
|
applicationData.application = {
|
|
3872
3890
|
...applicationData.application,
|
|
@@ -3881,23 +3899,33 @@ class ContractContext {
|
|
|
3881
3899
|
let t = undefined;
|
|
3882
3900
|
const application = lazyContext.any.application();
|
|
3883
3901
|
const txn = lazyContext.any.txn.applicationCall({ appId: application });
|
|
3902
|
+
const appData = lazyContext.ledger.applicationDataMap.getOrFail(application.id);
|
|
3903
|
+
appData.isCreating = true;
|
|
3884
3904
|
lazyContext.txn.ensureScope([txn]).execute(() => {
|
|
3885
3905
|
t = new target(...args);
|
|
3886
3906
|
});
|
|
3907
|
+
appData.isCreating = hasCreateMethods(t);
|
|
3887
3908
|
const instance = new Proxy(t, {
|
|
3888
3909
|
get(target, prop, receiver) {
|
|
3910
|
+
if (prop === isContractProxy) {
|
|
3911
|
+
return true;
|
|
3912
|
+
}
|
|
3889
3913
|
const orig = Reflect.get(target, prop, receiver);
|
|
3890
|
-
const abiMetadata =
|
|
3914
|
+
const abiMetadata = getContractMethodAbiMetadata(target, prop);
|
|
3891
3915
|
const isProgramMethod = prop === 'approvalProgram' || prop === 'clearStateProgram';
|
|
3892
3916
|
const isAbiMethod = isArc4 && abiMetadata;
|
|
3893
3917
|
if (isAbiMethod || isProgramMethod) {
|
|
3894
3918
|
return (...args) => {
|
|
3895
|
-
const txns = ContractContext.createMethodCallTxns(receiver,
|
|
3919
|
+
const txns = ContractContext.createMethodCallTxns(receiver, abiMetadata, ...args);
|
|
3896
3920
|
return lazyContext.txn.ensureScope(txns).execute(() => {
|
|
3921
|
+
if (isAbiMethod) {
|
|
3922
|
+
checkRoutingConditions$1(application.id, abiMetadata);
|
|
3923
|
+
}
|
|
3897
3924
|
const returnValue = orig.apply(target, args);
|
|
3898
3925
|
if (!isProgramMethod && isAbiMethod && returnValue !== undefined) {
|
|
3899
3926
|
txns.at(-1).logArc4ReturnValue(returnValue);
|
|
3900
3927
|
}
|
|
3928
|
+
appData.isCreating = false;
|
|
3901
3929
|
return returnValue;
|
|
3902
3930
|
});
|
|
3903
3931
|
};
|
|
@@ -3905,12 +3933,21 @@ class ContractContext {
|
|
|
3905
3933
|
return orig;
|
|
3906
3934
|
},
|
|
3907
3935
|
});
|
|
3908
|
-
onConstructed(application, instance);
|
|
3936
|
+
onConstructed(application, instance, getContractOptions(t));
|
|
3937
|
+
copyAbiMetadatas(t, instance);
|
|
3909
3938
|
return instance;
|
|
3910
3939
|
},
|
|
3911
3940
|
};
|
|
3912
3941
|
}
|
|
3913
3942
|
}
|
|
3943
|
+
const getContractOptions = (contract) => {
|
|
3944
|
+
const contractClass = contract.constructor;
|
|
3945
|
+
return contractClass[internal.ContractOptionsSymbol];
|
|
3946
|
+
};
|
|
3947
|
+
const hasCreateMethods = (contract) => {
|
|
3948
|
+
const metadatas = getContractAbiMetadata(contract);
|
|
3949
|
+
return Object.values(metadatas).some((metadata) => (metadata.onCreate ?? 'disallow') !== 'disallow');
|
|
3950
|
+
};
|
|
3914
3951
|
|
|
3915
3952
|
class LedgerContext {
|
|
3916
3953
|
appIdIter = iterBigInt(1001n, MAX_UINT64);
|
|
@@ -4068,19 +4105,35 @@ function ScopeGenerator(dispose) {
|
|
|
4068
4105
|
},
|
|
4069
4106
|
};
|
|
4070
4107
|
}
|
|
4108
|
+
const checkRoutingConditions = (appId, metadata) => {
|
|
4109
|
+
const appData = lazyContext.getApplicationData(appId);
|
|
4110
|
+
const isCreating = appData.isCreating;
|
|
4111
|
+
if (isCreating && metadata.onCreate === 'disallow') {
|
|
4112
|
+
throw new internal.errors.CodeError('method can not be called while creating');
|
|
4113
|
+
}
|
|
4114
|
+
if (!isCreating && metadata.onCreate === 'require') {
|
|
4115
|
+
throw new internal.errors.CodeError('method can only be called while creating');
|
|
4116
|
+
}
|
|
4117
|
+
const txn = lazyContext.activeGroup.activeTransaction;
|
|
4118
|
+
if (txn instanceof ApplicationTransaction && metadata.allowActions && !metadata.allowActions.includes(txn.onCompletion)) {
|
|
4119
|
+
throw new internal.errors.CodeError(`method can only be called with one of the following on_completion values: ${metadata.allowActions.join(', ')}`);
|
|
4120
|
+
}
|
|
4121
|
+
};
|
|
4071
4122
|
class DeferredAppCall {
|
|
4072
4123
|
appId;
|
|
4073
4124
|
txns;
|
|
4074
4125
|
method;
|
|
4126
|
+
abiMetadata;
|
|
4075
4127
|
args;
|
|
4076
|
-
constructor(appId, txns, method, args) {
|
|
4128
|
+
constructor(appId, txns, method, abiMetadata, args) {
|
|
4077
4129
|
this.appId = appId;
|
|
4078
4130
|
this.txns = txns;
|
|
4079
4131
|
this.method = method;
|
|
4132
|
+
this.abiMetadata = abiMetadata;
|
|
4080
4133
|
this.args = args;
|
|
4081
4134
|
}
|
|
4082
4135
|
submit() {
|
|
4083
|
-
|
|
4136
|
+
checkRoutingConditions(this.appId, this.abiMetadata);
|
|
4084
4137
|
return this.method(...this.args);
|
|
4085
4138
|
}
|
|
4086
4139
|
}
|
|
@@ -4139,10 +4192,11 @@ class TransactionContext {
|
|
|
4139
4192
|
}
|
|
4140
4193
|
activeTransaction.appendLog(value);
|
|
4141
4194
|
}
|
|
4142
|
-
deferAppCall(contract, method, ...args) {
|
|
4195
|
+
deferAppCall(contract, method, methodName, ...args) {
|
|
4143
4196
|
const appId = lazyContext.ledger.getApplicationForContract(contract);
|
|
4144
|
-
const
|
|
4145
|
-
|
|
4197
|
+
const abiMetadata = getContractMethodAbiMetadata(contract, methodName);
|
|
4198
|
+
const txns = ContractContext.createMethodCallTxns(contract, abiMetadata, ...args);
|
|
4199
|
+
return new DeferredAppCall(appId.id, txns, method, abiMetadata, args);
|
|
4146
4200
|
}
|
|
4147
4201
|
exportLogs(appId, ...decoding) {
|
|
4148
4202
|
const transaction = this.lastGroup.transactions
|
|
@@ -4473,13 +4527,13 @@ class TestExecutionContext {
|
|
|
4473
4527
|
#txnContext;
|
|
4474
4528
|
#valueGenerator;
|
|
4475
4529
|
#defaultSender;
|
|
4476
|
-
constructor() {
|
|
4530
|
+
constructor(defaultSenderAddress) {
|
|
4477
4531
|
internal.ctxMgr.instance = this;
|
|
4478
4532
|
this.#contractContext = new ContractContext();
|
|
4479
4533
|
this.#ledgerContext = new LedgerContext();
|
|
4480
4534
|
this.#txnContext = new TransactionContext();
|
|
4481
4535
|
this.#valueGenerator = new ValueGenerator();
|
|
4482
|
-
this.#defaultSender = Account(Bytes.fromBase32(algosdk.generateAccount().addr));
|
|
4536
|
+
this.#defaultSender = Account(defaultSenderAddress ?? Bytes.fromBase32(algosdk.generateAccount().addr));
|
|
4483
4537
|
}
|
|
4484
4538
|
account(address) {
|
|
4485
4539
|
return new AccountCls(address);
|