algosdk 1.11.1 → 1.13.0
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/README.md +17 -6
- package/dist/browser/algosdk.min.js +1 -1
- package/dist/browser/algosdk.min.js.map +1 -1
- package/dist/cjs/src/abi/abi_type.js +693 -0
- package/dist/cjs/src/abi/abi_type.js.map +1 -0
- package/dist/cjs/src/abi/contract.js +27 -0
- package/dist/cjs/src/abi/contract.js.map +1 -0
- package/dist/cjs/src/abi/index.js +19 -0
- package/dist/cjs/src/abi/index.js.map +1 -0
- package/dist/cjs/src/abi/interface.js +23 -0
- package/dist/cjs/src/abi/interface.js.map +1 -0
- package/dist/cjs/src/abi/method.js +114 -0
- package/dist/cjs/src/abi/method.js.map +1 -0
- package/dist/cjs/src/abi/reference.js +25 -0
- package/dist/cjs/src/abi/reference.js.map +1 -0
- package/dist/cjs/src/abi/transaction.js +52 -0
- package/dist/cjs/src/abi/transaction.js.map +1 -0
- package/dist/cjs/src/client/baseHTTPClient.js +3 -0
- package/dist/cjs/src/client/baseHTTPClient.js.map +1 -0
- package/dist/cjs/src/client/client.js +165 -104
- package/dist/cjs/src/client/client.js.map +1 -1
- package/dist/cjs/src/client/urlTokenBaseHTTPClient.js +138 -0
- package/dist/cjs/src/client/urlTokenBaseHTTPClient.js.map +1 -0
- package/dist/cjs/src/client/v2/algod/algod.js +262 -9
- package/dist/cjs/src/client/v2/algod/algod.js.map +1 -1
- package/dist/cjs/src/client/v2/algod/models/types.js +13 -33
- package/dist/cjs/src/client/v2/algod/models/types.js.map +1 -1
- package/dist/cjs/src/client/v2/indexer/indexer.js +168 -3
- package/dist/cjs/src/client/v2/indexer/indexer.js.map +1 -1
- package/dist/cjs/src/client/v2/indexer/lookupApplicationLogs.js +48 -0
- package/dist/cjs/src/client/v2/indexer/lookupApplicationLogs.js.map +1 -0
- package/dist/cjs/src/client/v2/indexer/lookupAssetBalances.js +98 -6
- package/dist/cjs/src/client/v2/indexer/lookupAssetBalances.js.map +1 -1
- package/dist/cjs/src/client/v2/serviceClient.js +17 -8
- package/dist/cjs/src/client/v2/serviceClient.js.map +1 -1
- package/dist/cjs/src/composer.js +439 -0
- package/dist/cjs/src/composer.js.map +1 -0
- package/dist/cjs/src/dryrun.js +103 -0
- package/dist/cjs/src/dryrun.js.map +1 -0
- package/dist/cjs/src/encoding/address.js +14 -1
- package/dist/cjs/src/encoding/address.js.map +1 -1
- package/dist/cjs/src/encoding/bigint.js +38 -0
- package/dist/cjs/src/encoding/bigint.js.map +1 -0
- package/dist/cjs/src/logic/langspec.json +392 -77
- package/dist/cjs/src/logicsig.js +2 -2
- package/dist/cjs/src/logicsig.js.map +1 -1
- package/dist/cjs/src/main.js +18 -91
- package/dist/cjs/src/main.js.map +1 -1
- package/dist/cjs/src/makeTxn.js +29 -1
- package/dist/cjs/src/makeTxn.js.map +1 -1
- package/dist/cjs/src/multisig.js +77 -2
- package/dist/cjs/src/multisig.js.map +1 -1
- package/dist/cjs/src/signer.js +66 -0
- package/dist/cjs/src/signer.js.map +1 -0
- package/dist/cjs/src/transaction.js +50 -10
- package/dist/cjs/src/transaction.js.map +1 -1
- package/dist/cjs/src/types/intDecoding.js +0 -2
- package/dist/cjs/src/types/intDecoding.js.map +1 -1
- package/dist/cjs/src/types/transactions/base.js +0 -1
- package/dist/cjs/src/types/transactions/base.js.map +1 -1
- package/dist/cjs/src/wait.js +53 -0
- package/dist/cjs/src/wait.js.map +1 -0
- package/dist/esm/src/abi/abi_type.js +680 -0
- package/dist/esm/src/abi/abi_type.js.map +1 -0
- package/dist/esm/src/abi/contract.js +23 -0
- package/dist/esm/src/abi/contract.js.map +1 -0
- package/dist/esm/src/abi/index.js +7 -0
- package/dist/esm/src/abi/index.js.map +1 -0
- package/dist/esm/src/abi/interface.js +19 -0
- package/dist/esm/src/abi/interface.js.map +1 -0
- package/dist/esm/src/abi/method.js +110 -0
- package/dist/esm/src/abi/method.js.map +1 -0
- package/dist/esm/src/abi/reference.js +21 -0
- package/dist/esm/src/abi/reference.js.map +1 -0
- package/dist/esm/src/abi/transaction.js +47 -0
- package/dist/esm/src/abi/transaction.js.map +1 -0
- package/dist/esm/src/client/baseHTTPClient.js +2 -0
- package/dist/esm/src/client/baseHTTPClient.js.map +1 -0
- package/dist/esm/src/client/client.js +165 -101
- package/dist/esm/src/client/client.js.map +1 -1
- package/dist/esm/src/client/urlTokenBaseHTTPClient.js +112 -0
- package/dist/esm/src/client/urlTokenBaseHTTPClient.js.map +1 -0
- package/dist/esm/src/client/v2/algod/algod.js +262 -9
- package/dist/esm/src/client/v2/algod/algod.js.map +1 -1
- package/dist/esm/src/client/v2/algod/models/types.js +12 -31
- package/dist/esm/src/client/v2/algod/models/types.js.map +1 -1
- package/dist/esm/src/client/v2/indexer/indexer.js +168 -3
- package/dist/esm/src/client/v2/indexer/indexer.js.map +1 -1
- package/dist/esm/src/client/v2/indexer/lookupApplicationLogs.js +42 -0
- package/dist/esm/src/client/v2/indexer/lookupApplicationLogs.js.map +1 -0
- package/dist/esm/src/client/v2/indexer/lookupAssetBalances.js +98 -6
- package/dist/esm/src/client/v2/indexer/lookupAssetBalances.js.map +1 -1
- package/dist/esm/src/client/v2/serviceClient.js +17 -8
- package/dist/esm/src/client/v2/serviceClient.js.map +1 -1
- package/dist/esm/src/composer.js +435 -0
- package/dist/esm/src/composer.js.map +1 -0
- package/dist/esm/src/dryrun.js +99 -0
- package/dist/esm/src/dryrun.js.map +1 -0
- package/dist/esm/src/encoding/address.js +12 -0
- package/dist/esm/src/encoding/address.js.map +1 -1
- package/dist/esm/src/encoding/bigint.js +33 -0
- package/dist/esm/src/encoding/bigint.js.map +1 -0
- package/dist/esm/src/logic/langspec.json +392 -77
- package/dist/esm/src/logicsig.js +2 -2
- package/dist/esm/src/logicsig.js.map +1 -1
- package/dist/esm/src/main.js +8 -85
- package/dist/esm/src/main.js.map +1 -1
- package/dist/esm/src/makeTxn.js +27 -0
- package/dist/esm/src/makeTxn.js.map +1 -1
- package/dist/esm/src/multisig.js +73 -1
- package/dist/esm/src/multisig.js.map +1 -1
- package/dist/esm/src/signer.js +59 -0
- package/dist/esm/src/signer.js.map +1 -0
- package/dist/esm/src/transaction.js +50 -10
- package/dist/esm/src/transaction.js.map +1 -1
- package/dist/esm/src/types/intDecoding.js +0 -2
- package/dist/esm/src/types/intDecoding.js.map +1 -1
- package/dist/esm/src/types/transactions/base.js +0 -1
- package/dist/esm/src/types/transactions/base.js.map +1 -1
- package/dist/esm/src/wait.js +49 -0
- package/dist/esm/src/wait.js.map +1 -0
- package/dist/types/src/abi/abi_type.d.ts +102 -0
- package/dist/types/src/abi/contract.d.ts +21 -0
- package/dist/types/src/abi/index.d.ts +6 -0
- package/dist/types/src/abi/interface.d.ts +13 -0
- package/dist/types/src/abi/method.d.ts +39 -0
- package/dist/types/src/abi/reference.d.ts +15 -0
- package/dist/types/src/abi/transaction.d.ts +33 -0
- package/dist/types/src/client/baseHTTPClient.d.ts +41 -0
- package/dist/types/src/client/client.d.ts +67 -31
- package/dist/types/src/client/kmd.d.ts +1 -1
- package/dist/types/src/client/urlTokenBaseHTTPClient.d.ts +44 -0
- package/dist/types/src/client/v2/algod/algod.d.ts +263 -9
- package/dist/types/src/client/v2/algod/models/types.d.ts +24 -37
- package/dist/types/src/client/v2/indexer/indexer.d.ts +167 -3
- package/dist/types/src/client/v2/indexer/lookupApplicationLogs.d.ts +20 -0
- package/dist/types/src/client/v2/indexer/lookupAssetBalances.d.ts +98 -0
- package/dist/types/src/client/v2/serviceClient.d.ts +6 -2
- package/dist/types/src/composer.d.ts +160 -0
- package/dist/types/src/dryrun.d.ts +20 -0
- package/dist/types/src/encoding/address.d.ts +6 -0
- package/dist/types/src/encoding/bigint.d.ts +14 -0
- package/dist/types/src/main.d.ts +9 -48
- package/dist/types/src/makeTxn.d.ts +18 -1
- package/dist/types/src/multisig.d.ts +39 -1
- package/dist/types/src/signer.d.ts +40 -0
- package/dist/types/src/wait.d.ts +11 -0
- package/package.json +6 -4
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise */
|
|
2
|
+
/* eslint-disable no-use-before-define */
|
|
3
|
+
/* eslint-disable class-methods-use-this */
|
|
4
|
+
/**
|
|
5
|
+
//ABI-Types: uint<N>: An N-bit unsigned integer (8 <= N <= 512 and N % 8 = 0).
|
|
6
|
+
// | byte (alias for uint8)
|
|
7
|
+
// | ufixed <N> x <M> (8 <= N <= 512, N % 8 = 0, and 0 < M <= 160)
|
|
8
|
+
// | bool
|
|
9
|
+
// | address (alias for byte[32])
|
|
10
|
+
// | <type> [<N>]
|
|
11
|
+
// | <type> []
|
|
12
|
+
// | string
|
|
13
|
+
// | (T1, ..., Tn)
|
|
14
|
+
*/
|
|
15
|
+
import { encodeAddress, decodeAddress } from '../encoding/address';
|
|
16
|
+
import { bigIntToBytes, bytesToBigInt } from '../encoding/bigint';
|
|
17
|
+
import { concatArrays } from '../utils/utils';
|
|
18
|
+
export const MAX_LEN = 2 ** 16 - 1;
|
|
19
|
+
export const ADDR_BYTE_SIZE = 32;
|
|
20
|
+
export const SINGLE_BYTE_SIZE = 1;
|
|
21
|
+
export const SINGLE_BOOL_SIZE = 1;
|
|
22
|
+
export const LENGTH_ENCODE_BYTE_SIZE = 2;
|
|
23
|
+
const staticArrayRegexp = /^([a-z\d[\](),]+)\[([1-9][\d]*)]$/;
|
|
24
|
+
const ufixedRegexp = /^ufixed([1-9][\d]*)x([1-9][\d]*)$/;
|
|
25
|
+
export class ABIType {
|
|
26
|
+
// De-serializes the ABI type from a string using the ABI specs
|
|
27
|
+
static from(str) {
|
|
28
|
+
if (str.endsWith('[]')) {
|
|
29
|
+
const arrayArgType = ABIType.from(str.slice(0, str.length - 2));
|
|
30
|
+
return new ABIArrayDynamicType(arrayArgType);
|
|
31
|
+
}
|
|
32
|
+
if (str.endsWith(']')) {
|
|
33
|
+
const stringMatches = str.match(staticArrayRegexp);
|
|
34
|
+
// Match the string itself, array element type, then array length
|
|
35
|
+
if (stringMatches.length !== 3) {
|
|
36
|
+
throw new Error(`malformed static array string: ${str}`);
|
|
37
|
+
}
|
|
38
|
+
// Parse static array using regex
|
|
39
|
+
const arrayLengthStr = stringMatches[2];
|
|
40
|
+
const arrayLength = parseInt(arrayLengthStr, 10);
|
|
41
|
+
if (arrayLength > MAX_LEN) {
|
|
42
|
+
throw new Error(`array length exceeds limit ${MAX_LEN}`);
|
|
43
|
+
}
|
|
44
|
+
// Parse the array element type
|
|
45
|
+
const arrayType = ABIType.from(stringMatches[1]);
|
|
46
|
+
return new ABIArrayStaticType(arrayType, arrayLength);
|
|
47
|
+
}
|
|
48
|
+
if (str.startsWith('uint')) {
|
|
49
|
+
// Checks if the parsed number contains only digits, no whitespaces
|
|
50
|
+
const digitsOnly = (string) => [...string].every((c) => '0123456789'.includes(c));
|
|
51
|
+
const typeSizeStr = str.slice(4, str.length);
|
|
52
|
+
if (!digitsOnly(typeSizeStr)) {
|
|
53
|
+
throw new Error(`malformed uint string: ${typeSizeStr}`);
|
|
54
|
+
}
|
|
55
|
+
const typeSize = parseInt(typeSizeStr, 10);
|
|
56
|
+
if (typeSize > MAX_LEN) {
|
|
57
|
+
throw new Error(`malformed uint string: ${typeSize}`);
|
|
58
|
+
}
|
|
59
|
+
return new ABIUintType(typeSize);
|
|
60
|
+
}
|
|
61
|
+
if (str === 'byte') {
|
|
62
|
+
return new ABIByteType();
|
|
63
|
+
}
|
|
64
|
+
if (str.startsWith('ufixed')) {
|
|
65
|
+
const stringMatches = str.match(ufixedRegexp);
|
|
66
|
+
if (stringMatches.length !== 3) {
|
|
67
|
+
throw new Error(`malformed ufixed type: ${str}`);
|
|
68
|
+
}
|
|
69
|
+
const ufixedSize = parseInt(stringMatches[1], 10);
|
|
70
|
+
const ufixedPrecision = parseInt(stringMatches[2], 10);
|
|
71
|
+
return new ABIUfixedType(ufixedSize, ufixedPrecision);
|
|
72
|
+
}
|
|
73
|
+
if (str === 'bool') {
|
|
74
|
+
return new ABIBoolType();
|
|
75
|
+
}
|
|
76
|
+
if (str === 'address') {
|
|
77
|
+
return new ABIAddressType();
|
|
78
|
+
}
|
|
79
|
+
if (str === 'string') {
|
|
80
|
+
return new ABIStringType();
|
|
81
|
+
}
|
|
82
|
+
if (str.length >= 2 && str[0] === '(' && str[str.length - 1] === ')') {
|
|
83
|
+
const tupleContent = ABITupleType.parseTupleContent(str.slice(1, str.length - 1));
|
|
84
|
+
const tupleTypes = [];
|
|
85
|
+
for (let i = 0; i < tupleContent.length; i++) {
|
|
86
|
+
const ti = ABIType.from(tupleContent[i]);
|
|
87
|
+
tupleTypes.push(ti);
|
|
88
|
+
}
|
|
89
|
+
return new ABITupleType(tupleTypes);
|
|
90
|
+
}
|
|
91
|
+
throw new Error(`cannot convert a string ${str} to an ABI type`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export class ABIUintType extends ABIType {
|
|
95
|
+
constructor(size) {
|
|
96
|
+
super();
|
|
97
|
+
if (size % 8 !== 0 || size < 8 || size > 512) {
|
|
98
|
+
throw new Error(`unsupported uint type bitSize: ${size}`);
|
|
99
|
+
}
|
|
100
|
+
this.bitSize = size;
|
|
101
|
+
}
|
|
102
|
+
toString() {
|
|
103
|
+
return `uint${this.bitSize}`;
|
|
104
|
+
}
|
|
105
|
+
equals(other) {
|
|
106
|
+
return other instanceof ABIUintType && this.bitSize === other.bitSize;
|
|
107
|
+
}
|
|
108
|
+
isDynamic() {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
byteLen() {
|
|
112
|
+
return this.bitSize / 8;
|
|
113
|
+
}
|
|
114
|
+
encode(value) {
|
|
115
|
+
if (typeof value !== 'bigint' && typeof value !== 'number') {
|
|
116
|
+
throw new Error(`Cannot encode value as uint${this.bitSize}: ${value}`);
|
|
117
|
+
}
|
|
118
|
+
if (value >= BigInt(2 ** this.bitSize) || value < BigInt(0)) {
|
|
119
|
+
throw new Error(`${value} is not a non-negative int or too big to fit in size uint${this.bitSize}`);
|
|
120
|
+
}
|
|
121
|
+
if (typeof value === 'number' && !Number.isSafeInteger(value)) {
|
|
122
|
+
throw new Error(`${value} should be converted into a BigInt before it is encoded`);
|
|
123
|
+
}
|
|
124
|
+
return bigIntToBytes(value, this.bitSize / 8);
|
|
125
|
+
}
|
|
126
|
+
decode(byteString) {
|
|
127
|
+
if (byteString.length !== this.bitSize / 8) {
|
|
128
|
+
throw new Error(`byte string must correspond to a uint${this.bitSize}`);
|
|
129
|
+
}
|
|
130
|
+
return bytesToBigInt(byteString);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
export class ABIUfixedType extends ABIType {
|
|
134
|
+
constructor(size, denominator) {
|
|
135
|
+
super();
|
|
136
|
+
if (size % 8 !== 0 || size < 8 || size > 512) {
|
|
137
|
+
throw new Error(`unsupported ufixed type bitSize: ${size}`);
|
|
138
|
+
}
|
|
139
|
+
if (denominator > 160 || denominator < 1) {
|
|
140
|
+
throw new Error(`unsupported ufixed type precision: ${denominator}`);
|
|
141
|
+
}
|
|
142
|
+
this.bitSize = size;
|
|
143
|
+
this.precision = denominator;
|
|
144
|
+
}
|
|
145
|
+
toString() {
|
|
146
|
+
return `ufixed${this.bitSize}x${this.precision}`;
|
|
147
|
+
}
|
|
148
|
+
equals(other) {
|
|
149
|
+
return (other instanceof ABIUfixedType &&
|
|
150
|
+
this.bitSize === other.bitSize &&
|
|
151
|
+
this.precision === other.precision);
|
|
152
|
+
}
|
|
153
|
+
isDynamic() {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
byteLen() {
|
|
157
|
+
return this.bitSize / 8;
|
|
158
|
+
}
|
|
159
|
+
encode(value) {
|
|
160
|
+
if (typeof value !== 'bigint' && typeof value !== 'number') {
|
|
161
|
+
throw new Error(`Cannot encode value as ${this.toString()}: ${value}`);
|
|
162
|
+
}
|
|
163
|
+
if (value >= BigInt(2 ** this.bitSize) || value < BigInt(0)) {
|
|
164
|
+
throw new Error(`${value} is not a non-negative int or too big to fit in size ${this.toString()}`);
|
|
165
|
+
}
|
|
166
|
+
if (typeof value === 'number' && !Number.isSafeInteger(value)) {
|
|
167
|
+
throw new Error(`${value} should be converted into a BigInt before it is encoded`);
|
|
168
|
+
}
|
|
169
|
+
return bigIntToBytes(value, this.bitSize / 8);
|
|
170
|
+
}
|
|
171
|
+
decode(byteString) {
|
|
172
|
+
if (byteString.length !== this.bitSize / 8) {
|
|
173
|
+
throw new Error(`byte string must correspond to a ${this.toString()}`);
|
|
174
|
+
}
|
|
175
|
+
return bytesToBigInt(byteString);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
export class ABIAddressType extends ABIType {
|
|
179
|
+
toString() {
|
|
180
|
+
return 'address';
|
|
181
|
+
}
|
|
182
|
+
equals(other) {
|
|
183
|
+
return other instanceof ABIAddressType;
|
|
184
|
+
}
|
|
185
|
+
isDynamic() {
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
byteLen() {
|
|
189
|
+
return ADDR_BYTE_SIZE;
|
|
190
|
+
}
|
|
191
|
+
encode(value) {
|
|
192
|
+
if (typeof value !== 'string' && !(value instanceof Uint8Array)) {
|
|
193
|
+
throw new Error(`Cannot encode value as ${this.toString()}: ${value}`);
|
|
194
|
+
}
|
|
195
|
+
if (typeof value === 'string') {
|
|
196
|
+
const decodedAddress = decodeAddress(value);
|
|
197
|
+
return decodedAddress.publicKey;
|
|
198
|
+
}
|
|
199
|
+
// Return the address if it is already in bytes
|
|
200
|
+
if (value.byteLength !== 32) {
|
|
201
|
+
throw new Error(`byte string must be 32 bytes long for an address`);
|
|
202
|
+
}
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
decode(byteString) {
|
|
206
|
+
if (byteString.byteLength !== 32) {
|
|
207
|
+
throw new Error(`byte string must be 32 bytes long for an address`);
|
|
208
|
+
}
|
|
209
|
+
return encodeAddress(byteString);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
export class ABIBoolType extends ABIType {
|
|
213
|
+
toString() {
|
|
214
|
+
return 'bool';
|
|
215
|
+
}
|
|
216
|
+
equals(other) {
|
|
217
|
+
return other instanceof ABIBoolType;
|
|
218
|
+
}
|
|
219
|
+
isDynamic() {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
byteLen() {
|
|
223
|
+
return SINGLE_BOOL_SIZE;
|
|
224
|
+
}
|
|
225
|
+
encode(value) {
|
|
226
|
+
if (typeof value !== 'boolean') {
|
|
227
|
+
throw new Error(`Cannot encode value as bool: ${value}`);
|
|
228
|
+
}
|
|
229
|
+
if (value) {
|
|
230
|
+
return new Uint8Array([128]);
|
|
231
|
+
}
|
|
232
|
+
return new Uint8Array([0]);
|
|
233
|
+
}
|
|
234
|
+
decode(byteString) {
|
|
235
|
+
if (byteString.byteLength !== 1) {
|
|
236
|
+
throw new Error(`bool string must be 1 byte long`);
|
|
237
|
+
}
|
|
238
|
+
const value = byteString[0];
|
|
239
|
+
if (value === 128) {
|
|
240
|
+
return true;
|
|
241
|
+
}
|
|
242
|
+
if (value === 0) {
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
throw new Error(`boolean could not be decoded from the byte string`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
export class ABIByteType extends ABIType {
|
|
249
|
+
toString() {
|
|
250
|
+
return 'byte';
|
|
251
|
+
}
|
|
252
|
+
equals(other) {
|
|
253
|
+
return other instanceof ABIByteType;
|
|
254
|
+
}
|
|
255
|
+
isDynamic() {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
byteLen() {
|
|
259
|
+
return SINGLE_BYTE_SIZE;
|
|
260
|
+
}
|
|
261
|
+
encode(value) {
|
|
262
|
+
if (typeof value !== 'number' && typeof value !== 'bigint') {
|
|
263
|
+
throw new Error(`Cannot encode value as byte: ${value}`);
|
|
264
|
+
}
|
|
265
|
+
if (typeof value === 'bigint') {
|
|
266
|
+
// eslint-disable-next-line no-param-reassign
|
|
267
|
+
value = Number(value);
|
|
268
|
+
}
|
|
269
|
+
if (value < 0 || value > 255) {
|
|
270
|
+
throw new Error(`${value} cannot be encoded into a byte`);
|
|
271
|
+
}
|
|
272
|
+
return new Uint8Array([value]);
|
|
273
|
+
}
|
|
274
|
+
decode(byteString) {
|
|
275
|
+
if (byteString.byteLength !== 1) {
|
|
276
|
+
throw new Error(`byte string must be 1 byte long`);
|
|
277
|
+
}
|
|
278
|
+
return byteString[0];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
export class ABIStringType extends ABIType {
|
|
282
|
+
toString() {
|
|
283
|
+
return 'string';
|
|
284
|
+
}
|
|
285
|
+
equals(other) {
|
|
286
|
+
return other instanceof ABIStringType;
|
|
287
|
+
}
|
|
288
|
+
isDynamic() {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
byteLen() {
|
|
292
|
+
throw new Error(`${this.toString()} is a dynamic type`);
|
|
293
|
+
}
|
|
294
|
+
encode(value) {
|
|
295
|
+
if (typeof value !== 'string' && !(value instanceof Uint8Array)) {
|
|
296
|
+
throw new Error(`Cannot encode value as string: ${value}`);
|
|
297
|
+
}
|
|
298
|
+
const encodedBytes = Buffer.from(value);
|
|
299
|
+
const encodedLength = bigIntToBytes(value.length, LENGTH_ENCODE_BYTE_SIZE);
|
|
300
|
+
const mergedBytes = new Uint8Array(value.length + LENGTH_ENCODE_BYTE_SIZE);
|
|
301
|
+
mergedBytes.set(encodedLength);
|
|
302
|
+
mergedBytes.set(encodedBytes, LENGTH_ENCODE_BYTE_SIZE);
|
|
303
|
+
return mergedBytes;
|
|
304
|
+
}
|
|
305
|
+
decode(byteString) {
|
|
306
|
+
if (byteString.length < LENGTH_ENCODE_BYTE_SIZE) {
|
|
307
|
+
throw new Error(`byte string is too short to be decoded. Actual length is ${byteString.length}, but expected at least ${LENGTH_ENCODE_BYTE_SIZE}`);
|
|
308
|
+
}
|
|
309
|
+
const buf = Buffer.from(byteString);
|
|
310
|
+
const byteLength = buf.readUIntBE(0, LENGTH_ENCODE_BYTE_SIZE);
|
|
311
|
+
const byteValue = byteString.slice(LENGTH_ENCODE_BYTE_SIZE, byteString.length);
|
|
312
|
+
if (byteLength !== byteValue.length) {
|
|
313
|
+
throw new Error(`string length bytes do not match the actual length of string. Expected ${byteLength}, got ${byteValue.length}`);
|
|
314
|
+
}
|
|
315
|
+
return Buffer.from(byteValue).toString('utf-8');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
export class ABIArrayStaticType extends ABIType {
|
|
319
|
+
constructor(argType, arrayLength) {
|
|
320
|
+
super();
|
|
321
|
+
if (arrayLength < 1) {
|
|
322
|
+
throw new Error(`static array must have a length greater than 0: ${arrayLength}`);
|
|
323
|
+
}
|
|
324
|
+
this.childType = argType;
|
|
325
|
+
this.staticLength = arrayLength;
|
|
326
|
+
}
|
|
327
|
+
toString() {
|
|
328
|
+
return `${this.childType.toString()}[${this.staticLength}]`;
|
|
329
|
+
}
|
|
330
|
+
equals(other) {
|
|
331
|
+
return (other instanceof ABIArrayStaticType &&
|
|
332
|
+
this.staticLength === other.staticLength &&
|
|
333
|
+
this.childType.equals(other.childType));
|
|
334
|
+
}
|
|
335
|
+
isDynamic() {
|
|
336
|
+
return this.childType.isDynamic();
|
|
337
|
+
}
|
|
338
|
+
byteLen() {
|
|
339
|
+
if (this.childType.constructor === ABIBoolType) {
|
|
340
|
+
return Math.ceil(this.staticLength / 8);
|
|
341
|
+
}
|
|
342
|
+
return this.staticLength * this.childType.byteLen();
|
|
343
|
+
}
|
|
344
|
+
encode(value) {
|
|
345
|
+
if (!Array.isArray(value) && !(value instanceof Uint8Array)) {
|
|
346
|
+
throw new Error(`Cannot encode value as ${this.toString()}: ${value}`);
|
|
347
|
+
}
|
|
348
|
+
if (value.length !== this.staticLength) {
|
|
349
|
+
throw new Error(`Value array does not match static array length. Expected ${this.staticLength}, got ${value.length}`);
|
|
350
|
+
}
|
|
351
|
+
const convertedTuple = this.toABITupleType();
|
|
352
|
+
return convertedTuple.encode(value);
|
|
353
|
+
}
|
|
354
|
+
decode(byteString) {
|
|
355
|
+
const convertedTuple = this.toABITupleType();
|
|
356
|
+
return convertedTuple.decode(byteString);
|
|
357
|
+
}
|
|
358
|
+
toABITupleType() {
|
|
359
|
+
return new ABITupleType(Array(this.staticLength).fill(this.childType));
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
export class ABIArrayDynamicType extends ABIType {
|
|
363
|
+
constructor(argType) {
|
|
364
|
+
super();
|
|
365
|
+
this.childType = argType;
|
|
366
|
+
}
|
|
367
|
+
toString() {
|
|
368
|
+
return `${this.childType.toString()}[]`;
|
|
369
|
+
}
|
|
370
|
+
equals(other) {
|
|
371
|
+
return (other instanceof ABIArrayDynamicType &&
|
|
372
|
+
this.childType.equals(other.childType));
|
|
373
|
+
}
|
|
374
|
+
isDynamic() {
|
|
375
|
+
return true;
|
|
376
|
+
}
|
|
377
|
+
byteLen() {
|
|
378
|
+
throw new Error(`${this.toString()} is a dynamic type`);
|
|
379
|
+
}
|
|
380
|
+
encode(value) {
|
|
381
|
+
if (!Array.isArray(value) && !(value instanceof Uint8Array)) {
|
|
382
|
+
throw new Error(`Cannot encode value as ${this.toString()}: ${value}`);
|
|
383
|
+
}
|
|
384
|
+
const convertedTuple = this.toABITupleType(value.length);
|
|
385
|
+
const encodedTuple = convertedTuple.encode(value);
|
|
386
|
+
const encodedLength = bigIntToBytes(convertedTuple.childTypes.length, LENGTH_ENCODE_BYTE_SIZE);
|
|
387
|
+
const mergedBytes = concatArrays(encodedLength, encodedTuple);
|
|
388
|
+
return mergedBytes;
|
|
389
|
+
}
|
|
390
|
+
decode(byteString) {
|
|
391
|
+
const buf = Buffer.from(byteString);
|
|
392
|
+
const byteLength = buf.readUIntBE(0, LENGTH_ENCODE_BYTE_SIZE);
|
|
393
|
+
const convertedTuple = this.toABITupleType(byteLength);
|
|
394
|
+
return convertedTuple.decode(byteString.slice(LENGTH_ENCODE_BYTE_SIZE, byteString.length));
|
|
395
|
+
}
|
|
396
|
+
toABITupleType(length) {
|
|
397
|
+
return new ABITupleType(Array(length).fill(this.childType));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
export class ABITupleType extends ABIType {
|
|
401
|
+
constructor(argTypes) {
|
|
402
|
+
super();
|
|
403
|
+
if (argTypes.length >= MAX_LEN) {
|
|
404
|
+
throw new Error('tuple type child type number larger than maximum uint16 error');
|
|
405
|
+
}
|
|
406
|
+
this.childTypes = argTypes;
|
|
407
|
+
}
|
|
408
|
+
toString() {
|
|
409
|
+
const typeStrings = [];
|
|
410
|
+
for (let i = 0; i < this.childTypes.length; i++) {
|
|
411
|
+
typeStrings[i] = this.childTypes[i].toString();
|
|
412
|
+
}
|
|
413
|
+
return `(${typeStrings.join(',')})`;
|
|
414
|
+
}
|
|
415
|
+
equals(other) {
|
|
416
|
+
return (other instanceof ABITupleType &&
|
|
417
|
+
this.childTypes.length === other.childTypes.length &&
|
|
418
|
+
this.childTypes.every((child, index) => child.equals(other.childTypes[index])));
|
|
419
|
+
}
|
|
420
|
+
isDynamic() {
|
|
421
|
+
const isDynamic = (child) => child.isDynamic();
|
|
422
|
+
return this.childTypes.some(isDynamic);
|
|
423
|
+
}
|
|
424
|
+
byteLen() {
|
|
425
|
+
let size = 0;
|
|
426
|
+
for (let i = 0; i < this.childTypes.length; i++) {
|
|
427
|
+
if (this.childTypes[i].constructor === ABIBoolType) {
|
|
428
|
+
const after = findBoolLR(this.childTypes, i, 1);
|
|
429
|
+
const boolNum = after + 1;
|
|
430
|
+
i += after;
|
|
431
|
+
size += Math.trunc((boolNum + 7) / 8);
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
const childByteSize = this.childTypes[i].byteLen();
|
|
435
|
+
size += childByteSize;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return size;
|
|
439
|
+
}
|
|
440
|
+
encode(value) {
|
|
441
|
+
if (!Array.isArray(value) && !(value instanceof Uint8Array)) {
|
|
442
|
+
throw new Error(`Cannot encode value as ${this.toString()}: ${value}`);
|
|
443
|
+
}
|
|
444
|
+
const values = Array.from(value);
|
|
445
|
+
if (value.length > MAX_LEN) {
|
|
446
|
+
throw new Error('length of tuple array should not exceed a uint16');
|
|
447
|
+
}
|
|
448
|
+
const tupleTypes = this.childTypes;
|
|
449
|
+
const heads = [];
|
|
450
|
+
const tails = [];
|
|
451
|
+
const isDynamicIndex = new Map();
|
|
452
|
+
let i = 0;
|
|
453
|
+
while (i < tupleTypes.length) {
|
|
454
|
+
const tupleType = tupleTypes[i];
|
|
455
|
+
if (tupleType.isDynamic()) {
|
|
456
|
+
// Head is not pre-determined for dynamic types; store a placeholder for now
|
|
457
|
+
isDynamicIndex.set(heads.length, true);
|
|
458
|
+
heads.push(new Uint8Array([0, 0]));
|
|
459
|
+
tails.push(tupleType.encode(values[i]));
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
if (tupleType.constructor === ABIBoolType) {
|
|
463
|
+
const before = findBoolLR(tupleTypes, i, -1);
|
|
464
|
+
let after = findBoolLR(tupleTypes, i, 1);
|
|
465
|
+
// Pack bytes to heads and tails
|
|
466
|
+
if (before % 8 !== 0) {
|
|
467
|
+
throw new Error('expected before index should have number of bool mod 8 equal 0');
|
|
468
|
+
}
|
|
469
|
+
after = Math.min(7, after);
|
|
470
|
+
const compressedInt = compressMultipleBool(values.slice(i, i + after + 1));
|
|
471
|
+
heads.push(bigIntToBytes(compressedInt, 1));
|
|
472
|
+
i += after;
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
const encodedTupleValue = tupleType.encode(values[i]);
|
|
476
|
+
heads.push(encodedTupleValue);
|
|
477
|
+
}
|
|
478
|
+
isDynamicIndex.set(i, false);
|
|
479
|
+
tails.push(new Uint8Array());
|
|
480
|
+
}
|
|
481
|
+
i += 1;
|
|
482
|
+
}
|
|
483
|
+
// Adjust head lengths for dynamic types
|
|
484
|
+
let headLength = 0;
|
|
485
|
+
for (const headElement of heads) {
|
|
486
|
+
headLength += headElement.length;
|
|
487
|
+
}
|
|
488
|
+
// encode any placeholders for dynamic types
|
|
489
|
+
let tailLength = 0;
|
|
490
|
+
for (let j = 0; j < heads.length; j++) {
|
|
491
|
+
if (isDynamicIndex.get(j)) {
|
|
492
|
+
const headValue = headLength + tailLength;
|
|
493
|
+
if (headValue > MAX_LEN) {
|
|
494
|
+
throw new Error(`byte length of ${headValue} should not exceed a uint16`);
|
|
495
|
+
}
|
|
496
|
+
heads[j] = bigIntToBytes(headValue, LENGTH_ENCODE_BYTE_SIZE);
|
|
497
|
+
}
|
|
498
|
+
tailLength += tails[j].length;
|
|
499
|
+
}
|
|
500
|
+
return concatArrays(...heads, ...tails);
|
|
501
|
+
}
|
|
502
|
+
decode(byteString) {
|
|
503
|
+
const tupleTypes = this.childTypes;
|
|
504
|
+
const dynamicSegments = [];
|
|
505
|
+
const valuePartition = [];
|
|
506
|
+
let i = 0;
|
|
507
|
+
let iterIndex = 0;
|
|
508
|
+
const buf = Buffer.from(byteString);
|
|
509
|
+
while (i < tupleTypes.length) {
|
|
510
|
+
const tupleType = tupleTypes[i];
|
|
511
|
+
if (tupleType.isDynamic()) {
|
|
512
|
+
if (byteString.slice(iterIndex, byteString.length).length <
|
|
513
|
+
LENGTH_ENCODE_BYTE_SIZE) {
|
|
514
|
+
throw new Error('dynamic type in tuple is too short to be decoded');
|
|
515
|
+
}
|
|
516
|
+
const dynamicIndex = buf.readUIntBE(iterIndex, LENGTH_ENCODE_BYTE_SIZE);
|
|
517
|
+
if (dynamicSegments.length > 0) {
|
|
518
|
+
dynamicSegments[dynamicSegments.length - 1].right = dynamicIndex;
|
|
519
|
+
// Check that right side of segment is greater than the left side
|
|
520
|
+
if (dynamicIndex < dynamicSegments[dynamicSegments.length - 1].left) {
|
|
521
|
+
throw new Error('dynamic index segment miscalculation: left is greater than right index');
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
// Since we do not know where the current dynamic element ends, put a placeholder and update later
|
|
525
|
+
const seg = {
|
|
526
|
+
left: dynamicIndex,
|
|
527
|
+
right: -1,
|
|
528
|
+
};
|
|
529
|
+
dynamicSegments.push(seg);
|
|
530
|
+
valuePartition.push(null);
|
|
531
|
+
iterIndex += LENGTH_ENCODE_BYTE_SIZE;
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
// eslint-disable-next-line no-lonely-if
|
|
535
|
+
if (tupleType.constructor === ABIBoolType) {
|
|
536
|
+
const before = findBoolLR(this.childTypes, i, -1);
|
|
537
|
+
let after = findBoolLR(this.childTypes, i, 1);
|
|
538
|
+
if (before % 8 !== 0) {
|
|
539
|
+
throw new Error('expected before bool number mod 8 === 0');
|
|
540
|
+
}
|
|
541
|
+
after = Math.min(7, after);
|
|
542
|
+
// Parse bool in a byte to multiple byte strings
|
|
543
|
+
for (let boolIndex = 0; boolIndex <= after; boolIndex++) {
|
|
544
|
+
const boolMask = 0x80 >> boolIndex;
|
|
545
|
+
if ((byteString[iterIndex] & boolMask) > 0) {
|
|
546
|
+
valuePartition.push(new Uint8Array([128]));
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
valuePartition.push(new Uint8Array([0]));
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
i += after;
|
|
553
|
+
iterIndex += 1;
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
const currLen = tupleType.byteLen();
|
|
557
|
+
valuePartition.push(byteString.slice(iterIndex, iterIndex + currLen));
|
|
558
|
+
iterIndex += currLen;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
if (i !== tupleTypes.length - 1 && iterIndex >= byteString.length) {
|
|
562
|
+
throw new Error('input byte not enough to decode');
|
|
563
|
+
}
|
|
564
|
+
i += 1;
|
|
565
|
+
}
|
|
566
|
+
if (dynamicSegments.length > 0) {
|
|
567
|
+
dynamicSegments[dynamicSegments.length - 1].right = byteString.length;
|
|
568
|
+
iterIndex = byteString.length;
|
|
569
|
+
}
|
|
570
|
+
if (iterIndex < byteString.length) {
|
|
571
|
+
throw new Error('input byte not fully consumed');
|
|
572
|
+
}
|
|
573
|
+
// Check segment indices are valid
|
|
574
|
+
// If the dynamic segment are not consecutive and well-ordered, we return error
|
|
575
|
+
for (let j = 0; j < dynamicSegments.length; j++) {
|
|
576
|
+
const seg = dynamicSegments[j];
|
|
577
|
+
if (seg.left > seg.right) {
|
|
578
|
+
throw new Error('dynamic segment should display a [l, r] space with l <= r');
|
|
579
|
+
}
|
|
580
|
+
if (j !== dynamicSegments.length - 1 &&
|
|
581
|
+
seg.right !== dynamicSegments[j + 1].left) {
|
|
582
|
+
throw new Error('dynamic segment should be consecutive');
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
// Check dynamic element partitions
|
|
586
|
+
let segIndex = 0;
|
|
587
|
+
for (let j = 0; j < tupleTypes.length; j++) {
|
|
588
|
+
if (tupleTypes[j].isDynamic()) {
|
|
589
|
+
valuePartition[j] = byteString.slice(dynamicSegments[segIndex].left, dynamicSegments[segIndex].right);
|
|
590
|
+
segIndex += 1;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
// Decode each tuple element
|
|
594
|
+
const returnValues = [];
|
|
595
|
+
for (let j = 0; j < tupleTypes.length; j++) {
|
|
596
|
+
const valueTi = tupleTypes[j].decode(valuePartition[j]);
|
|
597
|
+
returnValues.push(valueTi);
|
|
598
|
+
}
|
|
599
|
+
return returnValues;
|
|
600
|
+
}
|
|
601
|
+
static parseTupleContent(str) {
|
|
602
|
+
if (str.length === 0) {
|
|
603
|
+
return [];
|
|
604
|
+
}
|
|
605
|
+
if (str.endsWith(',') || str.startsWith(',')) {
|
|
606
|
+
throw new Error('tuple string should not start with comma');
|
|
607
|
+
}
|
|
608
|
+
if (str.includes(',,')) {
|
|
609
|
+
throw new Error('tuple string should not have consecutive commas');
|
|
610
|
+
}
|
|
611
|
+
const tupleStrings = [];
|
|
612
|
+
let depth = 0;
|
|
613
|
+
let word = '';
|
|
614
|
+
for (const char of str) {
|
|
615
|
+
word += char;
|
|
616
|
+
if (char === '(') {
|
|
617
|
+
depth += 1;
|
|
618
|
+
}
|
|
619
|
+
else if (char === ')') {
|
|
620
|
+
depth -= 1;
|
|
621
|
+
}
|
|
622
|
+
else if (char === ',') {
|
|
623
|
+
// If the comma is at depth 0, then append the word as token.
|
|
624
|
+
if (depth === 0) {
|
|
625
|
+
tupleStrings.push(word.slice(0, word.length - 1));
|
|
626
|
+
word = '';
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
if (word.length !== 0) {
|
|
631
|
+
tupleStrings.push(word);
|
|
632
|
+
}
|
|
633
|
+
if (depth !== 0) {
|
|
634
|
+
throw new Error('tuple string has mismatched parentheses');
|
|
635
|
+
}
|
|
636
|
+
return tupleStrings;
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
// compressMultipleBool compresses consecutive bool values into a byte in ABI tuple / array value.
|
|
640
|
+
function compressMultipleBool(valueList) {
|
|
641
|
+
let res = 0;
|
|
642
|
+
if (valueList.length > 8) {
|
|
643
|
+
throw new Error('value list passed in should be no greater than length 8');
|
|
644
|
+
}
|
|
645
|
+
for (let i = 0; i < valueList.length; i++) {
|
|
646
|
+
const boolVal = valueList[i];
|
|
647
|
+
if (typeof boolVal !== 'boolean') {
|
|
648
|
+
throw new Error('non-boolean values cannot be compressed into a byte');
|
|
649
|
+
}
|
|
650
|
+
if (boolVal) {
|
|
651
|
+
res |= 1 << (7 - i);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
return res;
|
|
655
|
+
}
|
|
656
|
+
// Assume that the current index on the list of type is an ABI bool type.
|
|
657
|
+
// It returns the difference between the current index and the index of the furthest consecutive Bool type.
|
|
658
|
+
function findBoolLR(typeList, index, delta) {
|
|
659
|
+
let until = 0;
|
|
660
|
+
while (true) {
|
|
661
|
+
const curr = index + delta * until;
|
|
662
|
+
if (typeList[curr].constructor === ABIBoolType) {
|
|
663
|
+
if (curr !== typeList.length - 1 && delta === 1) {
|
|
664
|
+
until += 1;
|
|
665
|
+
}
|
|
666
|
+
else if (curr > 0 && delta === -1) {
|
|
667
|
+
until += 1;
|
|
668
|
+
}
|
|
669
|
+
else {
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
until -= 1;
|
|
675
|
+
break;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
return until;
|
|
679
|
+
}
|
|
680
|
+
//# sourceMappingURL=abi_type.js.map
|