@algorandfoundation/algorand-typescript-testing 1.0.0-alpha.10
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 +16 -0
- package/collections/custom-key-map.d.ts +29 -0
- package/constants.d.ts +27 -0
- package/context-helpers/internal-context.d.ts +26 -0
- package/decode-logs.d.ts +9 -0
- package/encoders.d.ts +9 -0
- package/errors.d.ts +5 -0
- package/impl/account.d.ts +32 -0
- package/impl/acct-params.d.ts +5 -0
- package/impl/app-global.d.ts +2 -0
- package/impl/app-local.d.ts +2 -0
- package/impl/app-params.d.ts +3 -0
- package/impl/application.d.ts +30 -0
- package/impl/asset-holding.d.ts +2 -0
- package/impl/asset-params.d.ts +3 -0
- package/impl/asset.d.ts +24 -0
- package/impl/base.d.ts +18 -0
- package/impl/block.d.ts +2 -0
- package/impl/box.d.ts +2 -0
- package/impl/crypto.d.ts +12 -0
- package/impl/encoded-types.d.ts +165 -0
- package/impl/global.d.ts +18 -0
- package/impl/gtxn.d.ts +2 -0
- package/impl/index.d.ts +15 -0
- package/impl/inner-transactions.d.ts +51 -0
- package/impl/itxn.d.ts +8 -0
- package/impl/pure.d.ts +32 -0
- package/impl/scratch.d.ts +4 -0
- package/impl/state.d.ts +103 -0
- package/impl/transactions.d.ts +140 -0
- package/impl/txn.d.ts +3 -0
- package/index.d.ts +1 -0
- package/index.mjs +4563 -0
- package/index.mjs.map +1 -0
- package/package.json +45 -0
- package/runtime-helpers-DlIX78iw.js +1426 -0
- package/runtime-helpers-DlIX78iw.js.map +1 -0
- package/runtime-helpers.d.ts +11 -0
- package/runtime-helpers.mjs +8 -0
- package/runtime-helpers.mjs.map +1 -0
- package/set-up.d.ts +11 -0
- package/subcontexts/contract-context.d.ts +9 -0
- package/subcontexts/ledger-context.d.ts +45 -0
- package/subcontexts/transaction-context.d.ts +67 -0
- package/test-execution-context.d.ts +53 -0
- package/test-transformer/errors.d.ts +3 -0
- package/test-transformer/helpers.d.ts +3 -0
- package/test-transformer/index.d.ts +6 -0
- package/test-transformer/index.mjs +458 -0
- package/test-transformer/index.mjs.map +1 -0
- package/test-transformer/node-factory.d.ts +14 -0
- package/test-transformer/supported-binary-op-string.d.ts +4 -0
- package/test-transformer/visitors.d.ts +11 -0
- package/typescript-helpers.d.ts +15 -0
- package/util.d.ts +29 -0
- package/value-generators/avm.d.ts +23 -0
- package/value-generators/index.d.ts +6 -0
- package/value-generators/txn.d.ts +10 -0
|
@@ -0,0 +1,1426 @@
|
|
|
1
|
+
import { Bytes, internal, Uint64, Account } from '@algorandfoundation/algorand-typescript';
|
|
2
|
+
import { UintN, UFixedNxM, Byte, Str, Bool, StaticArray, Address, DynamicArray, Tuple, Struct, DynamicBytes, StaticBytes, ARC4Encoded } from '@algorandfoundation/algorand-typescript/arc4';
|
|
3
|
+
import { randomBytes } from 'crypto';
|
|
4
|
+
import { encodingUtil } from '@algorandfoundation/puya-ts';
|
|
5
|
+
import { decodeAddress } from 'algosdk';
|
|
6
|
+
import assert from 'assert';
|
|
7
|
+
|
|
8
|
+
const AbiMetaSymbol = Symbol('AbiMetadata');
|
|
9
|
+
const attachAbiMetadata = (contract, methodName, metadata) => {
|
|
10
|
+
const metadatas = (AbiMetaSymbol in contract ? contract[AbiMetaSymbol] : {});
|
|
11
|
+
metadatas[methodName] = metadata;
|
|
12
|
+
if (!(AbiMetaSymbol in contract)) {
|
|
13
|
+
Object.defineProperty(contract, AbiMetaSymbol, {
|
|
14
|
+
value: metadatas,
|
|
15
|
+
writable: true,
|
|
16
|
+
enumerable: false,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const captureMethodConfig = (contract, methodName, config) => {
|
|
21
|
+
const metadata = ensureMetadata(contract, methodName);
|
|
22
|
+
metadata.onCreate = config?.onCreate ?? 'disallow';
|
|
23
|
+
metadata.allowActions = [].concat(config?.allowActions ?? 'NoOp');
|
|
24
|
+
};
|
|
25
|
+
const ensureMetadata = (contract, methodName) => {
|
|
26
|
+
if (!hasAbiMetadata(contract)) {
|
|
27
|
+
const contractClass = contract.constructor;
|
|
28
|
+
Object.getOwnPropertyNames(Object.getPrototypeOf(contract)).forEach((name) => {
|
|
29
|
+
attachAbiMetadata(contractClass, name, { methodName: name, methodSelector: name, argTypes: [], returnType: '' });
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return getAbiMetadata(contract, methodName);
|
|
33
|
+
};
|
|
34
|
+
const hasAbiMetadata = (contract) => {
|
|
35
|
+
const contractClass = contract.constructor;
|
|
36
|
+
return (Object.getOwnPropertySymbols(contractClass).some((s) => s.toString() === AbiMetaSymbol.toString()) || AbiMetaSymbol in contractClass);
|
|
37
|
+
};
|
|
38
|
+
const getAbiMetadata = (contract, methodName) => {
|
|
39
|
+
const contractClass = contract.constructor;
|
|
40
|
+
const s = Object.getOwnPropertySymbols(contractClass).find((s) => s.toString() === AbiMetaSymbol.toString());
|
|
41
|
+
const metadatas = (s ? contractClass[s] : AbiMetaSymbol in contractClass ? contractClass[AbiMetaSymbol] : {});
|
|
42
|
+
return metadatas[methodName];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const UINT64_SIZE = 64;
|
|
46
|
+
const UINT512_SIZE = 512;
|
|
47
|
+
const MAX_UINT8 = 2 ** 8 - 1;
|
|
48
|
+
const MAX_UINT64 = 2n ** 64n - 1n;
|
|
49
|
+
const MAX_UINT512 = 2n ** 512n - 1n;
|
|
50
|
+
const MAX_BYTES_SIZE = 4096;
|
|
51
|
+
const MAX_ITEMS_IN_LOG = 32;
|
|
52
|
+
const MAX_BOX_SIZE = 32768;
|
|
53
|
+
const BITS_IN_BYTE = 8;
|
|
54
|
+
const DEFAULT_ACCOUNT_MIN_BALANCE = 100_000;
|
|
55
|
+
const DEFAULT_MAX_TXN_LIFE = 1_000;
|
|
56
|
+
const DEFAULT_ASSET_CREATE_MIN_BALANCE = 1000_000;
|
|
57
|
+
const DEFAULT_ASSET_OPT_IN_MIN_BALANCE = 10_000;
|
|
58
|
+
// from python code: list(b"\x85Y\xb5\x14x\xfd\x89\xc1vC\xd0]\x15\xa8\xaek\x10\xabG\xbbm\x8a1\x88\x11V\xe6\xbd;\xae\x95\xd1")
|
|
59
|
+
const DEFAULT_GLOBAL_GENESIS_HASH = Bytes(new Uint8Array([
|
|
60
|
+
133, 89, 181, 20, 120, 253, 137, 193, 118, 67, 208, 93, 21, 168, 174, 107, 16, 171, 71, 187, 109, 138, 49, 136, 17, 86, 230, 189, 59,
|
|
61
|
+
174, 149, 209,
|
|
62
|
+
]));
|
|
63
|
+
// algorand encoded address of 32 zero bytes
|
|
64
|
+
const ZERO_ADDRESS_B32 = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ';
|
|
65
|
+
const ZERO_ADDRESS = Bytes.fromBase32(ZERO_ADDRESS_B32);
|
|
66
|
+
/**
|
|
67
|
+
"\x09" # pragma version 9
|
|
68
|
+
"\x81\x01" # pushint 1
|
|
69
|
+
*/
|
|
70
|
+
const ALWAYS_APPROVE_TEAL_PROGRAM = Bytes(new Uint8Array([0x09, 0x81, 0x01]));
|
|
71
|
+
// bytes: program (logic) data prefix when signing
|
|
72
|
+
const LOGIC_DATA_PREFIX = Bytes('ProgData');
|
|
73
|
+
//number: minimum transaction fee
|
|
74
|
+
const MIN_TXN_FEE = 1000;
|
|
75
|
+
const ABI_RETURN_VALUE_LOG_PREFIX = Bytes.fromHex('151F7C75');
|
|
76
|
+
|
|
77
|
+
class BytesBackedCls {
|
|
78
|
+
#value;
|
|
79
|
+
// #typeInfo: GenericTypeInfo | undefined
|
|
80
|
+
get bytes() {
|
|
81
|
+
return this.#value;
|
|
82
|
+
}
|
|
83
|
+
constructor(value, _typeInfo) {
|
|
84
|
+
this.#value = value;
|
|
85
|
+
// this.#typeInfo = typeInfo
|
|
86
|
+
}
|
|
87
|
+
static fromBytes(value, typeInfo) {
|
|
88
|
+
return new this(internal.primitives.BytesCls.fromCompat(value).asAlgoTs(), typeInfo);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
class Uint64BackedCls {
|
|
92
|
+
#value;
|
|
93
|
+
get uint64() {
|
|
94
|
+
return this.#value;
|
|
95
|
+
}
|
|
96
|
+
constructor(value) {
|
|
97
|
+
this.#value = value;
|
|
98
|
+
}
|
|
99
|
+
static fromBytes(value) {
|
|
100
|
+
const uint8ArrayValue = value instanceof Uint8Array ? value : internal.primitives.BytesCls.fromCompat(value).asUint8Array();
|
|
101
|
+
const uint64Value = Uint64(encodingUtil.uint8ArrayToBigInt(uint8ArrayValue));
|
|
102
|
+
return new this(uint64Value);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const nameOfType = (x) => {
|
|
107
|
+
if (typeof x === 'object') {
|
|
108
|
+
if (x === null)
|
|
109
|
+
return 'Null';
|
|
110
|
+
if (x === undefined)
|
|
111
|
+
return 'undefined';
|
|
112
|
+
if ('constructor' in x) {
|
|
113
|
+
return x.constructor.name;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return typeof x;
|
|
117
|
+
};
|
|
118
|
+
function* iterBigInt(start, end) {
|
|
119
|
+
for (let i = start; i < end; i++) {
|
|
120
|
+
yield BigInt(i);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const asBigInt = (v) => asUint64Cls(v).asBigInt();
|
|
124
|
+
const asNumber = (v) => asUint64Cls(v).asNumber();
|
|
125
|
+
const asUint64Cls = (val) => internal.primitives.Uint64Cls.fromCompat(val);
|
|
126
|
+
const asBigUintCls = (val) => internal.primitives.BigUintCls.fromCompat(val);
|
|
127
|
+
const asBytesCls = (val) => internal.primitives.BytesCls.fromCompat(val);
|
|
128
|
+
const asUint64 = (val) => asUint64Cls(val).asAlgoTs();
|
|
129
|
+
const asBigUint = (val) => asBigUintCls(val).asAlgoTs();
|
|
130
|
+
const asBytes = (val) => asBytesCls(val).asAlgoTs();
|
|
131
|
+
const asUint8Array = (val) => asBytesCls(val).asUint8Array();
|
|
132
|
+
//TODO: handle arc4 types, bytes backed types
|
|
133
|
+
const toBytes = (val) => {
|
|
134
|
+
const uint64Val = asMaybeUint64Cls(val);
|
|
135
|
+
if (uint64Val !== undefined) {
|
|
136
|
+
return uint64Val.toBytes().asAlgoTs();
|
|
137
|
+
}
|
|
138
|
+
const bytesVal = asMaybeBytesCls(val);
|
|
139
|
+
if (bytesVal !== undefined) {
|
|
140
|
+
return bytesVal.asAlgoTs();
|
|
141
|
+
}
|
|
142
|
+
const bigUintVal = asMaybeBigUintCls(val);
|
|
143
|
+
if (bigUintVal !== undefined) {
|
|
144
|
+
return bigUintVal.toBytes().asAlgoTs();
|
|
145
|
+
}
|
|
146
|
+
if (val instanceof BytesBackedCls) {
|
|
147
|
+
return val.bytes;
|
|
148
|
+
}
|
|
149
|
+
if (val instanceof Uint64BackedCls) {
|
|
150
|
+
return asUint64Cls(val.uint64).toBytes().asAlgoTs();
|
|
151
|
+
}
|
|
152
|
+
if (Array.isArray(val)) {
|
|
153
|
+
// This hack handles tuples/arrays of uint64 only
|
|
154
|
+
return val.reduce((acc, cur) => {
|
|
155
|
+
const uint64Val = asMaybeUint64Cls(cur);
|
|
156
|
+
if (!uint64Val) {
|
|
157
|
+
// TODO: support ABI tuple encoding
|
|
158
|
+
// internal.errors.internalError(`ABI tuple encoding not supported: ${nameOfType(val)}`)
|
|
159
|
+
return acc.concat(Bytes());
|
|
160
|
+
}
|
|
161
|
+
return acc.concat(toBytes(cur));
|
|
162
|
+
}, Bytes());
|
|
163
|
+
}
|
|
164
|
+
internal.errors.internalError(`Invalid type for bytes: ${nameOfType(val)}`);
|
|
165
|
+
};
|
|
166
|
+
const asMaybeUint64Cls = (val) => {
|
|
167
|
+
try {
|
|
168
|
+
return internal.primitives.Uint64Cls.fromCompat(val);
|
|
169
|
+
}
|
|
170
|
+
catch (e) {
|
|
171
|
+
if (e instanceof internal.errors.InternalError) ;
|
|
172
|
+
else {
|
|
173
|
+
throw e;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return undefined;
|
|
177
|
+
};
|
|
178
|
+
const asMaybeBigUintCls = (val) => {
|
|
179
|
+
try {
|
|
180
|
+
return internal.primitives.BigUintCls.fromCompat(val);
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
if (e instanceof internal.errors.InternalError) ;
|
|
184
|
+
else {
|
|
185
|
+
throw e;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return undefined;
|
|
189
|
+
};
|
|
190
|
+
const asMaybeBytesCls = (val) => {
|
|
191
|
+
try {
|
|
192
|
+
return internal.primitives.BytesCls.fromCompat(val);
|
|
193
|
+
}
|
|
194
|
+
catch (e) {
|
|
195
|
+
if (e instanceof internal.errors.InternalError) ;
|
|
196
|
+
else {
|
|
197
|
+
throw e;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return undefined;
|
|
201
|
+
};
|
|
202
|
+
const binaryStringToBytes = (s) => internal.primitives.BytesCls.fromCompat(new Uint8Array(s.match(/.{1,8}/g).map((x) => parseInt(x, 2))));
|
|
203
|
+
const getRandomNumber = (min, max) => {
|
|
204
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
205
|
+
};
|
|
206
|
+
const getRandomBigInt = (min, max) => {
|
|
207
|
+
const bigIntMin = BigInt(min);
|
|
208
|
+
const bigIntMax = BigInt(max);
|
|
209
|
+
const randomValue = [...Array(UINT512_SIZE / BITS_IN_BYTE).keys()]
|
|
210
|
+
.map(() => getRandomNumber(0, MAX_UINT8))
|
|
211
|
+
.reduce((acc, x) => acc * 256n + BigInt(x), 0n);
|
|
212
|
+
return (randomValue % (bigIntMax - bigIntMin)) + bigIntMin;
|
|
213
|
+
};
|
|
214
|
+
const getRandomBytes = (length) => asBytesCls(Bytes(randomBytes(length)));
|
|
215
|
+
const ObjectReferenceSymbol = Symbol('ObjectReference');
|
|
216
|
+
const objectRefIter = iterBigInt(1001n, MAX_UINT512);
|
|
217
|
+
const getObjectReference = (obj) => {
|
|
218
|
+
const tryGetReference = (obj) => {
|
|
219
|
+
const s = Object.getOwnPropertySymbols(obj).find((s) => s.toString() === ObjectReferenceSymbol.toString());
|
|
220
|
+
return s ? obj[s] : ObjectReferenceSymbol in obj ? obj[ObjectReferenceSymbol] : undefined;
|
|
221
|
+
};
|
|
222
|
+
const existingRef = tryGetReference(obj);
|
|
223
|
+
if (existingRef !== undefined) {
|
|
224
|
+
return existingRef;
|
|
225
|
+
}
|
|
226
|
+
const ref = objectRefIter.next().value;
|
|
227
|
+
Object.defineProperty(obj, ObjectReferenceSymbol, {
|
|
228
|
+
value: ref,
|
|
229
|
+
enumerable: false,
|
|
230
|
+
writable: false,
|
|
231
|
+
});
|
|
232
|
+
return ref;
|
|
233
|
+
};
|
|
234
|
+
const combineIntoMaxBytePages = (pages) => {
|
|
235
|
+
const combined = pages.reduce((acc, x) => acc.concat(x), asBytesCls(''));
|
|
236
|
+
const totalPages = (asNumber(combined.length) + MAX_BYTES_SIZE - 1) / MAX_BYTES_SIZE;
|
|
237
|
+
const result = [];
|
|
238
|
+
for (let i = 0; i < totalPages; i++) {
|
|
239
|
+
const start = i * MAX_BYTES_SIZE;
|
|
240
|
+
const end = Math.min((i + 1) * MAX_BYTES_SIZE, asNumber(combined.length));
|
|
241
|
+
const page = combined.slice(start, end);
|
|
242
|
+
result.push(page.asAlgoTs());
|
|
243
|
+
}
|
|
244
|
+
return result;
|
|
245
|
+
};
|
|
246
|
+
const conactUint8Arrays = (...values) => {
|
|
247
|
+
const result = new Uint8Array(values.reduce((acc, value) => acc + value.length, 0));
|
|
248
|
+
let index = 0;
|
|
249
|
+
for (const value of values) {
|
|
250
|
+
result.set(value, index);
|
|
251
|
+
index += value.length;
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
};
|
|
255
|
+
const uint8ArrayToNumber = (value) => {
|
|
256
|
+
return value.reduce((acc, x) => acc * 256 + x, 0);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const ABI_LENGTH_SIZE = 2;
|
|
260
|
+
const maxBigIntValue = (bitSize) => 2n ** BigInt(bitSize) - 1n;
|
|
261
|
+
const maxBytesLength = (bitSize) => Math.floor(bitSize / BITS_IN_BYTE);
|
|
262
|
+
const encodeLength = (length) => new internal.primitives.BytesCls(encodingUtil.bigIntToUint8Array(BigInt(length), ABI_LENGTH_SIZE));
|
|
263
|
+
class UintNImpl extends UintN {
|
|
264
|
+
value;
|
|
265
|
+
bitSize;
|
|
266
|
+
typeInfo;
|
|
267
|
+
constructor(typeInfo, v) {
|
|
268
|
+
super();
|
|
269
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
270
|
+
this.bitSize = UintNImpl.getMaxBitsLength(this.typeInfo);
|
|
271
|
+
assert([8, 16, 32, 64, 128, 256, 512].includes(this.bitSize), `Invalid bit size ${this.bitSize}`);
|
|
272
|
+
const bigIntValue = asBigUintCls(v ?? 0n).valueOf();
|
|
273
|
+
const maxValue = maxBigIntValue(this.bitSize);
|
|
274
|
+
assert(bigIntValue <= maxValue, `expected value <= ${maxValue}, got: ${bigIntValue}`);
|
|
275
|
+
this.value = encodingUtil.bigIntToUint8Array(bigIntValue, maxBytesLength(this.bitSize));
|
|
276
|
+
}
|
|
277
|
+
get native() {
|
|
278
|
+
const bigIntValue = encodingUtil.uint8ArrayToBigInt(this.value);
|
|
279
|
+
return (this.bitSize <= UINT64_SIZE ? asUint64(bigIntValue) : asBigUint(bigIntValue));
|
|
280
|
+
}
|
|
281
|
+
get bytes() {
|
|
282
|
+
return Bytes(this.value);
|
|
283
|
+
}
|
|
284
|
+
equals(other) {
|
|
285
|
+
if (!(other instanceof UintNImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
286
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
287
|
+
}
|
|
288
|
+
return this.bytes.equals(other.bytes);
|
|
289
|
+
}
|
|
290
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
291
|
+
let bytesValue = asBytesCls(value);
|
|
292
|
+
if (prefix === 'log') {
|
|
293
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
294
|
+
bytesValue = bytesValue.slice(4);
|
|
295
|
+
}
|
|
296
|
+
const result = new UintNImpl(typeInfo);
|
|
297
|
+
result.value = asUint8Array(bytesValue);
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
300
|
+
static getMaxBitsLength(typeInfo) {
|
|
301
|
+
return parseInt(typeInfo.genericArgs[0].name, 10);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const regExpNxM = (maxPrecision) => new RegExp(`^\\d*\\.?\\d{0,${maxPrecision}}$`);
|
|
305
|
+
const trimTrailingDecimalZeros = (v) => v.replace(/(\d+\.\d*?)0+$/, '$1').replace(/\.$/, '');
|
|
306
|
+
class UFixedNxMImpl extends UFixedNxM {
|
|
307
|
+
value;
|
|
308
|
+
bitSize;
|
|
309
|
+
precision;
|
|
310
|
+
typeInfo;
|
|
311
|
+
constructor(typeInfo, v) {
|
|
312
|
+
super(v);
|
|
313
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
314
|
+
const genericArgs = this.typeInfo.genericArgs;
|
|
315
|
+
this.bitSize = UFixedNxMImpl.getMaxBitsLength(this.typeInfo);
|
|
316
|
+
this.precision = parseInt(genericArgs.m.name, 10);
|
|
317
|
+
const trimmedValue = trimTrailingDecimalZeros(v);
|
|
318
|
+
assert(regExpNxM(this.precision).test(trimmedValue), `expected positive decimal literal with max of ${this.precision} decimal places`);
|
|
319
|
+
const bigIntValue = BigInt(trimmedValue.replace('.', ''));
|
|
320
|
+
const maxValue = maxBigIntValue(this.bitSize);
|
|
321
|
+
assert(bigIntValue <= maxValue, `expected value <= ${maxValue}, got: ${bigIntValue}`);
|
|
322
|
+
this.value = encodingUtil.bigIntToUint8Array(bigIntValue, maxBytesLength(this.bitSize));
|
|
323
|
+
}
|
|
324
|
+
get native() {
|
|
325
|
+
const bigIntValue = encodingUtil.uint8ArrayToBigInt(this.value);
|
|
326
|
+
return (this.bitSize <= UINT64_SIZE ? asUint64(bigIntValue) : asBigUint(bigIntValue));
|
|
327
|
+
}
|
|
328
|
+
get bytes() {
|
|
329
|
+
return Bytes(this.value);
|
|
330
|
+
}
|
|
331
|
+
equals(other) {
|
|
332
|
+
if (!(other instanceof UFixedNxMImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
333
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
334
|
+
}
|
|
335
|
+
return this.bytes.equals(other.bytes);
|
|
336
|
+
}
|
|
337
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
338
|
+
let bytesValue = asBytesCls(value);
|
|
339
|
+
if (prefix === 'log') {
|
|
340
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
341
|
+
bytesValue = bytesValue.slice(4);
|
|
342
|
+
}
|
|
343
|
+
const result = new UFixedNxMImpl(typeInfo, '0.0');
|
|
344
|
+
result.value = asUint8Array(bytesValue);
|
|
345
|
+
return result;
|
|
346
|
+
}
|
|
347
|
+
static getMaxBitsLength(typeInfo) {
|
|
348
|
+
const genericArgs = typeInfo.genericArgs;
|
|
349
|
+
return parseInt(genericArgs.n.name, 10);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
class ByteImpl extends Byte {
|
|
353
|
+
value;
|
|
354
|
+
constructor(typeInfo, v) {
|
|
355
|
+
super(v);
|
|
356
|
+
this.value = new UintNImpl(typeInfo, v);
|
|
357
|
+
}
|
|
358
|
+
get native() {
|
|
359
|
+
return this.value.native;
|
|
360
|
+
}
|
|
361
|
+
get bytes() {
|
|
362
|
+
return this.value.bytes;
|
|
363
|
+
}
|
|
364
|
+
equals(other) {
|
|
365
|
+
if (!(other instanceof ByteImpl) || JSON.stringify(this.value.typeInfo) !== JSON.stringify(other.value.typeInfo)) {
|
|
366
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.value.typeInfo.name}, got ${other.value.typeInfo.name}`);
|
|
367
|
+
}
|
|
368
|
+
return this.bytes.equals(other.bytes);
|
|
369
|
+
}
|
|
370
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
371
|
+
const uintNValue = UintNImpl.fromBytesImpl(value, typeInfo, prefix);
|
|
372
|
+
const result = new ByteImpl(typeInfo);
|
|
373
|
+
result.value = uintNValue;
|
|
374
|
+
return result;
|
|
375
|
+
}
|
|
376
|
+
static getMaxBitsLength(typeInfo) {
|
|
377
|
+
return UintNImpl.getMaxBitsLength(typeInfo);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
class StrImpl extends Str {
|
|
381
|
+
value;
|
|
382
|
+
constructor(_typeInfo, s) {
|
|
383
|
+
super();
|
|
384
|
+
const bytesValue = asBytesCls(s ?? '');
|
|
385
|
+
const bytesLength = encodeLength(bytesValue.length.asNumber());
|
|
386
|
+
this.value = asUint8Array(bytesLength.concat(bytesValue));
|
|
387
|
+
}
|
|
388
|
+
get native() {
|
|
389
|
+
return encodingUtil.uint8ArrayToUtf8(this.value.slice(ABI_LENGTH_SIZE));
|
|
390
|
+
}
|
|
391
|
+
get bytes() {
|
|
392
|
+
return Bytes(this.value);
|
|
393
|
+
}
|
|
394
|
+
equals(other) {
|
|
395
|
+
if (!(other instanceof StrImpl)) {
|
|
396
|
+
throw new internal.errors.CodeError(`Expected expression of type Str, got ${other.constructor.name}`);
|
|
397
|
+
}
|
|
398
|
+
return this.bytes.equals(other.bytes);
|
|
399
|
+
}
|
|
400
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
401
|
+
let bytesValue = asBytesCls(value);
|
|
402
|
+
if (prefix === 'log') {
|
|
403
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
404
|
+
bytesValue = bytesValue.slice(4);
|
|
405
|
+
}
|
|
406
|
+
const result = new StrImpl(typeInfo);
|
|
407
|
+
result.value = asUint8Array(bytesValue);
|
|
408
|
+
return result;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
const TRUE_BIGINT_VALUE = 128n;
|
|
412
|
+
const FALSE_BIGINT_VALUE = 0n;
|
|
413
|
+
class BoolImpl extends Bool {
|
|
414
|
+
value;
|
|
415
|
+
constructor(_typeInfo, v) {
|
|
416
|
+
super(v);
|
|
417
|
+
this.value = encodingUtil.bigIntToUint8Array(v ? TRUE_BIGINT_VALUE : FALSE_BIGINT_VALUE, 1);
|
|
418
|
+
}
|
|
419
|
+
get native() {
|
|
420
|
+
return encodingUtil.uint8ArrayToBigInt(this.value) === TRUE_BIGINT_VALUE;
|
|
421
|
+
}
|
|
422
|
+
equals(other) {
|
|
423
|
+
if (!(other instanceof BoolImpl)) {
|
|
424
|
+
throw new internal.errors.CodeError(`Expected expression of type Bool, got ${other.constructor.name}`);
|
|
425
|
+
}
|
|
426
|
+
return this.bytes.equals(other.bytes);
|
|
427
|
+
}
|
|
428
|
+
get bytes() {
|
|
429
|
+
return Bytes(this.value);
|
|
430
|
+
}
|
|
431
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
432
|
+
let bytesValue = asBytesCls(value);
|
|
433
|
+
if (prefix === 'log') {
|
|
434
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
435
|
+
bytesValue = bytesValue.slice(4);
|
|
436
|
+
}
|
|
437
|
+
const result = new BoolImpl(typeInfo);
|
|
438
|
+
result.value = asUint8Array(bytesValue);
|
|
439
|
+
return result;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const areAllARC4Encoded = (items) => items.every((item) => item instanceof ARC4Encoded);
|
|
443
|
+
const checkItemTypeName = (type, value) => {
|
|
444
|
+
const typeName = trimGenericTypeName(type.name);
|
|
445
|
+
const validTypeNames = [typeName, `${typeName}Impl`];
|
|
446
|
+
assert(validTypeNames.includes(value.constructor.name), `item must be of type ${typeName}, not ${value.constructor.name}`);
|
|
447
|
+
};
|
|
448
|
+
const arrayProxyHandler = () => ({
|
|
449
|
+
get(target, prop) {
|
|
450
|
+
const idx = prop ? parseInt(prop.toString(), 10) : NaN;
|
|
451
|
+
if (!isNaN(idx)) {
|
|
452
|
+
if (idx < target.items.length)
|
|
453
|
+
return target.items[idx];
|
|
454
|
+
internal.errors.avmError('Index out of bounds');
|
|
455
|
+
}
|
|
456
|
+
else if (prop === Symbol.iterator) {
|
|
457
|
+
return target.items[Symbol.iterator].bind(target.items);
|
|
458
|
+
}
|
|
459
|
+
else if (prop === 'entries') {
|
|
460
|
+
return target.items.entries.bind(target.items);
|
|
461
|
+
}
|
|
462
|
+
else if (prop === 'at') {
|
|
463
|
+
return (index) => {
|
|
464
|
+
return internal.primitives.arrayUtil.arrayAt(target.items, index);
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
return Reflect.get(target, prop);
|
|
468
|
+
},
|
|
469
|
+
set(target, prop, value) {
|
|
470
|
+
const idx = prop ? parseInt(prop.toString(), 10) : NaN;
|
|
471
|
+
if (!isNaN(idx)) {
|
|
472
|
+
if (idx < target.items.length) {
|
|
473
|
+
target.setItem(idx, value);
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
internal.errors.avmError('Index out of bounds');
|
|
477
|
+
}
|
|
478
|
+
return Reflect.set(target, prop, value);
|
|
479
|
+
},
|
|
480
|
+
});
|
|
481
|
+
class StaticArrayImpl extends StaticArray {
|
|
482
|
+
value;
|
|
483
|
+
uint8ArrayValue;
|
|
484
|
+
typeInfo;
|
|
485
|
+
size;
|
|
486
|
+
genericArgs;
|
|
487
|
+
constructor(typeInfo, ...items) {
|
|
488
|
+
super(...items);
|
|
489
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
490
|
+
this.genericArgs = this.typeInfo.genericArgs;
|
|
491
|
+
this.size = parseInt(this.genericArgs.size.name, 10);
|
|
492
|
+
if (items.length && items.length !== this.size) {
|
|
493
|
+
throw new internal.errors.CodeError(`expected ${this.size} items, not ${items.length}`);
|
|
494
|
+
}
|
|
495
|
+
assert(areAllARC4Encoded(items), 'expected ARC4 type');
|
|
496
|
+
items.forEach((item) => {
|
|
497
|
+
checkItemTypeName(this.genericArgs.elementType, item);
|
|
498
|
+
});
|
|
499
|
+
this.value = items.length ? items : undefined;
|
|
500
|
+
return new Proxy(this, arrayProxyHandler());
|
|
501
|
+
}
|
|
502
|
+
get bytes() {
|
|
503
|
+
return Bytes(this.uint8ArrayValue ?? encode(this.items));
|
|
504
|
+
}
|
|
505
|
+
equals(other) {
|
|
506
|
+
if (!(other instanceof StaticArrayImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
507
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
508
|
+
}
|
|
509
|
+
return this.bytes.equals(other.bytes);
|
|
510
|
+
}
|
|
511
|
+
get length() {
|
|
512
|
+
return this.size;
|
|
513
|
+
}
|
|
514
|
+
get items() {
|
|
515
|
+
if (this.uint8ArrayValue) {
|
|
516
|
+
const childTypes = Array(this.size).fill(this.genericArgs.elementType);
|
|
517
|
+
this.value = decode(this.uint8ArrayValue, childTypes);
|
|
518
|
+
this.uint8ArrayValue = undefined;
|
|
519
|
+
return this.value;
|
|
520
|
+
}
|
|
521
|
+
else if (this.value) {
|
|
522
|
+
this.uint8ArrayValue = undefined;
|
|
523
|
+
return this.value;
|
|
524
|
+
}
|
|
525
|
+
throw new internal.errors.CodeError('value is not set');
|
|
526
|
+
}
|
|
527
|
+
setItem(index, value) {
|
|
528
|
+
this.items[index] = value;
|
|
529
|
+
}
|
|
530
|
+
copy() {
|
|
531
|
+
return StaticArrayImpl.fromBytesImpl(this.bytes, JSON.stringify(this.typeInfo));
|
|
532
|
+
}
|
|
533
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
534
|
+
let bytesValue = asBytesCls(value);
|
|
535
|
+
if (prefix === 'log') {
|
|
536
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
537
|
+
bytesValue = bytesValue.slice(4);
|
|
538
|
+
}
|
|
539
|
+
const result = new StaticArrayImpl(typeInfo);
|
|
540
|
+
result.uint8ArrayValue = asUint8Array(bytesValue);
|
|
541
|
+
return result;
|
|
542
|
+
}
|
|
543
|
+
static getMaxBytesLength(typeInfo) {
|
|
544
|
+
const genericArgs = typeInfo.genericArgs;
|
|
545
|
+
const arraySize = parseInt(genericArgs.size.name, 10);
|
|
546
|
+
const childTypes = Array(arraySize).fill(genericArgs.elementType);
|
|
547
|
+
let i = 0;
|
|
548
|
+
let size = 0;
|
|
549
|
+
if (genericArgs.elementType.name === 'Bool') {
|
|
550
|
+
while (i < childTypes.length) {
|
|
551
|
+
const after = findBoolTypes(childTypes, i, 1);
|
|
552
|
+
const boolNum = after + 1;
|
|
553
|
+
size += Math.floor(boolNum / BITS_IN_BYTE);
|
|
554
|
+
size += boolNum % BITS_IN_BYTE ? 1 : 0;
|
|
555
|
+
i += after + 1;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
size = getMaxLengthOfStaticContentType(genericArgs.elementType) * arraySize;
|
|
560
|
+
}
|
|
561
|
+
return size;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
class AddressImpl extends Address {
|
|
565
|
+
typeInfo;
|
|
566
|
+
value;
|
|
567
|
+
constructor(typeInfo, value) {
|
|
568
|
+
super(value);
|
|
569
|
+
let uint8ArrayValue;
|
|
570
|
+
if (value === undefined) {
|
|
571
|
+
uint8ArrayValue = new Uint8Array(32);
|
|
572
|
+
}
|
|
573
|
+
else if (typeof value === 'string') {
|
|
574
|
+
uint8ArrayValue = decodeAddress(value).publicKey;
|
|
575
|
+
}
|
|
576
|
+
else if (internal.primitives.isBytes(value)) {
|
|
577
|
+
uint8ArrayValue = internal.primitives.getUint8Array(value);
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
uint8ArrayValue = internal.primitives.getUint8Array(value.bytes);
|
|
581
|
+
}
|
|
582
|
+
internal.errors.avmInvariant(uint8ArrayValue.length === 32, 'Addresses should be 32 bytes');
|
|
583
|
+
this.value = StaticArrayImpl.fromBytesImpl(uint8ArrayValue, typeInfo);
|
|
584
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
585
|
+
return new Proxy(this, arrayProxyHandler());
|
|
586
|
+
}
|
|
587
|
+
get bytes() {
|
|
588
|
+
return this.value.bytes;
|
|
589
|
+
}
|
|
590
|
+
equals(other) {
|
|
591
|
+
if (!(other instanceof AddressImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
592
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
593
|
+
}
|
|
594
|
+
return this.bytes.equals(other.bytes);
|
|
595
|
+
}
|
|
596
|
+
get length() {
|
|
597
|
+
return 32;
|
|
598
|
+
}
|
|
599
|
+
get native() {
|
|
600
|
+
return Account(this.value.bytes);
|
|
601
|
+
}
|
|
602
|
+
get items() {
|
|
603
|
+
return this.value.items;
|
|
604
|
+
}
|
|
605
|
+
setItem(_index, _value) {
|
|
606
|
+
throw new internal.errors.CodeError('Address is immutable');
|
|
607
|
+
}
|
|
608
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
609
|
+
const staticArrayValue = StaticArrayImpl.fromBytesImpl(value, typeInfo, prefix);
|
|
610
|
+
const result = new AddressImpl(typeInfo);
|
|
611
|
+
result.value = staticArrayValue;
|
|
612
|
+
return result;
|
|
613
|
+
}
|
|
614
|
+
static getMaxBytesLength(typeInfo) {
|
|
615
|
+
return StaticArrayImpl.getMaxBytesLength(typeInfo);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
const readLength = (value) => {
|
|
619
|
+
const length = Number(encodingUtil.uint8ArrayToBigInt(value.slice(0, ABI_LENGTH_SIZE)));
|
|
620
|
+
const data = value.slice(ABI_LENGTH_SIZE);
|
|
621
|
+
return [length, data];
|
|
622
|
+
};
|
|
623
|
+
class DynamicArrayImpl extends DynamicArray {
|
|
624
|
+
value;
|
|
625
|
+
uint8ArrayValue;
|
|
626
|
+
typeInfo;
|
|
627
|
+
genericArgs;
|
|
628
|
+
constructor(typeInfo, ...items) {
|
|
629
|
+
super(...items);
|
|
630
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
631
|
+
this.genericArgs = this.typeInfo.genericArgs;
|
|
632
|
+
assert(areAllARC4Encoded(items), 'expected ARC4 type');
|
|
633
|
+
items.forEach((item) => {
|
|
634
|
+
checkItemTypeName(this.genericArgs.elementType, item);
|
|
635
|
+
});
|
|
636
|
+
this.value = items;
|
|
637
|
+
return new Proxy(this, arrayProxyHandler());
|
|
638
|
+
}
|
|
639
|
+
get bytes() {
|
|
640
|
+
return Bytes(this.uint8ArrayValue ?? this.encodeWithLength(this.items));
|
|
641
|
+
}
|
|
642
|
+
equals(other) {
|
|
643
|
+
if (!(other instanceof DynamicArrayImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
644
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
645
|
+
}
|
|
646
|
+
return this.bytes.equals(other.bytes);
|
|
647
|
+
}
|
|
648
|
+
get length() {
|
|
649
|
+
return this.items.length;
|
|
650
|
+
}
|
|
651
|
+
get items() {
|
|
652
|
+
if (this.uint8ArrayValue) {
|
|
653
|
+
const [length, data] = readLength(this.uint8ArrayValue);
|
|
654
|
+
const childTypes = Array(length).fill(this.genericArgs.elementType);
|
|
655
|
+
this.value = decode(data, childTypes);
|
|
656
|
+
this.uint8ArrayValue = undefined;
|
|
657
|
+
return this.value;
|
|
658
|
+
}
|
|
659
|
+
else if (this.value) {
|
|
660
|
+
this.uint8ArrayValue = undefined;
|
|
661
|
+
return this.value;
|
|
662
|
+
}
|
|
663
|
+
throw new internal.errors.CodeError('value is not set');
|
|
664
|
+
}
|
|
665
|
+
setItem(index, value) {
|
|
666
|
+
this.items[index] = value;
|
|
667
|
+
}
|
|
668
|
+
copy() {
|
|
669
|
+
return DynamicArrayImpl.fromBytesImpl(this.bytes, JSON.stringify(this.typeInfo));
|
|
670
|
+
}
|
|
671
|
+
push(...values) {
|
|
672
|
+
const items = this.items;
|
|
673
|
+
items.push(...values);
|
|
674
|
+
}
|
|
675
|
+
pop() {
|
|
676
|
+
const items = this.items;
|
|
677
|
+
const popped = items.pop();
|
|
678
|
+
if (popped === undefined)
|
|
679
|
+
internal.errors.avmError('The array is empty');
|
|
680
|
+
return popped;
|
|
681
|
+
}
|
|
682
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
683
|
+
let bytesValue = asBytesCls(value);
|
|
684
|
+
if (prefix === 'log') {
|
|
685
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
686
|
+
bytesValue = bytesValue.slice(4);
|
|
687
|
+
}
|
|
688
|
+
const result = new DynamicArrayImpl(typeInfo);
|
|
689
|
+
result.uint8ArrayValue = asUint8Array(bytesValue);
|
|
690
|
+
return result;
|
|
691
|
+
}
|
|
692
|
+
encodeWithLength(items) {
|
|
693
|
+
return conactUint8Arrays(encodeLength(items.length).asUint8Array(), encode(items));
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
class TupleImpl extends Tuple {
|
|
697
|
+
value;
|
|
698
|
+
uint8ArrayValue;
|
|
699
|
+
typeInfo;
|
|
700
|
+
genericArgs;
|
|
701
|
+
constructor(typeInfo, ...items) {
|
|
702
|
+
super(...items);
|
|
703
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
704
|
+
this.genericArgs = Object.values(this.typeInfo.genericArgs);
|
|
705
|
+
assert(areAllARC4Encoded(items), 'expected ARC4 type');
|
|
706
|
+
items.forEach((item, index) => {
|
|
707
|
+
checkItemTypeName(this.genericArgs[index], item);
|
|
708
|
+
});
|
|
709
|
+
this.value = items.length ? items : undefined;
|
|
710
|
+
}
|
|
711
|
+
get bytes() {
|
|
712
|
+
return Bytes(this.uint8ArrayValue ?? encode(this.items));
|
|
713
|
+
}
|
|
714
|
+
equals(other) {
|
|
715
|
+
if (!(other instanceof TupleImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
716
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
717
|
+
}
|
|
718
|
+
return this.bytes.equals(other.bytes);
|
|
719
|
+
}
|
|
720
|
+
get length() {
|
|
721
|
+
return this.items.length;
|
|
722
|
+
}
|
|
723
|
+
get native() {
|
|
724
|
+
return this.items;
|
|
725
|
+
}
|
|
726
|
+
at(index) {
|
|
727
|
+
return this.items[index];
|
|
728
|
+
}
|
|
729
|
+
get items() {
|
|
730
|
+
if (this.uint8ArrayValue) {
|
|
731
|
+
this.value = decode(this.uint8ArrayValue, this.genericArgs);
|
|
732
|
+
this.uint8ArrayValue = undefined;
|
|
733
|
+
return this.value;
|
|
734
|
+
}
|
|
735
|
+
else if (this.value) {
|
|
736
|
+
this.uint8ArrayValue = undefined;
|
|
737
|
+
return this.value;
|
|
738
|
+
}
|
|
739
|
+
throw new internal.errors.CodeError('value is not set');
|
|
740
|
+
}
|
|
741
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
742
|
+
let bytesValue = asBytesCls(value);
|
|
743
|
+
if (prefix === 'log') {
|
|
744
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
745
|
+
bytesValue = bytesValue.slice(4);
|
|
746
|
+
}
|
|
747
|
+
const result = new TupleImpl(typeInfo);
|
|
748
|
+
result.uint8ArrayValue = asUint8Array(bytesValue);
|
|
749
|
+
return result;
|
|
750
|
+
}
|
|
751
|
+
static getMaxBytesLength(typeInfo) {
|
|
752
|
+
const genericArgs = Object.values(typeInfo.genericArgs);
|
|
753
|
+
let i = 0;
|
|
754
|
+
let size = 0;
|
|
755
|
+
while (i < genericArgs.length) {
|
|
756
|
+
const childType = genericArgs[i];
|
|
757
|
+
if (childType.name === 'Bool') {
|
|
758
|
+
const after = findBoolTypes(genericArgs, i, 1);
|
|
759
|
+
const boolNum = after + 1;
|
|
760
|
+
size += Math.floor(boolNum / BITS_IN_BYTE);
|
|
761
|
+
size += boolNum % BITS_IN_BYTE ? 1 : 0;
|
|
762
|
+
i += after;
|
|
763
|
+
}
|
|
764
|
+
else {
|
|
765
|
+
size += getMaxLengthOfStaticContentType(childType);
|
|
766
|
+
}
|
|
767
|
+
i += 1;
|
|
768
|
+
}
|
|
769
|
+
return size;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
class StructImpl extends Struct {
|
|
773
|
+
uint8ArrayValue;
|
|
774
|
+
typeInfo;
|
|
775
|
+
genericArgs;
|
|
776
|
+
constructor(typeInfo, value = {}) {
|
|
777
|
+
super(value);
|
|
778
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
779
|
+
this.genericArgs = this.typeInfo.genericArgs;
|
|
780
|
+
Object.keys(this.genericArgs).forEach((key) => {
|
|
781
|
+
Object.defineProperty(this, key, {
|
|
782
|
+
value: value[key],
|
|
783
|
+
writable: true,
|
|
784
|
+
enumerable: true,
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
return new Proxy(this, {
|
|
788
|
+
get(target, prop) {
|
|
789
|
+
const originalValue = Reflect.get(target, prop);
|
|
790
|
+
if (originalValue === undefined && target.uint8ArrayValue && Object.keys(target.genericArgs).includes(prop.toString())) {
|
|
791
|
+
return target.items[prop.toString()];
|
|
792
|
+
}
|
|
793
|
+
return originalValue;
|
|
794
|
+
},
|
|
795
|
+
set(target, prop, value) {
|
|
796
|
+
if (target.uint8ArrayValue && Object.keys(target.genericArgs).includes(prop.toString())) {
|
|
797
|
+
target.decodeAsProperties();
|
|
798
|
+
}
|
|
799
|
+
return Reflect.set(target, prop, value);
|
|
800
|
+
},
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
get bytes() {
|
|
804
|
+
return Bytes(this.uint8ArrayValue ?? encode(Object.values(this.items)));
|
|
805
|
+
}
|
|
806
|
+
get items() {
|
|
807
|
+
this.decodeAsProperties();
|
|
808
|
+
const result = {};
|
|
809
|
+
Object.keys(this.genericArgs).forEach((key) => {
|
|
810
|
+
result[key] = this[key];
|
|
811
|
+
});
|
|
812
|
+
return result;
|
|
813
|
+
}
|
|
814
|
+
decodeAsProperties() {
|
|
815
|
+
if (this.uint8ArrayValue) {
|
|
816
|
+
const values = decode(this.uint8ArrayValue, Object.values(this.genericArgs));
|
|
817
|
+
Object.keys(this.genericArgs).forEach((key, index) => {
|
|
818
|
+
this[key] = values[index];
|
|
819
|
+
});
|
|
820
|
+
this.uint8ArrayValue = undefined;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
824
|
+
let bytesValue = asBytesCls(value);
|
|
825
|
+
if (prefix === 'log') {
|
|
826
|
+
assert(bytesValue.slice(0, 4).equals(ABI_RETURN_VALUE_LOG_PREFIX), 'ABI return prefix not found');
|
|
827
|
+
bytesValue = bytesValue.slice(4);
|
|
828
|
+
}
|
|
829
|
+
const result = new StructImpl(typeInfo);
|
|
830
|
+
result.uint8ArrayValue = asUint8Array(bytesValue);
|
|
831
|
+
return result;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
class DynamicBytesImpl extends DynamicBytes {
|
|
835
|
+
typeInfo;
|
|
836
|
+
value;
|
|
837
|
+
constructor(typeInfo, value) {
|
|
838
|
+
super(value);
|
|
839
|
+
const uint8ArrayValue = conactUint8Arrays(encodeLength(value?.length ?? 0).asUint8Array(), asUint8Array(value ?? new Uint8Array()));
|
|
840
|
+
this.value = DynamicArrayImpl.fromBytesImpl(uint8ArrayValue, typeInfo);
|
|
841
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
842
|
+
return new Proxy(this, arrayProxyHandler());
|
|
843
|
+
}
|
|
844
|
+
get bytes() {
|
|
845
|
+
return this.value.bytes;
|
|
846
|
+
}
|
|
847
|
+
equals(other) {
|
|
848
|
+
if (!(other instanceof DynamicBytesImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
849
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
850
|
+
}
|
|
851
|
+
return this.bytes.equals(other.bytes);
|
|
852
|
+
}
|
|
853
|
+
get length() {
|
|
854
|
+
return this.value.length;
|
|
855
|
+
}
|
|
856
|
+
get native() {
|
|
857
|
+
return this.value.bytes.slice(ABI_LENGTH_SIZE);
|
|
858
|
+
}
|
|
859
|
+
get items() {
|
|
860
|
+
return this.value.items;
|
|
861
|
+
}
|
|
862
|
+
setItem(_index, _value) {
|
|
863
|
+
throw new internal.errors.CodeError('DynamicBytes is immutable');
|
|
864
|
+
}
|
|
865
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
866
|
+
const dynamicArrayValue = DynamicArrayImpl.fromBytesImpl(value, typeInfo, prefix);
|
|
867
|
+
const result = new DynamicBytesImpl(typeInfo);
|
|
868
|
+
result.value = dynamicArrayValue;
|
|
869
|
+
return result;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
class StaticBytesImpl extends StaticBytes {
|
|
873
|
+
value;
|
|
874
|
+
typeInfo;
|
|
875
|
+
constructor(typeInfo, value) {
|
|
876
|
+
super(value);
|
|
877
|
+
const uint8ArrayValue = asUint8Array(value ?? new Uint8Array());
|
|
878
|
+
this.value = StaticArrayImpl.fromBytesImpl(uint8ArrayValue, typeInfo);
|
|
879
|
+
this.typeInfo = typeof typeInfo === 'string' ? JSON.parse(typeInfo) : typeInfo;
|
|
880
|
+
return new Proxy(this, arrayProxyHandler());
|
|
881
|
+
}
|
|
882
|
+
get bytes() {
|
|
883
|
+
return this.value.bytes;
|
|
884
|
+
}
|
|
885
|
+
equals(other) {
|
|
886
|
+
if (!(other instanceof StaticBytesImpl) || JSON.stringify(this.typeInfo) !== JSON.stringify(other.typeInfo)) {
|
|
887
|
+
throw new internal.errors.CodeError(`Expected expression of type ${this.typeInfo.name}, got ${other.typeInfo.name}`);
|
|
888
|
+
}
|
|
889
|
+
return this.bytes.equals(other.bytes);
|
|
890
|
+
}
|
|
891
|
+
get length() {
|
|
892
|
+
return this.value.length;
|
|
893
|
+
}
|
|
894
|
+
get native() {
|
|
895
|
+
return this.value.bytes;
|
|
896
|
+
}
|
|
897
|
+
get items() {
|
|
898
|
+
return this.value.items;
|
|
899
|
+
}
|
|
900
|
+
setItem(_index, _value) {
|
|
901
|
+
throw new internal.errors.CodeError('StaticBytes is immutable');
|
|
902
|
+
}
|
|
903
|
+
static fromBytesImpl(value, typeInfo, prefix = 'none') {
|
|
904
|
+
const staticArrayValue = StaticArrayImpl.fromBytesImpl(value, typeInfo, prefix);
|
|
905
|
+
const result = new StaticBytesImpl(typeInfo);
|
|
906
|
+
result.value = staticArrayValue;
|
|
907
|
+
return result;
|
|
908
|
+
}
|
|
909
|
+
static getMaxBytesLength(typeInfo) {
|
|
910
|
+
return StaticArrayImpl.getMaxBytesLength(typeInfo);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
const decode = (value, childTypes) => {
|
|
914
|
+
let i = 0;
|
|
915
|
+
let arrayIndex = 0;
|
|
916
|
+
const valuePartitions = [];
|
|
917
|
+
const dynamicSegments = []; // Store the start and end of a dynamic element
|
|
918
|
+
while (i < childTypes.length) {
|
|
919
|
+
const childType = childTypes[i];
|
|
920
|
+
if (holdsDynamicLengthContent(childType)) {
|
|
921
|
+
// Decode the size of the dynamic element
|
|
922
|
+
const dynamicIndex = uint8ArrayToNumber(value.slice(arrayIndex, arrayIndex + ABI_LENGTH_SIZE));
|
|
923
|
+
if (dynamicSegments.length) {
|
|
924
|
+
dynamicSegments.at(-1)[1] = dynamicIndex;
|
|
925
|
+
}
|
|
926
|
+
// Since we do not know where the current dynamic element ends,
|
|
927
|
+
// put a placeholder and update later
|
|
928
|
+
dynamicSegments.push([dynamicIndex, -1]);
|
|
929
|
+
valuePartitions.push(new Uint8Array());
|
|
930
|
+
arrayIndex += ABI_LENGTH_SIZE;
|
|
931
|
+
}
|
|
932
|
+
else if (childType.name === 'Bool') {
|
|
933
|
+
const before = findBoolTypes(childTypes, i, -1);
|
|
934
|
+
let after = findBoolTypes(childTypes, i, 1);
|
|
935
|
+
if (before % 8 != 0) {
|
|
936
|
+
throw new internal.errors.CodeError('"expected before index should have number of bool mod 8 equal 0"');
|
|
937
|
+
}
|
|
938
|
+
after = Math.min(7, after);
|
|
939
|
+
const bits = uint8ArrayToNumber(value.slice(arrayIndex, arrayIndex + 1));
|
|
940
|
+
Array(after + 1)
|
|
941
|
+
.fill(0)
|
|
942
|
+
.forEach((_, j) => {
|
|
943
|
+
const mask = 128 >> j;
|
|
944
|
+
valuePartitions.push(mask & bits ? encodingUtil.bigIntToUint8Array(TRUE_BIGINT_VALUE) : encodingUtil.bigIntToUint8Array(FALSE_BIGINT_VALUE));
|
|
945
|
+
});
|
|
946
|
+
i += after;
|
|
947
|
+
arrayIndex += 1;
|
|
948
|
+
}
|
|
949
|
+
else {
|
|
950
|
+
const currLen = getMaxLengthOfStaticContentType(childType);
|
|
951
|
+
valuePartitions.push(value.slice(arrayIndex, arrayIndex + currLen));
|
|
952
|
+
arrayIndex += currLen;
|
|
953
|
+
}
|
|
954
|
+
if (arrayIndex >= value.length && i != childTypes.length - 1) {
|
|
955
|
+
throw new internal.errors.CodeError('input string is not long enough to be decoded');
|
|
956
|
+
}
|
|
957
|
+
i += 1;
|
|
958
|
+
}
|
|
959
|
+
if (dynamicSegments.length > 0) {
|
|
960
|
+
dynamicSegments.at(-1)[1] = value.length;
|
|
961
|
+
arrayIndex = value.length;
|
|
962
|
+
}
|
|
963
|
+
if (arrayIndex < value.length) {
|
|
964
|
+
throw new internal.errors.CodeError('input string was not fully consumed');
|
|
965
|
+
}
|
|
966
|
+
// Check dynamic element partitions
|
|
967
|
+
let segmentIndex = 0;
|
|
968
|
+
childTypes.forEach((childType, index) => {
|
|
969
|
+
if (holdsDynamicLengthContent(childType)) {
|
|
970
|
+
const [segmentStart, segmentEnd] = dynamicSegments[segmentIndex];
|
|
971
|
+
valuePartitions[index] = value.slice(segmentStart, segmentEnd);
|
|
972
|
+
segmentIndex += 1;
|
|
973
|
+
}
|
|
974
|
+
});
|
|
975
|
+
const values = [];
|
|
976
|
+
childTypes.forEach((childType, index) => {
|
|
977
|
+
values.push(getArc4Encoder(childType)(valuePartitions[index], childType));
|
|
978
|
+
});
|
|
979
|
+
return values;
|
|
980
|
+
};
|
|
981
|
+
const findBoolTypes = (values, index, delta) => {
|
|
982
|
+
// Helper function to find consecutive booleans from current index in a tuple.
|
|
983
|
+
let until = 0;
|
|
984
|
+
const length = values.length;
|
|
985
|
+
while (true) {
|
|
986
|
+
const curr = index + delta * until;
|
|
987
|
+
if (values[curr].name === 'Bool') {
|
|
988
|
+
if ((curr != length - 1 && delta > 0) || (curr > 0 && delta < 0)) {
|
|
989
|
+
until += 1;
|
|
990
|
+
}
|
|
991
|
+
else {
|
|
992
|
+
break;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
else {
|
|
996
|
+
until -= 1;
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
return until;
|
|
1001
|
+
};
|
|
1002
|
+
const getMaxLengthOfStaticContentType = (type) => {
|
|
1003
|
+
switch (trimGenericTypeName(type.name)) {
|
|
1004
|
+
case 'Address':
|
|
1005
|
+
return AddressImpl.getMaxBytesLength(type);
|
|
1006
|
+
case 'Byte':
|
|
1007
|
+
return ByteImpl.getMaxBitsLength(type) / BITS_IN_BYTE;
|
|
1008
|
+
case 'UintN':
|
|
1009
|
+
return UintNImpl.getMaxBitsLength(type) / BITS_IN_BYTE;
|
|
1010
|
+
case 'UFixedNxM':
|
|
1011
|
+
return UFixedNxMImpl.getMaxBitsLength(type) / BITS_IN_BYTE;
|
|
1012
|
+
case 'StaticArray':
|
|
1013
|
+
return StaticArrayImpl.getMaxBytesLength(type);
|
|
1014
|
+
case 'StaticBytes':
|
|
1015
|
+
return StaticBytesImpl.getMaxBytesLength(type);
|
|
1016
|
+
case 'Tuple':
|
|
1017
|
+
return TupleImpl.getMaxBytesLength(type);
|
|
1018
|
+
}
|
|
1019
|
+
throw new internal.errors.CodeError(`unsupported type ${type.name}`);
|
|
1020
|
+
};
|
|
1021
|
+
const encode = (values) => {
|
|
1022
|
+
const length = values.length;
|
|
1023
|
+
const heads = [];
|
|
1024
|
+
const tails = [];
|
|
1025
|
+
const dynamicLengthTypeIndex = [];
|
|
1026
|
+
let i = 0;
|
|
1027
|
+
const valuesLengthBytes = values instanceof DynamicArray ? encodeLength(length).asUint8Array() : new Uint8Array();
|
|
1028
|
+
while (i < length) {
|
|
1029
|
+
const value = values[i];
|
|
1030
|
+
assert(value instanceof ARC4Encoded, `expected ARC4 type ${value.constructor.name}`);
|
|
1031
|
+
dynamicLengthTypeIndex.push(isDynamicLengthType(value));
|
|
1032
|
+
if (dynamicLengthTypeIndex.at(-1)) {
|
|
1033
|
+
heads.push(asUint8Array(Bytes.fromHex('0000')));
|
|
1034
|
+
tails.push(asUint8Array(value.bytes));
|
|
1035
|
+
}
|
|
1036
|
+
else {
|
|
1037
|
+
if (value instanceof Bool) {
|
|
1038
|
+
const before = findBool(values, i, -1);
|
|
1039
|
+
let after = findBool(values, i, 1);
|
|
1040
|
+
if (before % 8 != 0) {
|
|
1041
|
+
throw new internal.errors.CodeError('"expected before index should have number of bool mod 8 equal 0"');
|
|
1042
|
+
}
|
|
1043
|
+
after = Math.min(7, after);
|
|
1044
|
+
const consecutiveBools = values.slice(i, i + after + 1);
|
|
1045
|
+
const compressedNumber = compressMultipleBool(consecutiveBools);
|
|
1046
|
+
heads.push(new Uint8Array([compressedNumber]));
|
|
1047
|
+
i += after;
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
heads.push(asUint8Array(value.bytes));
|
|
1051
|
+
}
|
|
1052
|
+
tails.push(new Uint8Array());
|
|
1053
|
+
}
|
|
1054
|
+
i += 1;
|
|
1055
|
+
}
|
|
1056
|
+
// Adjust heads for dynamic types
|
|
1057
|
+
let headLength = 0;
|
|
1058
|
+
heads.forEach((head) => {
|
|
1059
|
+
// If the element is not a placeholder, append the length of the element
|
|
1060
|
+
headLength += head.length;
|
|
1061
|
+
});
|
|
1062
|
+
// Correctly encode dynamic types and replace placeholder
|
|
1063
|
+
let tailCurrLength = 0;
|
|
1064
|
+
for (let i = 0; i < heads.length; i++) {
|
|
1065
|
+
if (dynamicLengthTypeIndex[i]) {
|
|
1066
|
+
const headValue = headLength + tailCurrLength;
|
|
1067
|
+
heads[i] = asUint8Array(encodeLength(headValue));
|
|
1068
|
+
}
|
|
1069
|
+
tailCurrLength += tails[i].length;
|
|
1070
|
+
}
|
|
1071
|
+
return conactUint8Arrays(valuesLengthBytes, ...heads, ...tails);
|
|
1072
|
+
};
|
|
1073
|
+
const findBool = (values, index, delta) => {
|
|
1074
|
+
let until = 0;
|
|
1075
|
+
const length = values.length;
|
|
1076
|
+
while (true) {
|
|
1077
|
+
const curr = index + delta * until;
|
|
1078
|
+
if (values[curr] instanceof Bool) {
|
|
1079
|
+
if ((curr !== length - 1 && delta > 0) || (curr > 0 && delta < 0)) {
|
|
1080
|
+
until += 1;
|
|
1081
|
+
}
|
|
1082
|
+
else {
|
|
1083
|
+
break;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
else {
|
|
1087
|
+
until -= 1;
|
|
1088
|
+
break;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
return until;
|
|
1092
|
+
};
|
|
1093
|
+
const compressMultipleBool = (values) => {
|
|
1094
|
+
let result = 0;
|
|
1095
|
+
if (values.length > 8) {
|
|
1096
|
+
throw new Error('length of list should not be greater than 8');
|
|
1097
|
+
}
|
|
1098
|
+
for (let i = 0; i < values.length; i++) {
|
|
1099
|
+
const value = values[i];
|
|
1100
|
+
if (value.native) {
|
|
1101
|
+
result |= 1 << (7 - i);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
return result;
|
|
1105
|
+
};
|
|
1106
|
+
const trimGenericTypeName = (typeName) => typeName.replace(/<.*>/, '');
|
|
1107
|
+
const isDynamicLengthType = (value) => value instanceof StrImpl ||
|
|
1108
|
+
(value instanceof StaticArrayImpl && holdsDynamicLengthContent(value)) ||
|
|
1109
|
+
(value instanceof TupleImpl && value.genericArgs.some(holdsDynamicLengthContent)) ||
|
|
1110
|
+
(value instanceof StructImpl && Object.values(value.genericArgs).some(holdsDynamicLengthContent)) ||
|
|
1111
|
+
value instanceof DynamicArrayImpl ||
|
|
1112
|
+
value instanceof DynamicBytesImpl;
|
|
1113
|
+
const holdsDynamicLengthContent = (value) => {
|
|
1114
|
+
const itemTypeName = trimGenericTypeName(value instanceof StaticArrayImpl || value instanceof DynamicArrayImpl ? value.genericArgs.elementType.name : value.name);
|
|
1115
|
+
return (itemTypeName === 'Str' ||
|
|
1116
|
+
itemTypeName === 'DynamicArray' ||
|
|
1117
|
+
itemTypeName === 'DynamicBytes' ||
|
|
1118
|
+
(itemTypeName === 'StaticArray' &&
|
|
1119
|
+
holdsDynamicLengthContent(value.genericArgs.elementType)) ||
|
|
1120
|
+
((itemTypeName === 'Tuple' || itemTypeName === 'Struct') &&
|
|
1121
|
+
Object.values(value.genericArgs).some(holdsDynamicLengthContent)));
|
|
1122
|
+
};
|
|
1123
|
+
function interpretAsArc4Impl(typeInfoString, bytes, prefix = 'none') {
|
|
1124
|
+
const typeInfo = JSON.parse(typeInfoString);
|
|
1125
|
+
return getArc4Encoder(typeInfo)(bytes, typeInfo, prefix);
|
|
1126
|
+
}
|
|
1127
|
+
const arc4Encoders = {
|
|
1128
|
+
Address: AddressImpl.fromBytesImpl,
|
|
1129
|
+
Bool: BoolImpl.fromBytesImpl,
|
|
1130
|
+
Byte: ByteImpl.fromBytesImpl,
|
|
1131
|
+
Str: StrImpl.fromBytesImpl,
|
|
1132
|
+
'UintN<.*>': UintNImpl.fromBytesImpl,
|
|
1133
|
+
'UFixedNxM<.*>': UFixedNxMImpl.fromBytesImpl,
|
|
1134
|
+
'StaticArray<.*>': StaticArrayImpl.fromBytesImpl,
|
|
1135
|
+
'DynamicArray<.*>': DynamicArrayImpl.fromBytesImpl,
|
|
1136
|
+
Tuple: TupleImpl.fromBytesImpl,
|
|
1137
|
+
Struct: StructImpl.fromBytesImpl,
|
|
1138
|
+
DynamicBytes: DynamicBytesImpl.fromBytesImpl,
|
|
1139
|
+
'StaticBytes<.*>': StaticBytesImpl.fromBytesImpl,
|
|
1140
|
+
};
|
|
1141
|
+
const getArc4Encoder = (typeInfo, encoders) => {
|
|
1142
|
+
const encoder = Object.entries(encoders ?? arc4Encoders).find(([k, _]) => new RegExp(`^${k}$`, 'i').test(typeInfo.name))?.[1];
|
|
1143
|
+
if (!encoder) {
|
|
1144
|
+
throw new Error(`No encoder found for type ${typeInfo.name}`);
|
|
1145
|
+
}
|
|
1146
|
+
return encoder;
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1149
|
+
function switchableValue(x) {
|
|
1150
|
+
if (typeof x === 'boolean')
|
|
1151
|
+
return x;
|
|
1152
|
+
if (typeof x === 'bigint')
|
|
1153
|
+
return x;
|
|
1154
|
+
if (typeof x === 'string')
|
|
1155
|
+
return x;
|
|
1156
|
+
if (x instanceof internal.primitives.AlgoTsPrimitiveCls)
|
|
1157
|
+
return x.valueOf();
|
|
1158
|
+
internal.errors.internalError(`Cannot convert ${nameOfType(x)} to switchable value`);
|
|
1159
|
+
}
|
|
1160
|
+
function tryGetBigInt(value) {
|
|
1161
|
+
if (typeof value == 'bigint')
|
|
1162
|
+
return value;
|
|
1163
|
+
if (typeof value == 'number')
|
|
1164
|
+
return BigInt(value);
|
|
1165
|
+
if (value instanceof internal.primitives.Uint64Cls)
|
|
1166
|
+
return value.valueOf();
|
|
1167
|
+
if (value instanceof internal.primitives.BigUintCls)
|
|
1168
|
+
return value.valueOf();
|
|
1169
|
+
return undefined;
|
|
1170
|
+
}
|
|
1171
|
+
function binaryOp(left, right, op) {
|
|
1172
|
+
if (left instanceof ARC4Encoded && right instanceof ARC4Encoded) {
|
|
1173
|
+
return arc4EncodedOp(left, right, op);
|
|
1174
|
+
}
|
|
1175
|
+
if (left instanceof internal.primitives.BigUintCls || right instanceof internal.primitives.BigUintCls) {
|
|
1176
|
+
return bigUintBinaryOp(left, right, op);
|
|
1177
|
+
}
|
|
1178
|
+
if (left instanceof internal.primitives.Uint64Cls || right instanceof internal.primitives.Uint64Cls) {
|
|
1179
|
+
return uint64BinaryOp(left, right, op);
|
|
1180
|
+
}
|
|
1181
|
+
if (left instanceof internal.primitives.BytesCls || right instanceof internal.primitives.BytesCls) {
|
|
1182
|
+
return bytesBinaryOp(left, right, op);
|
|
1183
|
+
}
|
|
1184
|
+
const lbi = tryGetBigInt(left);
|
|
1185
|
+
const rbi = tryGetBigInt(right);
|
|
1186
|
+
if (lbi !== undefined && rbi !== undefined) {
|
|
1187
|
+
const result = defaultBinaryOp(lbi, rbi, op);
|
|
1188
|
+
if (typeof result === 'boolean') {
|
|
1189
|
+
return result;
|
|
1190
|
+
}
|
|
1191
|
+
if (typeof left === 'number' && typeof right === 'number' && result <= Number.MAX_SAFE_INTEGER) {
|
|
1192
|
+
return Number(result);
|
|
1193
|
+
}
|
|
1194
|
+
return result;
|
|
1195
|
+
}
|
|
1196
|
+
return defaultBinaryOp(left, right, op);
|
|
1197
|
+
}
|
|
1198
|
+
function unaryOp(operand, op) {
|
|
1199
|
+
if (operand instanceof internal.primitives.Uint64Cls) {
|
|
1200
|
+
return uint64UnaryOp(operand, op);
|
|
1201
|
+
}
|
|
1202
|
+
return defaultUnaryOp(operand, op);
|
|
1203
|
+
}
|
|
1204
|
+
function arc4EncodedOp(left, right, op) {
|
|
1205
|
+
const hasEqualsMethod = (x) => Object.hasOwn(x, 'equals') && typeof x.equals === 'function';
|
|
1206
|
+
const compareEquality = (x, y) => hasEqualsMethod(x) ? x.equals(y) : y.equals(x);
|
|
1207
|
+
switch (op) {
|
|
1208
|
+
case '===':
|
|
1209
|
+
return compareEquality(left, right);
|
|
1210
|
+
case '!==':
|
|
1211
|
+
return !compareEquality(left, right);
|
|
1212
|
+
default:
|
|
1213
|
+
internal.errors.internalError(`Unsupported operator ${op}`);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
function uint64BinaryOp(left, right, op) {
|
|
1217
|
+
const lbi = internal.primitives.Uint64Cls.fromCompat(left).valueOf();
|
|
1218
|
+
const rbi = internal.primitives.Uint64Cls.fromCompat(right).valueOf();
|
|
1219
|
+
const result = (function () {
|
|
1220
|
+
switch (op) {
|
|
1221
|
+
case '+':
|
|
1222
|
+
return lbi + rbi;
|
|
1223
|
+
case '-':
|
|
1224
|
+
return lbi - rbi;
|
|
1225
|
+
case '*':
|
|
1226
|
+
return lbi * rbi;
|
|
1227
|
+
case '**':
|
|
1228
|
+
if (lbi === 0n && rbi === 0n) {
|
|
1229
|
+
throw internal.errors.codeError('0 ** 0 is undefined');
|
|
1230
|
+
}
|
|
1231
|
+
return lbi ** rbi;
|
|
1232
|
+
case '/':
|
|
1233
|
+
return lbi / rbi;
|
|
1234
|
+
case '%':
|
|
1235
|
+
return lbi % rbi;
|
|
1236
|
+
case '>>':
|
|
1237
|
+
if (rbi > 63n) {
|
|
1238
|
+
throw new internal.errors.CodeError('expected shift <= 63');
|
|
1239
|
+
}
|
|
1240
|
+
return (lbi >> rbi) & MAX_UINT64;
|
|
1241
|
+
case '<<':
|
|
1242
|
+
if (rbi > 63n) {
|
|
1243
|
+
throw new internal.errors.CodeError('expected shift <= 63');
|
|
1244
|
+
}
|
|
1245
|
+
return (lbi << rbi) & MAX_UINT64;
|
|
1246
|
+
case '>':
|
|
1247
|
+
return lbi > rbi;
|
|
1248
|
+
case '<':
|
|
1249
|
+
return lbi < rbi;
|
|
1250
|
+
case '>=':
|
|
1251
|
+
return lbi >= rbi;
|
|
1252
|
+
case '<=':
|
|
1253
|
+
return lbi <= rbi;
|
|
1254
|
+
case '===':
|
|
1255
|
+
return lbi === rbi;
|
|
1256
|
+
case '!==':
|
|
1257
|
+
return lbi !== rbi;
|
|
1258
|
+
case '&':
|
|
1259
|
+
return lbi & rbi;
|
|
1260
|
+
case '|':
|
|
1261
|
+
return lbi | rbi;
|
|
1262
|
+
case '^':
|
|
1263
|
+
return lbi ^ rbi;
|
|
1264
|
+
default:
|
|
1265
|
+
internal.errors.internalError(`Unsupported operator ${op}`);
|
|
1266
|
+
}
|
|
1267
|
+
})();
|
|
1268
|
+
return typeof result === 'boolean' ? result : new internal.primitives.Uint64Cls(result);
|
|
1269
|
+
}
|
|
1270
|
+
function bigUintBinaryOp(left, right, op) {
|
|
1271
|
+
const lbi = internal.primitives.checkBigUint(internal.primitives.BigUintCls.fromCompat(left).valueOf());
|
|
1272
|
+
const rbi = internal.primitives.checkBigUint(internal.primitives.BigUintCls.fromCompat(right).valueOf());
|
|
1273
|
+
const result = (function () {
|
|
1274
|
+
switch (op) {
|
|
1275
|
+
case '+':
|
|
1276
|
+
return lbi + rbi;
|
|
1277
|
+
case '-':
|
|
1278
|
+
return lbi - rbi;
|
|
1279
|
+
case '*':
|
|
1280
|
+
return lbi * rbi;
|
|
1281
|
+
case '**':
|
|
1282
|
+
if (lbi === 0n && rbi === 0n) {
|
|
1283
|
+
throw internal.errors.codeError('0 ** 0 is undefined');
|
|
1284
|
+
}
|
|
1285
|
+
return lbi ** rbi;
|
|
1286
|
+
case '/':
|
|
1287
|
+
return lbi / rbi;
|
|
1288
|
+
case '%':
|
|
1289
|
+
return lbi % rbi;
|
|
1290
|
+
case '>>':
|
|
1291
|
+
throw new internal.errors.CodeError('BigUint does not support >> operator');
|
|
1292
|
+
case '<<':
|
|
1293
|
+
throw new internal.errors.CodeError('BigUint does not support << operator');
|
|
1294
|
+
case '>':
|
|
1295
|
+
return lbi > rbi;
|
|
1296
|
+
case '<':
|
|
1297
|
+
return lbi < rbi;
|
|
1298
|
+
case '>=':
|
|
1299
|
+
return lbi >= rbi;
|
|
1300
|
+
case '<=':
|
|
1301
|
+
return lbi <= rbi;
|
|
1302
|
+
case '===':
|
|
1303
|
+
return lbi === rbi;
|
|
1304
|
+
case '!==':
|
|
1305
|
+
return lbi !== rbi;
|
|
1306
|
+
case '&':
|
|
1307
|
+
return lbi & rbi;
|
|
1308
|
+
case '|':
|
|
1309
|
+
return lbi | rbi;
|
|
1310
|
+
case '^':
|
|
1311
|
+
return lbi ^ rbi;
|
|
1312
|
+
default:
|
|
1313
|
+
internal.errors.internalError(`Unsupported operator ${op}`);
|
|
1314
|
+
}
|
|
1315
|
+
})();
|
|
1316
|
+
if (typeof result === 'boolean') {
|
|
1317
|
+
return result;
|
|
1318
|
+
}
|
|
1319
|
+
if (result < 0) {
|
|
1320
|
+
internal.errors.avmError('BigUint underflow');
|
|
1321
|
+
}
|
|
1322
|
+
return new internal.primitives.BigUintCls(result);
|
|
1323
|
+
}
|
|
1324
|
+
function bytesBinaryOp(left, right, op) {
|
|
1325
|
+
const lbb = internal.primitives.checkBytes(internal.primitives.BytesCls.fromCompat(left).asUint8Array());
|
|
1326
|
+
const rbb = internal.primitives.checkBytes(internal.primitives.BytesCls.fromCompat(right).asUint8Array());
|
|
1327
|
+
const lbi = internal.encodingUtil.uint8ArrayToBigInt(lbb);
|
|
1328
|
+
const rbi = internal.encodingUtil.uint8ArrayToBigInt(rbb);
|
|
1329
|
+
const result = (function () {
|
|
1330
|
+
switch (op) {
|
|
1331
|
+
case '>':
|
|
1332
|
+
return lbi > rbi;
|
|
1333
|
+
case '<':
|
|
1334
|
+
return lbi < rbi;
|
|
1335
|
+
case '>=':
|
|
1336
|
+
return lbi >= rbi;
|
|
1337
|
+
case '<=':
|
|
1338
|
+
return lbi <= rbi;
|
|
1339
|
+
case '===':
|
|
1340
|
+
return lbi === rbi;
|
|
1341
|
+
case '!==':
|
|
1342
|
+
return lbi !== rbi;
|
|
1343
|
+
default:
|
|
1344
|
+
internal.errors.internalError(`Unsupported operator ${op}`);
|
|
1345
|
+
}
|
|
1346
|
+
})();
|
|
1347
|
+
return result;
|
|
1348
|
+
}
|
|
1349
|
+
function defaultBinaryOp(left, right, op) {
|
|
1350
|
+
switch (op) {
|
|
1351
|
+
case '+':
|
|
1352
|
+
return left + right;
|
|
1353
|
+
case '-':
|
|
1354
|
+
return left - right;
|
|
1355
|
+
case '*':
|
|
1356
|
+
return left * right;
|
|
1357
|
+
case '**':
|
|
1358
|
+
if (left === 0n && right === 0n) {
|
|
1359
|
+
throw new internal.errors.CodeError('0 ** 0 is undefined');
|
|
1360
|
+
}
|
|
1361
|
+
return left ** right;
|
|
1362
|
+
case '/':
|
|
1363
|
+
return left / right;
|
|
1364
|
+
case '%':
|
|
1365
|
+
return left % right;
|
|
1366
|
+
case '>>':
|
|
1367
|
+
if (typeof left === 'bigint' && typeof right === 'bigint') {
|
|
1368
|
+
if (right > 63n) {
|
|
1369
|
+
throw new internal.errors.CodeError('expected shift <= 63');
|
|
1370
|
+
}
|
|
1371
|
+
return (left >> right) & MAX_UINT64;
|
|
1372
|
+
}
|
|
1373
|
+
return left >> right;
|
|
1374
|
+
case '<<':
|
|
1375
|
+
if (typeof left === 'bigint' && typeof right === 'bigint') {
|
|
1376
|
+
if (right > 63n) {
|
|
1377
|
+
throw new internal.errors.CodeError('expected shift <= 63');
|
|
1378
|
+
}
|
|
1379
|
+
return (left << right) & MAX_UINT64;
|
|
1380
|
+
}
|
|
1381
|
+
return left << right;
|
|
1382
|
+
case '>':
|
|
1383
|
+
return left > right;
|
|
1384
|
+
case '<':
|
|
1385
|
+
return left < right;
|
|
1386
|
+
case '>=':
|
|
1387
|
+
return left >= right;
|
|
1388
|
+
case '<=':
|
|
1389
|
+
return left <= right;
|
|
1390
|
+
case '===':
|
|
1391
|
+
return left === right;
|
|
1392
|
+
case '!==':
|
|
1393
|
+
return left !== right;
|
|
1394
|
+
case '&':
|
|
1395
|
+
return left & right;
|
|
1396
|
+
case '|':
|
|
1397
|
+
return left | right;
|
|
1398
|
+
case '^':
|
|
1399
|
+
return left ^ right;
|
|
1400
|
+
default:
|
|
1401
|
+
internal.errors.internalError(`Unsupported operator ${op}`);
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
function uint64UnaryOp(operand, op) {
|
|
1405
|
+
const obi = internal.primitives.Uint64Cls.fromCompat(operand).valueOf();
|
|
1406
|
+
switch (op) {
|
|
1407
|
+
case '~':
|
|
1408
|
+
return ~obi & MAX_UINT64;
|
|
1409
|
+
default:
|
|
1410
|
+
internal.errors.internalError(`Unsupported operator ${op}`);
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
function defaultUnaryOp(_operand, op) {
|
|
1414
|
+
internal.errors.internalError(`Unsupported operator ${op}`);
|
|
1415
|
+
}
|
|
1416
|
+
const genericTypeMap = new WeakMap();
|
|
1417
|
+
function captureGenericTypeInfo(target, t) {
|
|
1418
|
+
genericTypeMap.set(target, JSON.parse(t));
|
|
1419
|
+
return target;
|
|
1420
|
+
}
|
|
1421
|
+
function getGenericTypeInfo(target) {
|
|
1422
|
+
return genericTypeMap.get(target);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
export { AddressImpl as $, ALWAYS_APPROVE_TEAL_PROGRAM as A, BITS_IN_BYTE as B, ABI_RETURN_VALUE_LOG_PREFIX as C, DEFAULT_ACCOUNT_MIN_BALANCE as D, getRandomBytes as E, getArc4Encoder as F, arc4Encoders as G, getGenericTypeInfo as H, getAbiMetadata as I, iterBigInt as J, getRandomBigInt as K, LOGIC_DATA_PREFIX as L, MAX_BOX_SIZE as M, captureMethodConfig as N, switchableValue as O, binaryOp as P, unaryOp as Q, captureGenericTypeInfo as R, attachAbiMetadata as S, UintNImpl as T, UINT64_SIZE as U, UFixedNxMImpl as V, ByteImpl as W, StrImpl as X, BoolImpl as Y, ZERO_ADDRESS as Z, StaticArrayImpl as _, asMaybeUint64Cls as a, DynamicArrayImpl as a0, TupleImpl as a1, StructImpl as a2, DynamicBytesImpl as a3, StaticBytesImpl as a4, interpretAsArc4Impl as a5, asUint64 as b, asBytes as c, asNumber as d, asBytesCls as e, asUint8Array as f, conactUint8Arrays as g, asBigInt as h, getObjectReference as i, MIN_TXN_FEE as j, DEFAULT_MAX_TXN_LIFE as k, DEFAULT_ASSET_CREATE_MIN_BALANCE as l, DEFAULT_ASSET_OPT_IN_MIN_BALANCE as m, DEFAULT_GLOBAL_GENESIS_HASH as n, asUint64Cls as o, asMaybeBytesCls as p, asBigUint as q, MAX_BYTES_SIZE as r, MAX_UINT8 as s, toBytes as t, binaryStringToBytes as u, MAX_UINT64 as v, Uint64BackedCls as w, BytesBackedCls as x, combineIntoMaxBytePages as y, MAX_ITEMS_IN_LOG as z };
|
|
1426
|
+
//# sourceMappingURL=runtime-helpers-DlIX78iw.js.map
|