@defillama/sdk 5.0.236 → 5.0.240

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.
Files changed (131) hide show
  1. package/package.json +3 -3
  2. package/build/Balances.d.ts +0 -139
  3. package/build/Balances.js +0 -363
  4. package/build/ChainApi.d.ts +0 -142
  5. package/build/ChainApi.js +0 -297
  6. package/build/abi/abi2.d.ts +0 -5
  7. package/build/abi/abi2.js +0 -215
  8. package/build/abi/cachedABIs.d.ts +0 -4
  9. package/build/abi/cachedABIs.js +0 -8
  10. package/build/abi/convertResults.d.ts +0 -5
  11. package/build/abi/convertResults.js +0 -60
  12. package/build/abi/index.d.ts +0 -31
  13. package/build/abi/index.js +0 -327
  14. package/build/abi/multicall.d.ts +0 -23
  15. package/build/abi/multicall.js +0 -382
  16. package/build/abi/multicall3.d.ts +0 -7
  17. package/build/abi/multicall3.js +0 -397
  18. package/build/abi/rpcCall.d.ts +0 -4
  19. package/build/abi/rpcCall.js +0 -62
  20. package/build/abi/tron.d.ts +0 -33
  21. package/build/abi/tron.js +0 -110
  22. package/build/api.d.ts +0 -10
  23. package/build/api.js +0 -45
  24. package/build/api2.d.ts +0 -5
  25. package/build/api2.js +0 -41
  26. package/build/chains/algorand.d.ts +0 -277
  27. package/build/chains/algorand.js +0 -618
  28. package/build/chains/aptos.d.ts +0 -230
  29. package/build/chains/aptos.js +0 -612
  30. package/build/chains/cardano.d.ts +0 -242
  31. package/build/chains/cardano.js +0 -407
  32. package/build/chains/cosmos.d.ts +0 -252
  33. package/build/chains/cosmos.js +0 -618
  34. package/build/chains/icp.d.ts +0 -235
  35. package/build/chains/icp.js +0 -1040
  36. package/build/chains/index.d.ts +0 -23
  37. package/build/chains/index.js +0 -59
  38. package/build/chains/near.d.ts +0 -192
  39. package/build/chains/near.js +0 -446
  40. package/build/chains/rpc.d.ts +0 -125
  41. package/build/chains/rpc.js +0 -326
  42. package/build/chains/starknet.d.ts +0 -205
  43. package/build/chains/starknet.js +0 -884
  44. package/build/chains/stellar.d.ts +0 -410
  45. package/build/chains/stellar.js +0 -1082
  46. package/build/chains/substrate.d.ts +0 -333
  47. package/build/chains/substrate.js +0 -1042
  48. package/build/chains/sui.d.ts +0 -365
  49. package/build/chains/sui.js +0 -1135
  50. package/build/chains/svm.d.ts +0 -340
  51. package/build/chains/svm.js +0 -760
  52. package/build/chains/tezos.d.ts +0 -225
  53. package/build/chains/tezos.js +0 -412
  54. package/build/chains/ton.d.ts +0 -353
  55. package/build/chains/ton.js +0 -788
  56. package/build/chains/tron.d.ts +0 -45
  57. package/build/chains/tron.js +0 -110
  58. package/build/chains/utxo.d.ts +0 -202
  59. package/build/chains/utxo.js +0 -592
  60. package/build/chains/xrpl.d.ts +0 -179
  61. package/build/chains/xrpl.js +0 -467
  62. package/build/computeTVL/blocks.d.ts +0 -1
  63. package/build/computeTVL/blocks.js +0 -12
  64. package/build/computeTVL/humanizeNumber.d.ts +0 -1
  65. package/build/computeTVL/humanizeNumber.js +0 -19
  66. package/build/erc20/index.d.ts +0 -31
  67. package/build/erc20/index.js +0 -56
  68. package/build/eth/index.d.ts +0 -22
  69. package/build/eth/index.js +0 -118
  70. package/build/general.d.ts +0 -5
  71. package/build/general.js +0 -20
  72. package/build/generalUtil.d.ts +0 -8
  73. package/build/generalUtil.js +0 -73
  74. package/build/index.d.ts +0 -32
  75. package/build/index.js +0 -74
  76. package/build/providers.json +0 -1
  77. package/build/types.d.ts +0 -76
  78. package/build/types.js +0 -2
  79. package/build/util/LlamaProvider.d.ts +0 -46
  80. package/build/util/LlamaProvider.js +0 -365
  81. package/build/util/blocks.d.ts +0 -36
  82. package/build/util/blocks.js +0 -292
  83. package/build/util/cache.d.ts +0 -45
  84. package/build/util/cache.js +0 -309
  85. package/build/util/chainUtils/data.json +0 -1356
  86. package/build/util/chainUtils/index.d.ts +0 -11
  87. package/build/util/chainUtils/index.js +0 -136
  88. package/build/util/coins.d.ts +0 -19
  89. package/build/util/coins.js +0 -113
  90. package/build/util/common.d.ts +0 -34
  91. package/build/util/common.js +0 -373
  92. package/build/util/computeTVL.d.ts +0 -19
  93. package/build/util/computeTVL.js +0 -102
  94. package/build/util/cosmos.d.ts +0 -1
  95. package/build/util/cosmos.js +0 -8
  96. package/build/util/debugLog.d.ts +0 -4
  97. package/build/util/debugLog.js +0 -18
  98. package/build/util/discord.d.ts +0 -1
  99. package/build/util/discord.js +0 -33
  100. package/build/util/elastic.d.ts +0 -43
  101. package/build/util/elastic.js +0 -113
  102. package/build/util/env.d.ts +0 -19
  103. package/build/util/env.js +0 -158
  104. package/build/util/graph.d.ts +0 -8
  105. package/build/util/graph.js +0 -50
  106. package/build/util/index.d.ts +0 -32
  107. package/build/util/index.js +0 -227
  108. package/build/util/indexer.compatibility.d.ts +0 -6
  109. package/build/util/indexer.compatibility.js +0 -64
  110. package/build/util/indexer.d.ts +0 -92
  111. package/build/util/indexer.js +0 -744
  112. package/build/util/indexerSql.d.ts +0 -9
  113. package/build/util/indexerSql.js +0 -102
  114. package/build/util/internal-cache.d.ts +0 -11
  115. package/build/util/internal-cache.js +0 -77
  116. package/build/util/logs.d.ts +0 -55
  117. package/build/util/logs.decode.shared.d.ts +0 -8
  118. package/build/util/logs.decode.shared.js +0 -289
  119. package/build/util/logs.js +0 -401
  120. package/build/util/promisePool.d.ts +0 -8
  121. package/build/util/promisePool.js +0 -31
  122. package/build/util/r2.d.ts +0 -4
  123. package/build/util/r2.js +0 -52
  124. package/build/util/removeRedundantRPCs.d.ts +0 -1
  125. package/build/util/removeRedundantRPCs.js +0 -49
  126. package/build/util/transactions.d.ts +0 -35
  127. package/build/util/transactions.js +0 -22
  128. package/build/util/updateChainLabels.d.ts +0 -1
  129. package/build/util/updateChainLabels.js +0 -5
  130. package/build/util/updateProviderList.d.ts +0 -1
  131. package/build/util/updateProviderList.js +0 -274
@@ -1,1040 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.IcpRejectError = exports.CANDID_TYPE = exports.ANONYMOUS_SENDER = exports.EMPTY_ARGS = exports.ICP_LEDGER = exports.DEFAULT_ENDPOINTS = exports.CHAIN = void 0;
4
- exports.encodeCborHead = encodeCborHead;
5
- exports.encodeCbor = encodeCbor;
6
- exports.decodeCbor = decodeCbor;
7
- exports.decodeUleb128 = decodeUleb128;
8
- exports.decodeSleb128 = decodeSleb128;
9
- exports.encodeUleb128 = encodeUleb128;
10
- exports.encodeSleb128 = encodeSleb128;
11
- exports.hashCandidLabel = hashCandidLabel;
12
- exports.buildLabelHashMap = buildLabelHashMap;
13
- exports.decodeCandid = decodeCandid;
14
- exports.encodeCandid = encodeCandid;
15
- exports.toBytes = toBytes;
16
- exports.crc32 = crc32;
17
- exports.bytesToBase32 = bytesToBase32;
18
- exports.base32ToBytes = base32ToBytes;
19
- exports.principalBytesToText = principalBytesToText;
20
- exports.principalTextToBytes = principalTextToBytes;
21
- exports.isPrincipal = isPrincipal;
22
- exports.accountIdentifierFromPrincipal = accountIdentifierFromPrincipal;
23
- exports.getEndpoints = getEndpoints;
24
- exports.queryCanister = queryCanister;
25
- exports.queryCanisterDecoded = queryCanisterDecoded;
26
- exports.callCandid = callCandid;
27
- exports.getIcrcMetadata = getIcrcMetadata;
28
- exports.getIcrcDecimals = getIcrcDecimals;
29
- exports.getIcrcSymbol = getIcrcSymbol;
30
- exports.getIcrcName = getIcrcName;
31
- exports.getIcrcTotalSupply = getIcrcTotalSupply;
32
- exports.getIcrcBalance = getIcrcBalance;
33
- exports.getIcpAccountBalance = getIcpAccountBalance;
34
- /**
35
- * Internet Computer (ICP) query client with a hand-rolled CBOR / Candid / Principal codec.
36
- *
37
- * Replaces (and unifies) the ad-hoc ICP helpers spread across the llama repos:
38
- * - DefiLlama-Adapters `projects/helper/chain/icp.js` (encodeCbor, decodeCbor, LEB128, decodeCandid,
39
- * hashCandidLabel, principal text <-> bytes, queryCanister; used by liquidium, onesec)
40
- * - dimension-adapters `helpers/icp.ts` (TS port of the above + queryCanisterDecoded; used by dexs/ICDex)
41
- *
42
- * What is new compared to those helpers:
43
- * - `queryCanister` accepts an `arg` (Candid encoded) so methods with parameters can be queried
44
- * (`icrc1_balance_of`, `account_balance`, ...). Zero-arg calls behave exactly as before.
45
- * - A minimal Candid *encoder* (`encodeCandid`) covering the primitive types plus `opt`, `vec`,
46
- * `record` and `variant`, enough for ICRC-1 / ICRC-2 queries.
47
- * - CBOR encoder supports negative integers, LEB128 encoders, base32 decoder, principal checksum
48
- * verification, `isPrincipal`, `accountIdentifierFromPrincipal` (ICP ledger account ids).
49
- * - ICRC helpers (`getIcrcMetadata`, `getIcrcDecimals`, `getIcrcSymbol`, `getIcrcTotalSupply`,
50
- * `getIcrcBalance`) and `getIcpAccountBalance` for the ICP ledger.
51
- *
52
- * Transport: requests go through the shared `httpPost` (endpoint rotation + retry on transport
53
- * errors) and a shared p-limit(10) limiter (`ICP_RPC_CONCURRENCY` overrides it). `ICP_RPC` (comma
54
- * separated) overrides the default boundary node list. Canister rejects are NOT retried and are
55
- * surfaced as `IcpRejectError` with `rejectCode` / `errorCode` so callers can tell a permanently
56
- * dead canister (`IC0537`, no Wasm module installed) from a transient failure.
57
- *
58
- * Only anonymous query calls are supported (no update calls, no identities), which is all the
59
- * llama adapters need.
60
- *
61
- * Usage:
62
- * `sdk.chains.icp.getIcrcBalance({ ledger: 'mxzaz-hqaaa-aaaar-qaada-cai', owner: 'mqygn-kiaaa-aaaar-qaadq-cai' })`
63
- * `sdk.chains.icp.queryCanisterDecoded({ canisterId, method: 'stats', labels: ['vol24h'] })`
64
- */
65
- const crypto_1 = require("crypto");
66
- const debugLog_1 = require("../util/debugLog");
67
- const rpc_1 = require("./rpc");
68
- exports.CHAIN = 'icp';
69
- exports.DEFAULT_ENDPOINTS = [
70
- 'https://icp-api.io',
71
- 'https://ic0.app',
72
- ];
73
- /** ICP ledger canister */
74
- exports.ICP_LEDGER = 'ryjl3-tyaaa-aaaaa-aaaba-cai';
75
- const DEFAULT_TIMEOUT = 30000;
76
- const CONCURRENCY = 10;
77
- const INGRESS_EXPIRY_MS = 5 * 60 * 1000;
78
- /** Candid encoding of an empty argument list: "DIDL" + 0 types + 0 args */
79
- exports.EMPTY_ARGS = Buffer.from([0x44, 0x49, 0x44, 0x4c, 0x00, 0x00]);
80
- /** anonymous principal (0x04) */
81
- exports.ANONYMOUS_SENDER = Buffer.from([0x04]);
82
- // bigint literals need es2020, so build the constants at runtime
83
- const B0 = BigInt(0);
84
- const B1 = BigInt(1);
85
- const B7 = BigInt(7);
86
- const B8 = BigInt(8);
87
- const B24 = BigInt(24);
88
- const B0x40 = BigInt(0x40);
89
- const B0x7f = BigInt(0x7f);
90
- const B0xff = BigInt(0xff);
91
- const B0xffff = BigInt(0xffff);
92
- const B0xffffffff = BigInt(0xffffffff);
93
- const MAX_U64 = BigInt('18446744073709551615');
94
- const NEG1 = BigInt(-1);
95
- const MAX_SAFE_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
96
- const MIN_SAFE_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
97
- const NANOS_PER_MS = BigInt(1000000);
98
- // ---------------------------------------------------------------------------
99
- // CBOR encoder
100
- // ---------------------------------------------------------------------------
101
- /** Encode a CBOR item head: major type (0-7) + unsigned argument. */
102
- function encodeCborHead(major, value) {
103
- const n = BigInt(value);
104
- if (n < B0)
105
- throw new Error('CBOR head argument must be non-negative');
106
- if (n > MAX_U64)
107
- throw new Error(`CBOR head argument exceeds 64 bits: ${n}`);
108
- if (n < B24)
109
- return Buffer.from([(major << 5) | Number(n)]);
110
- if (n <= B0xff)
111
- return Buffer.from([(major << 5) | 24, Number(n)]);
112
- if (n <= B0xffff)
113
- return Buffer.from([(major << 5) | 25, Number((n >> B8) & B0xff), Number(n & B0xff)]);
114
- if (n <= B0xffffffff)
115
- return Buffer.from([
116
- (major << 5) | 26,
117
- Number((n >> BigInt(24)) & B0xff),
118
- Number((n >> BigInt(16)) & B0xff),
119
- Number((n >> B8) & B0xff),
120
- Number(n & B0xff),
121
- ]);
122
- const out = Buffer.alloc(9);
123
- out[0] = (major << 5) | 27;
124
- for (let i = 0; i < 8; i++)
125
- out[1 + i] = Number((n >> BigInt(56 - i * 8)) & B0xff);
126
- return out;
127
- }
128
- /**
129
- * Encode a JS value as CBOR. Supports null, booleans, integers (number / bigint, negative too),
130
- * byte strings (Buffer / Uint8Array), text, arrays and plain objects (keys encoded as text, in
131
- * insertion order). Floats are rejected: the IC request format never needs them.
132
- */
133
- function encodeCbor(value) {
134
- if (value === null || value === undefined)
135
- return Buffer.from([0xf6]);
136
- if (value === false)
137
- return Buffer.from([0xf4]);
138
- if (value === true)
139
- return Buffer.from([0xf5]);
140
- if (typeof value === 'number') {
141
- if (!Number.isInteger(value))
142
- throw new Error('CBOR encoder only supports integers');
143
- return encodeCbor(BigInt(value));
144
- }
145
- if (typeof value === 'bigint') {
146
- if (value < B0)
147
- return encodeCborHead(1, NEG1 - value);
148
- return encodeCborHead(0, value);
149
- }
150
- if (Buffer.isBuffer(value) || value instanceof Uint8Array) {
151
- const bytes = Buffer.from(value);
152
- return Buffer.concat([encodeCborHead(2, bytes.length), bytes]);
153
- }
154
- if (typeof value === 'string') {
155
- const bytes = Buffer.from(value, 'utf8');
156
- return Buffer.concat([encodeCborHead(3, bytes.length), bytes]);
157
- }
158
- if (Array.isArray(value))
159
- return Buffer.concat([encodeCborHead(4, value.length), ...value.map(encodeCbor)]);
160
- if (typeof value === 'object') {
161
- const keys = Object.keys(value);
162
- const chunks = [encodeCborHead(5, keys.length)];
163
- for (const key of keys) {
164
- chunks.push(encodeCbor(key));
165
- chunks.push(encodeCbor(value[key]));
166
- }
167
- return Buffer.concat(chunks);
168
- }
169
- throw new Error(`Unsupported CBOR value type: ${typeof value}`);
170
- }
171
- // ---------------------------------------------------------------------------
172
- // CBOR decoder
173
- // ---------------------------------------------------------------------------
174
- function readCborUint(bytes, state, additionalInfo) {
175
- if (additionalInfo < 24)
176
- return BigInt(additionalInfo);
177
- if (additionalInfo === 24)
178
- return BigInt(bytes[state.i++]);
179
- if (additionalInfo === 25) {
180
- const out = (BigInt(bytes[state.i]) << B8) | BigInt(bytes[state.i + 1]);
181
- state.i += 2;
182
- return out;
183
- }
184
- if (additionalInfo === 26) {
185
- const out = (BigInt(bytes[state.i]) << BigInt(24)) |
186
- (BigInt(bytes[state.i + 1]) << BigInt(16)) |
187
- (BigInt(bytes[state.i + 2]) << B8) |
188
- BigInt(bytes[state.i + 3]);
189
- state.i += 4;
190
- return out;
191
- }
192
- if (additionalInfo === 27) {
193
- let out = B0;
194
- for (let i = 0; i < 8; i++)
195
- out = (out << B8) | BigInt(bytes[state.i++]);
196
- return out;
197
- }
198
- throw new Error(`Unsupported CBOR additional info ${additionalInfo}`);
199
- }
200
- /**
201
- * Decode one CBOR item starting at `state.i` (default: the start of `bytes`).
202
- * Integers within the safe range decode to `number`, larger ones to `bigint`; byte strings to
203
- * `Uint8Array`; maps to plain objects. Tags are skipped (the IC self-describe tag 55799 included).
204
- */
205
- function decodeCbor(bytes, state = { i: 0 }) {
206
- if (state.i >= bytes.length)
207
- throw new Error('Unexpected end of CBOR input');
208
- const first = bytes[state.i++];
209
- const major = first >> 5;
210
- const additionalInfo = first & 0x1f;
211
- if (major === 0) {
212
- const out = readCborUint(bytes, state, additionalInfo);
213
- return out <= MAX_SAFE_BIGINT ? Number(out) : out;
214
- }
215
- if (major === 1) {
216
- const out = NEG1 - readCborUint(bytes, state, additionalInfo);
217
- return out >= MIN_SAFE_BIGINT ? Number(out) : out;
218
- }
219
- if (major === 2) {
220
- if (additionalInfo === 31) {
221
- const parts = [];
222
- while (bytes[state.i] !== 0xff)
223
- parts.push(Buffer.from(decodeCbor(bytes, state)));
224
- state.i += 1;
225
- return Buffer.concat(parts);
226
- }
227
- const length = Number(readCborUint(bytes, state, additionalInfo));
228
- const out = bytes.slice(state.i, state.i + length);
229
- state.i += length;
230
- return out;
231
- }
232
- if (major === 3) {
233
- if (additionalInfo === 31) {
234
- let out = '';
235
- while (bytes[state.i] !== 0xff)
236
- out += decodeCbor(bytes, state);
237
- state.i += 1;
238
- return out;
239
- }
240
- const length = Number(readCborUint(bytes, state, additionalInfo));
241
- const out = Buffer.from(bytes.slice(state.i, state.i + length)).toString('utf8');
242
- state.i += length;
243
- return out;
244
- }
245
- if (major === 4) {
246
- if (additionalInfo === 31) {
247
- const out = [];
248
- while (bytes[state.i] !== 0xff)
249
- out.push(decodeCbor(bytes, state));
250
- state.i += 1;
251
- return out;
252
- }
253
- const length = Number(readCborUint(bytes, state, additionalInfo));
254
- const out = [];
255
- for (let i = 0; i < length; i++)
256
- out.push(decodeCbor(bytes, state));
257
- return out;
258
- }
259
- if (major === 5) {
260
- if (additionalInfo === 31) {
261
- const out = {};
262
- while (bytes[state.i] !== 0xff) {
263
- const key = decodeCbor(bytes, state);
264
- out[key] = decodeCbor(bytes, state);
265
- }
266
- state.i += 1;
267
- return out;
268
- }
269
- const length = Number(readCborUint(bytes, state, additionalInfo));
270
- const out = {};
271
- for (let i = 0; i < length; i++) {
272
- const key = decodeCbor(bytes, state);
273
- out[key] = decodeCbor(bytes, state);
274
- }
275
- return out;
276
- }
277
- if (major === 6) {
278
- readCborUint(bytes, state, additionalInfo); // tag number, ignored
279
- return decodeCbor(bytes, state);
280
- }
281
- if (major === 7) {
282
- if (additionalInfo === 20)
283
- return false;
284
- if (additionalInfo === 21)
285
- return true;
286
- if (additionalInfo === 22)
287
- return null;
288
- if (additionalInfo === 23)
289
- return undefined;
290
- if (additionalInfo === 26) {
291
- const out = Buffer.from(bytes.slice(state.i, state.i + 4)).readFloatBE(0);
292
- state.i += 4;
293
- return out;
294
- }
295
- if (additionalInfo === 27) {
296
- const out = Buffer.from(bytes.slice(state.i, state.i + 8)).readDoubleBE(0);
297
- state.i += 8;
298
- return out;
299
- }
300
- }
301
- throw new Error(`Unsupported CBOR major type ${major} with additional info ${additionalInfo}`);
302
- }
303
- // ---------------------------------------------------------------------------
304
- // LEB128
305
- // ---------------------------------------------------------------------------
306
- /** Read an unsigned LEB128 integer at `state.i`, advancing the cursor. */
307
- function decodeUleb128(bytes, state) {
308
- let out = B0;
309
- let shift = B0;
310
- while (true) {
311
- if (state.i >= bytes.length)
312
- throw new Error('Unexpected end of LEB128 input');
313
- const byte = bytes[state.i++];
314
- out |= BigInt(byte & 0x7f) << shift;
315
- if ((byte & 0x80) === 0)
316
- return out;
317
- shift += B7;
318
- }
319
- }
320
- /** Read a signed LEB128 integer at `state.i`, advancing the cursor. */
321
- function decodeSleb128(bytes, state) {
322
- let out = B0;
323
- let shift = B0;
324
- let byte = 0;
325
- while (true) {
326
- if (state.i >= bytes.length)
327
- throw new Error('Unexpected end of LEB128 input');
328
- byte = bytes[state.i++];
329
- out |= BigInt(byte & 0x7f) << shift;
330
- shift += B7;
331
- if ((byte & 0x80) === 0)
332
- break;
333
- }
334
- if (byte & 0x40)
335
- out |= NEG1 << shift;
336
- return out;
337
- }
338
- /** Encode a non-negative integer as unsigned LEB128. */
339
- function encodeUleb128(value) {
340
- let n = BigInt(value);
341
- if (n < B0)
342
- throw new Error(`uleb128: value must be non-negative, got ${value}`);
343
- const out = [];
344
- do {
345
- let byte = Number(n & B0x7f);
346
- n >>= B7;
347
- if (n !== B0)
348
- byte |= 0x80;
349
- out.push(byte);
350
- } while (n !== B0);
351
- return Buffer.from(out);
352
- }
353
- /** Encode an integer as signed LEB128. */
354
- function encodeSleb128(value) {
355
- let n = BigInt(value);
356
- const out = [];
357
- while (true) {
358
- const byte = Number(n & B0x7f);
359
- n >>= B7;
360
- const signBitClear = (byte & 0x40) === 0;
361
- const done = (n === B0 && signBitClear) || (n === NEG1 && !signBitClear);
362
- out.push(done ? byte : byte | 0x80);
363
- if (done)
364
- break;
365
- }
366
- return Buffer.from(out);
367
- }
368
- // ---------------------------------------------------------------------------
369
- // Candid
370
- // ---------------------------------------------------------------------------
371
- /** Candid type opcodes (negative sleb128 in the type table) */
372
- exports.CANDID_TYPE = {
373
- null: -1,
374
- bool: -2,
375
- nat: -3,
376
- int: -4,
377
- nat8: -5,
378
- nat16: -6,
379
- nat32: -7,
380
- nat64: -8,
381
- int8: -9,
382
- int16: -10,
383
- int32: -11,
384
- int64: -12,
385
- float32: -13,
386
- float64: -14,
387
- text: -15,
388
- reserved: -16,
389
- empty: -17,
390
- opt: -18,
391
- vec: -19,
392
- record: -20,
393
- variant: -21,
394
- func: -22,
395
- service: -23,
396
- principal: -24,
397
- };
398
- /**
399
- * Candid identifies a record field by a hash of its name rather than the name itself, so a decoded
400
- * record comes back keyed by number. Build a `{ [hash]: name }` map with this (or with
401
- * {@link buildLabelHashMap}) to get readable keys. `hash = fold(h * 223 + byte) mod 2^32`.
402
- */
403
- function hashCandidLabel(label) {
404
- let out = 0;
405
- for (const codePoint of Buffer.from(label, 'utf8'))
406
- out = (out * 223 + codePoint) >>> 0;
407
- return out;
408
- }
409
- /** `['owner', 'subaccount']` -> `{ 947296307: 'owner', 1349681965: 'subaccount' }` */
410
- function buildLabelHashMap(labels = []) {
411
- const out = {};
412
- for (const label of labels)
413
- out[hashCandidLabel(label)] = label;
414
- return out;
415
- }
416
- function fieldId(name) {
417
- if (/^\d+$/.test(name))
418
- return Number(name);
419
- return hashCandidLabel(name);
420
- }
421
- /**
422
- * Decode a Candid-encoded reply. Candid is self-describing, so the concrete shape is only known at
423
- * runtime and values are returned as `any`; narrow them at the call site.
424
- * - `nat`, `int`, `nat64`, `int64` -> `bigint`; `nat8/16/32`, `int8/16/32`, floats -> `number`
425
- * - `text`, `principal` -> `string`; `opt` -> 0- or 1-element array; `vec` -> array (`vec nat8` too)
426
- * - `record` -> object keyed by label (via `labelHashMap`) or by field hash as a string
427
- * - `variant` -> single-key object
428
- * @param bytes the raw `DIDL...` payload returned by {@link queryCanister}
429
- * @param labelHashMap `{ [hash]: name }` from {@link hashCandidLabel}; unmapped fields keep their hash
430
- * @returns one entry per value in the reply tuple
431
- */
432
- function decodeCandid(bytes, labelHashMap = {}) {
433
- const state = { i: 0 };
434
- if (Buffer.from(bytes.slice(0, 4)).toString('ascii') !== 'DIDL')
435
- throw new Error('Invalid Candid payload');
436
- state.i = 4;
437
- const typeCount = Number(decodeUleb128(bytes, state));
438
- const typeTable = [];
439
- const readTypeRef = () => Number(decodeSleb128(bytes, state));
440
- for (let i = 0; i < typeCount; i++) {
441
- const kind = Number(decodeSleb128(bytes, state));
442
- if (kind === exports.CANDID_TYPE.opt || kind === exports.CANDID_TYPE.vec) {
443
- typeTable.push({ kind, type: readTypeRef() });
444
- continue;
445
- }
446
- if (kind === exports.CANDID_TYPE.record || kind === exports.CANDID_TYPE.variant) {
447
- const fieldCount = Number(decodeUleb128(bytes, state));
448
- const fields = [];
449
- for (let j = 0; j < fieldCount; j++) {
450
- const id = Number(decodeUleb128(bytes, state));
451
- const type = readTypeRef();
452
- fields.push({ id, type });
453
- }
454
- typeTable.push({ kind, fields });
455
- continue;
456
- }
457
- throw new Error(`Unsupported Candid type table kind ${kind}`);
458
- }
459
- const argCount = Number(decodeUleb128(bytes, state));
460
- const argTypes = [];
461
- for (let i = 0; i < argCount; i++)
462
- argTypes.push(readTypeRef());
463
- const readFixedUint = (size) => {
464
- let out = B0;
465
- for (let i = 0; i < size; i++)
466
- out |= BigInt(bytes[state.i++]) << BigInt(i * 8);
467
- return out;
468
- };
469
- const label = (id) => labelHashMap[id] || String(id);
470
- const decodeType = (typeRef) => {
471
- if (typeRef >= 0) {
472
- const definition = typeTable[typeRef];
473
- if (!definition)
474
- throw new Error(`Unknown Candid type ref ${typeRef}`);
475
- if (definition.kind === exports.CANDID_TYPE.opt) {
476
- const tag = bytes[state.i++];
477
- if (tag === 0)
478
- return [];
479
- if (tag === 1)
480
- return [decodeType(definition.type)];
481
- throw new Error(`Invalid Candid opt tag ${tag}`);
482
- }
483
- if (definition.kind === exports.CANDID_TYPE.vec) {
484
- const length = Number(decodeUleb128(bytes, state));
485
- const out = [];
486
- for (let i = 0; i < length; i++)
487
- out.push(decodeType(definition.type));
488
- return out;
489
- }
490
- if (definition.kind === exports.CANDID_TYPE.record) {
491
- const out = {};
492
- for (const field of definition.fields)
493
- out[label(field.id)] = decodeType(field.type);
494
- return out;
495
- }
496
- if (definition.kind === exports.CANDID_TYPE.variant) {
497
- const index = Number(decodeUleb128(bytes, state));
498
- const selectedField = definition.fields[index];
499
- if (!selectedField)
500
- throw new Error(`Invalid Candid variant index ${index}`);
501
- return { [label(selectedField.id)]: decodeType(selectedField.type) };
502
- }
503
- throw new Error(`Unsupported Candid composite kind ${definition.kind}`);
504
- }
505
- switch (typeRef) {
506
- case exports.CANDID_TYPE.null:
507
- case exports.CANDID_TYPE.reserved:
508
- return null;
509
- case exports.CANDID_TYPE.bool: {
510
- const value = bytes[state.i++];
511
- if (value !== 0 && value !== 1)
512
- throw new Error(`Invalid Candid bool value ${value}`);
513
- return value === 1;
514
- }
515
- case exports.CANDID_TYPE.nat: return decodeUleb128(bytes, state);
516
- case exports.CANDID_TYPE.int: return decodeSleb128(bytes, state);
517
- case exports.CANDID_TYPE.nat8: return bytes[state.i++];
518
- case exports.CANDID_TYPE.nat16: return Number(readFixedUint(2));
519
- case exports.CANDID_TYPE.nat32: return Number(readFixedUint(4));
520
- case exports.CANDID_TYPE.nat64: return readFixedUint(8);
521
- case exports.CANDID_TYPE.int8: return Number(BigInt.asIntN(8, readFixedUint(1)));
522
- case exports.CANDID_TYPE.int16: return Number(BigInt.asIntN(16, readFixedUint(2)));
523
- case exports.CANDID_TYPE.int32: return Number(BigInt.asIntN(32, readFixedUint(4)));
524
- case exports.CANDID_TYPE.int64: return BigInt.asIntN(64, readFixedUint(8));
525
- case exports.CANDID_TYPE.float32: {
526
- const out = Buffer.from(bytes.slice(state.i, state.i + 4)).readFloatLE(0);
527
- state.i += 4;
528
- return out;
529
- }
530
- case exports.CANDID_TYPE.float64: {
531
- const out = Buffer.from(bytes.slice(state.i, state.i + 8)).readDoubleLE(0);
532
- state.i += 8;
533
- return out;
534
- }
535
- case exports.CANDID_TYPE.text: {
536
- const length = Number(decodeUleb128(bytes, state));
537
- const out = Buffer.from(bytes.slice(state.i, state.i + length)).toString('utf8');
538
- state.i += length;
539
- return out;
540
- }
541
- case exports.CANDID_TYPE.principal: {
542
- const principalTag = bytes[state.i++];
543
- if (principalTag !== 1)
544
- throw new Error(`Invalid Candid principal tag ${principalTag}`);
545
- const length = Number(decodeUleb128(bytes, state));
546
- const principalBytes = bytes.slice(state.i, state.i + length);
547
- state.i += length;
548
- return principalBytesToText(principalBytes);
549
- }
550
- case exports.CANDID_TYPE.empty:
551
- throw new Error('Cannot decode a value of Candid type empty');
552
- }
553
- throw new Error(`Unsupported Candid primitive type ${typeRef}`);
554
- };
555
- return argTypes.map(decodeType);
556
- }
557
- /**
558
- * Minimal Candid encoder: `DIDL` + type table + arg types + values.
559
- *
560
- * Value conventions (mirroring what {@link decodeCandid} produces):
561
- * - `nat` / `int` / fixed-width ints accept number, bigint or decimal string
562
- * - `text` string; `bool` boolean; `null` / `reserved` anything (nothing is written)
563
- * - `principal` textual principal or raw bytes
564
- * - `blob` (`vec nat8`) Uint8Array / Buffer / number[] / hex string
565
- * - `opt` `null` / `undefined` / `[]` -> none, `[x]` -> some(x), any other value -> some(value)
566
- * - `vec` array (or Uint8Array when the element type is `nat8`)
567
- * - `record` object keyed by field name; a missing `opt` field is encoded as none
568
- * - `variant` single-key object `{ Tag: value }`, or a string `'Tag'` for unit variants
569
- */
570
- function encodeCandid(args = []) {
571
- const table = [];
572
- const tableIndex = new Map();
573
- const addComposite = (key, body) => {
574
- const existing = tableIndex.get(key);
575
- if (existing !== undefined)
576
- return existing;
577
- const idx = table.length;
578
- table.push(body);
579
- tableIndex.set(key, idx);
580
- return idx;
581
- };
582
- const sortedFields = (fields) => Object.keys(fields)
583
- .map(name => ({ name, id: fieldId(name), type: fields[name] }))
584
- .sort((a, b) => a.id - b.id);
585
- const typeRef = (t) => {
586
- if (typeof t === 'string') {
587
- if (t === 'blob')
588
- return addComposite('vec:-5', Buffer.concat([encodeSleb128(exports.CANDID_TYPE.vec), encodeSleb128(exports.CANDID_TYPE.nat8)]));
589
- const code = exports.CANDID_TYPE[t];
590
- if (code === undefined || code === exports.CANDID_TYPE.opt || code === exports.CANDID_TYPE.vec || code === exports.CANDID_TYPE.record || code === exports.CANDID_TYPE.variant || code === exports.CANDID_TYPE.func || code === exports.CANDID_TYPE.service)
591
- throw new Error(`Unsupported Candid type "${t}"`);
592
- return code;
593
- }
594
- if ('opt' in t) {
595
- const inner = typeRef(t.opt);
596
- return addComposite(`opt:${inner}`, Buffer.concat([encodeSleb128(exports.CANDID_TYPE.opt), encodeSleb128(inner)]));
597
- }
598
- if ('vec' in t) {
599
- const inner = typeRef(t.vec);
600
- return addComposite(`vec:${inner}`, Buffer.concat([encodeSleb128(exports.CANDID_TYPE.vec), encodeSleb128(inner)]));
601
- }
602
- const kind = 'record' in t ? exports.CANDID_TYPE.record : exports.CANDID_TYPE.variant;
603
- const fields = sortedFields('record' in t ? t.record : t.variant);
604
- const refs = fields.map(f => ({ id: f.id, ref: typeRef(f.type) }));
605
- const body = Buffer.concat([
606
- encodeSleb128(kind),
607
- encodeUleb128(refs.length),
608
- ...refs.map(f => Buffer.concat([encodeUleb128(f.id), encodeSleb128(f.ref)])),
609
- ]);
610
- return addComposite(`${kind}:${refs.map(f => `${f.id}=${f.ref}`).join(',')}`, body);
611
- };
612
- const fixedInt = (value, bits, signed) => {
613
- let n = toBigInt(value);
614
- if (signed)
615
- n = BigInt.asUintN(bits, n);
616
- else if (n < B0 || n >= (B1 << BigInt(bits)))
617
- throw new Error(`nat${bits} out of range: ${value}`);
618
- const out = Buffer.alloc(bits / 8);
619
- for (let i = 0; i < out.length; i++)
620
- out[i] = Number((n >> BigInt(i * 8)) & B0xff);
621
- return out;
622
- };
623
- const encodeValue = (t, value) => {
624
- if (typeof t === 'string') {
625
- switch (t) {
626
- case 'null':
627
- case 'reserved':
628
- return Buffer.alloc(0);
629
- case 'empty': throw new Error('Cannot encode a value of Candid type empty');
630
- case 'bool': return Buffer.from([value ? 1 : 0]);
631
- case 'nat': return encodeUleb128(toBigInt(value));
632
- case 'int': return encodeSleb128(toBigInt(value));
633
- case 'nat8': return fixedInt(value, 8, false);
634
- case 'nat16': return fixedInt(value, 16, false);
635
- case 'nat32': return fixedInt(value, 32, false);
636
- case 'nat64': return fixedInt(value, 64, false);
637
- case 'int8': return fixedInt(value, 8, true);
638
- case 'int16': return fixedInt(value, 16, true);
639
- case 'int32': return fixedInt(value, 32, true);
640
- case 'int64': return fixedInt(value, 64, true);
641
- case 'float32': {
642
- const b = Buffer.alloc(4);
643
- b.writeFloatLE(Number(value), 0);
644
- return b;
645
- }
646
- case 'float64': {
647
- const b = Buffer.alloc(8);
648
- b.writeDoubleLE(Number(value), 0);
649
- return b;
650
- }
651
- case 'text': {
652
- const bytes = Buffer.from(String(value), 'utf8');
653
- return Buffer.concat([encodeUleb128(bytes.length), bytes]);
654
- }
655
- case 'principal': {
656
- const bytes = typeof value === 'string' ? principalTextToBytes(value) : toBytes(value, 'principal');
657
- return Buffer.concat([Buffer.from([1]), encodeUleb128(bytes.length), Buffer.from(bytes)]);
658
- }
659
- case 'blob': {
660
- const bytes = toBytes(value, 'blob');
661
- return Buffer.concat([encodeUleb128(bytes.length), Buffer.from(bytes)]);
662
- }
663
- }
664
- throw new Error(`Unsupported Candid type "${t}"`);
665
- }
666
- if ('opt' in t) {
667
- if (value === null || value === undefined)
668
- return Buffer.from([0]);
669
- if (Array.isArray(value)) {
670
- if (value.length === 0)
671
- return Buffer.from([0]);
672
- if (value.length === 1)
673
- return Buffer.concat([Buffer.from([1]), encodeValue(t.opt, value[0])]);
674
- throw new Error('opt value must be [] or a single element array');
675
- }
676
- return Buffer.concat([Buffer.from([1]), encodeValue(t.opt, value)]);
677
- }
678
- if ('vec' in t) {
679
- if (t.vec === 'nat8' && !Array.isArray(value)) {
680
- const bytes = toBytes(value, 'vec nat8');
681
- return Buffer.concat([encodeUleb128(bytes.length), Buffer.from(bytes)]);
682
- }
683
- if (!Array.isArray(value))
684
- throw new Error('vec value must be an array');
685
- return Buffer.concat([encodeUleb128(value.length), ...value.map((v) => encodeValue(t.vec, v))]);
686
- }
687
- if ('record' in t) {
688
- if (value === null || typeof value !== 'object')
689
- throw new Error('record value must be an object');
690
- const chunks = [];
691
- for (const field of sortedFields(t.record)) {
692
- const v = value[field.name];
693
- if (v === undefined && !(typeof field.type === 'object' && 'opt' in field.type) && field.type !== 'null' && field.type !== 'reserved')
694
- throw new Error(`Missing record field "${field.name}"`);
695
- chunks.push(encodeValue(field.type, v));
696
- }
697
- return Buffer.concat(chunks);
698
- }
699
- // variant
700
- const fields = sortedFields(t.variant);
701
- let tag;
702
- let inner = null;
703
- if (typeof value === 'string')
704
- tag = value;
705
- else if (value && typeof value === 'object') {
706
- const keys = Object.keys(value);
707
- if (keys.length !== 1)
708
- throw new Error('variant value must have exactly one key');
709
- tag = keys[0];
710
- inner = value[tag];
711
- }
712
- else
713
- throw new Error('variant value must be a string or a single-key object');
714
- const index = fields.findIndex(f => f.name === tag);
715
- if (index === -1)
716
- throw new Error(`Unknown variant tag "${tag}"`);
717
- return Buffer.concat([encodeUleb128(index), encodeValue(fields[index].type, inner)]);
718
- };
719
- // type refs first (fills the table), then values
720
- const refs = args.map(a => typeRef(a.type));
721
- const values = args.map((a, i) => encodeValue(a.type, a.value));
722
- return Buffer.concat([
723
- Buffer.from('DIDL', 'ascii'),
724
- encodeUleb128(table.length),
725
- ...table,
726
- encodeUleb128(refs.length),
727
- ...refs.map(r => encodeSleb128(r)),
728
- ...values,
729
- ]);
730
- }
731
- function toBigInt(value) {
732
- if (typeof value === 'bigint')
733
- return value;
734
- if (typeof value === 'number') {
735
- if (!Number.isInteger(value))
736
- throw new Error(`Expected an integer, got ${value}`);
737
- return BigInt(value);
738
- }
739
- if (typeof value === 'string')
740
- return BigInt(value.trim());
741
- if (typeof value === 'boolean')
742
- return value ? B1 : B0;
743
- throw new Error(`Cannot convert ${typeof value} to bigint`);
744
- }
745
- /** Uint8Array / Buffer / number[] / hex string (0x optional) -> Uint8Array */
746
- function toBytes(value, what = 'bytes') {
747
- if (value instanceof Uint8Array)
748
- return value;
749
- if (Array.isArray(value))
750
- return Uint8Array.from(value);
751
- if (typeof value === 'string') {
752
- const hex = value.startsWith('0x') ? value.slice(2) : value;
753
- if (hex.length % 2 !== 0 || !/^[0-9a-fA-F]*$/.test(hex))
754
- throw new Error(`Invalid hex ${what}: ${value}`);
755
- return Uint8Array.from(Buffer.from(hex, 'hex'));
756
- }
757
- if (value && typeof value === 'object' && value.type === 'Buffer' && Array.isArray(value.data))
758
- return Uint8Array.from(value.data);
759
- throw new Error(`Cannot convert ${typeof value} to ${what}`);
760
- }
761
- // ---------------------------------------------------------------------------
762
- // Principal / account identifier
763
- // ---------------------------------------------------------------------------
764
- const BASE32_ALPHABET = 'abcdefghijklmnopqrstuvwxyz234567';
765
- /** CRC-32 (IEEE) as used by principal text and account identifiers */
766
- function crc32(bytes) {
767
- let crc = 0xffffffff;
768
- for (const value of bytes) {
769
- crc ^= value;
770
- for (let i = 0; i < 8; i++) {
771
- const mask = -(crc & 1);
772
- crc = (crc >>> 1) ^ (0xedb88320 & mask);
773
- }
774
- }
775
- return ~crc >>> 0;
776
- }
777
- function crc32Bytes(bytes) {
778
- const checksum = crc32(bytes);
779
- return Buffer.from([(checksum >>> 24) & 0xff, (checksum >>> 16) & 0xff, (checksum >>> 8) & 0xff, checksum & 0xff]);
780
- }
781
- /** RFC 4648 base32 without padding, lowercase alphabet by default (as principals use). */
782
- function bytesToBase32(bytes, alphabet = BASE32_ALPHABET) {
783
- let out = '';
784
- let value = 0;
785
- let bits = 0;
786
- for (const byte of bytes) {
787
- value = ((value << 8) | byte) & 0xffff;
788
- bits += 8;
789
- while (bits >= 5) {
790
- out += alphabet[(value >>> (bits - 5)) & 31];
791
- bits -= 5;
792
- }
793
- }
794
- if (bits > 0)
795
- out += alphabet[(value << (5 - bits)) & 31];
796
- return out;
797
- }
798
- /** Inverse of {@link bytesToBase32}: case-insensitive, ignores `-` separators and `=` padding. */
799
- function base32ToBytes(text) {
800
- const clean = text.replace(/[-=]/g, '').toLowerCase();
801
- let value = 0;
802
- let bits = 0;
803
- const out = [];
804
- for (const char of clean) {
805
- const index = BASE32_ALPHABET.indexOf(char);
806
- if (index === -1)
807
- throw new Error(`Invalid base32 character "${char}"`);
808
- value = ((value << 5) | index) & 0xffff;
809
- bits += 5;
810
- if (bits >= 8) {
811
- out.push((value >>> (bits - 8)) & 0xff);
812
- bits -= 8;
813
- }
814
- }
815
- return Uint8Array.from(out);
816
- }
817
- /** Raw principal bytes -> textual principal (`crc32 || bytes`, base32, dashed every 5 chars). */
818
- function principalBytesToText(principalBytes) {
819
- const bytes = Buffer.from(principalBytes);
820
- if (bytes.length > 29)
821
- throw new Error(`Principal too long: ${bytes.length} bytes`);
822
- const base32 = bytesToBase32(Buffer.concat([crc32Bytes(bytes), bytes]));
823
- return base32.match(/.{1,5}/g).join('-');
824
- }
825
- /** Textual principal -> raw bytes. Verifies the CRC-32 prefix and throws on mismatch. */
826
- function principalTextToBytes(principalText) {
827
- if (typeof principalText !== 'string' || !principalText.length)
828
- throw new Error(`Invalid principal "${principalText}"`);
829
- const decoded = base32ToBytes(principalText);
830
- if (decoded.length < 4)
831
- throw new Error(`Invalid principal "${principalText}": too short`);
832
- const bytes = decoded.slice(4);
833
- if (bytes.length > 29)
834
- throw new Error(`Invalid principal "${principalText}": too long`);
835
- const expected = crc32Bytes(bytes);
836
- for (let i = 0; i < 4; i++)
837
- if (decoded[i] !== expected[i])
838
- throw new Error(`Invalid principal "${principalText}": checksum mismatch`);
839
- return bytes;
840
- }
841
- /** True when `str` is a well formed textual principal (valid base32, checksum and grouping). */
842
- function isPrincipal(str) {
843
- if (typeof str !== 'string')
844
- return false;
845
- try {
846
- return principalBytesToText(principalTextToBytes(str)) === str.toLowerCase();
847
- }
848
- catch {
849
- return false;
850
- }
851
- }
852
- /**
853
- * ICP ledger account identifier (hex, 32 bytes):
854
- * `crc32(h) || h` where `h = sha224("\x0Aaccount-id" || principal || subaccount)`.
855
- * `subaccount` defaults to 32 zero bytes; accepts Uint8Array / number[] / hex, right-padded to 32 bytes.
856
- */
857
- function accountIdentifierFromPrincipal(principal, subaccount) {
858
- const principalBytes = typeof principal === 'string' ? principalTextToBytes(principal) : principal;
859
- const sub = Buffer.alloc(32);
860
- if (subaccount !== undefined && subaccount !== null) {
861
- const given = Buffer.from(toBytes(subaccount, 'subaccount'));
862
- if (given.length > 32)
863
- throw new Error('subaccount must be at most 32 bytes');
864
- given.copy(sub, 32 - given.length);
865
- }
866
- const hash = (0, crypto_1.createHash)('sha224')
867
- .update(Buffer.concat([Buffer.from([0x0a]), Buffer.from('account-id', 'ascii'), Buffer.from(principalBytes), sub]))
868
- .digest();
869
- return Buffer.concat([crc32Bytes(hash), hash]).toString('hex');
870
- }
871
- // ---------------------------------------------------------------------------
872
- // endpoints
873
- // ---------------------------------------------------------------------------
874
- /** Boundary node list: `ICP_RPC` (comma separated) or {@link DEFAULT_ENDPOINTS}. */
875
- function getEndpoints() {
876
- return (0, rpc_1.getEndpoints)(exports.CHAIN, exports.DEFAULT_ENDPOINTS);
877
- }
878
- // ---------------------------------------------------------------------------
879
- // query call
880
- // ---------------------------------------------------------------------------
881
- /** Thrown when the replica answers a query with a reject (canister error, missing method, dead canister). */
882
- class IcpRejectError extends Error {
883
- constructor(canisterId, method, decoded) {
884
- var _a, _b;
885
- super(`Canister ${canisterId} did not reply to ${method}: ${(_b = (_a = decoded === null || decoded === void 0 ? void 0 : decoded.reject_message) !== null && _a !== void 0 ? _a : decoded === null || decoded === void 0 ? void 0 : decoded.status) !== null && _b !== void 0 ? _b : 'unknown response'}`);
886
- this.name = 'IcpRejectError';
887
- this.canisterId = canisterId;
888
- this.method = method;
889
- this.status = decoded === null || decoded === void 0 ? void 0 : decoded.status;
890
- this.rejectCode = decoded === null || decoded === void 0 ? void 0 : decoded.reject_code;
891
- this.rejectMessage = decoded === null || decoded === void 0 ? void 0 : decoded.reject_message;
892
- this.errorCode = decoded === null || decoded === void 0 ? void 0 : decoded.error_code;
893
- }
894
- }
895
- exports.IcpRejectError = IcpRejectError;
896
- function toUint8Array(data) {
897
- if (Buffer.isBuffer(data) || data instanceof Uint8Array)
898
- return data;
899
- if (data instanceof ArrayBuffer)
900
- return new Uint8Array(data);
901
- if (typeof data === 'string')
902
- return Buffer.from(data, 'binary');
903
- throw new Error(`Unexpected response body type ${typeof data}`);
904
- }
905
- /**
906
- * Anonymous query call against a canister (`/api/v2/canister/<id>/query`).
907
- * Rotates over the configured boundary nodes and retries transport errors; canister rejects are
908
- * thrown as {@link IcpRejectError} without retry.
909
- * @returns the raw Candid reply (`DIDL...` bytes), to be passed to {@link decodeCandid}
910
- */
911
- async function queryCanister(params) {
912
- var _a, _b, _c;
913
- const { canisterId, arg = exports.EMPTY_ARGS, timeout = DEFAULT_TIMEOUT, retries } = params;
914
- const method = (_a = params.method) !== null && _a !== void 0 ? _a : params.methodName;
915
- if (!method)
916
- throw new Error('queryCanister: method is required');
917
- const hosts = params.host ? (0, rpc_1.toEndpointList)(params.host) : getEndpoints();
918
- const content = {
919
- request_type: 'query',
920
- canister_id: Buffer.from(principalTextToBytes(canisterId)),
921
- method_name: method,
922
- arg: Buffer.from(arg),
923
- sender: Buffer.from(exports.ANONYMOUS_SENDER),
924
- ingress_expiry: BigInt(Date.now() + INGRESS_EXPIRY_MS) * NANOS_PER_MS,
925
- };
926
- // self-describing CBOR tag (55799) as recommended by the IC HTTP interface spec
927
- const body = Buffer.concat([Buffer.from([0xd9, 0xd9, 0xf7]), encodeCbor({ content })]);
928
- const urls = hosts.map(h => `${(0, rpc_1.stripTrailingSlash)(h)}/api/v2/canister/${canisterId}/query`);
929
- const data = await (0, rpc_1.getLimiter)('ICP', CONCURRENCY)(() => (0, rpc_1.httpPost)(urls, body, {
930
- timeout,
931
- retries,
932
- headers: { 'Content-Type': 'application/cbor' },
933
- axiosConfig: { responseType: 'arraybuffer' },
934
- }));
935
- const decoded = decodeCbor(toUint8Array(data));
936
- if ((decoded === null || decoded === void 0 ? void 0 : decoded.status) !== 'replied' || !((_b = decoded === null || decoded === void 0 ? void 0 : decoded.reply) === null || _b === void 0 ? void 0 : _b.arg)) {
937
- (0, debugLog_1.debugLog)(`[chains.icp] ${canisterId}.${method} rejected: ${(_c = decoded === null || decoded === void 0 ? void 0 : decoded.reject_message) !== null && _c !== void 0 ? _c : decoded === null || decoded === void 0 ? void 0 : decoded.status} (code ${decoded === null || decoded === void 0 ? void 0 : decoded.reject_code}, ${decoded === null || decoded === void 0 ? void 0 : decoded.error_code})`);
938
- throw new IcpRejectError(canisterId, method, decoded);
939
- }
940
- return toUint8Array(decoded.reply.arg);
941
- }
942
- async function queryCanisterDecoded(paramsOrCanister, method, labels) {
943
- var _a;
944
- const params = typeof paramsOrCanister === 'string'
945
- ? { canisterId: paramsOrCanister, method, labels }
946
- : paramsOrCanister;
947
- const labelHashMap = { ...buildLabelHashMap(params.labels), ...((_a = params.labelHashMap) !== null && _a !== void 0 ? _a : {}) };
948
- const [value] = decodeCandid(await queryCanister(params), labelHashMap);
949
- return value;
950
- }
951
- /**
952
- * Encode `args` with {@link encodeCandid}, query `method` and decode the reply.
953
- * `args` is either `CandidValue[]` (`{ type, value }`) or raw values paired with `argTypes`.
954
- * @returns the first value of the reply tuple
955
- */
956
- async function callCandid(params) {
957
- const { args = [], argTypes, ...rest } = params;
958
- let typed;
959
- if (argTypes) {
960
- if (argTypes.length !== args.length)
961
- throw new Error('callCandid: args and argTypes length mismatch');
962
- typed = args.map((value, i) => ({ type: argTypes[i], value }));
963
- }
964
- else
965
- typed = args;
966
- return queryCanisterDecoded({ ...rest, arg: encodeCandid(typed) });
967
- }
968
- const ICRC_ACCOUNT_TYPE = { record: { owner: 'principal', subaccount: { opt: 'blob' } } };
969
- /**
970
- * `icrc1_metadata` as `{ 'icrc1:symbol': 'ckBTC', 'icrc1:decimals': '8', ... }`.
971
- * `Nat` / `Int` values are returned as decimal strings, `Text` as string, `Blob` as Uint8Array.
972
- */
973
- async function getIcrcMetadata({ ledger, host, timeout }) {
974
- const rows = await queryCanisterDecoded({ canisterId: ledger, method: 'icrc1_metadata', host, timeout, labels: ['Nat', 'Int', 'Text', 'Blob'] });
975
- const out = {};
976
- if (!Array.isArray(rows))
977
- throw new Error(`Unexpected icrc1_metadata reply from ${ledger}`);
978
- for (const row of rows) {
979
- const key = row === null || row === void 0 ? void 0 : row[0];
980
- const variant = row === null || row === void 0 ? void 0 : row[1];
981
- if (typeof key !== 'string' || !variant || typeof variant !== 'object')
982
- continue;
983
- const tag = Object.keys(variant)[0];
984
- const value = variant[tag];
985
- if (tag === 'Blob')
986
- out[key] = Array.isArray(value) ? Uint8Array.from(value) : toBytes(value);
987
- else
988
- out[key] = typeof value === 'bigint' ? value.toString() : String(value);
989
- }
990
- return out;
991
- }
992
- /** `icrc1_decimals` (nat8) */
993
- async function getIcrcDecimals({ ledger, host, timeout }) {
994
- return Number(await queryCanisterDecoded({ canisterId: ledger, method: 'icrc1_decimals', host, timeout }));
995
- }
996
- /** `icrc1_symbol` */
997
- async function getIcrcSymbol({ ledger, host, timeout }) {
998
- return String(await queryCanisterDecoded({ canisterId: ledger, method: 'icrc1_symbol', host, timeout }));
999
- }
1000
- /** `icrc1_name` */
1001
- async function getIcrcName({ ledger, host, timeout }) {
1002
- return String(await queryCanisterDecoded({ canisterId: ledger, method: 'icrc1_name', host, timeout }));
1003
- }
1004
- /** `icrc1_total_supply` as a decimal string in base units */
1005
- async function getIcrcTotalSupply({ ledger, host, timeout }) {
1006
- return toBigInt(await queryCanisterDecoded({ canisterId: ledger, method: 'icrc1_total_supply', host, timeout })).toString();
1007
- }
1008
- /**
1009
- * `icrc1_balance_of(record { owner: principal; subaccount: opt blob })` as a decimal string in base units.
1010
- * `subaccount` accepts Uint8Array / number[] / hex; omit it for the default subaccount.
1011
- */
1012
- async function getIcrcBalance({ ledger, owner, subaccount, host, timeout }) {
1013
- const sub = subaccount === undefined || subaccount === null ? null : toBytes(subaccount, 'subaccount');
1014
- const balance = await callCandid({
1015
- canisterId: ledger,
1016
- method: 'icrc1_balance_of',
1017
- host,
1018
- timeout,
1019
- args: [{ type: ICRC_ACCOUNT_TYPE, value: { owner, subaccount: sub } }],
1020
- });
1021
- return toBigInt(balance).toString();
1022
- }
1023
- /**
1024
- * ICP ledger `account_balance(record { account: blob })` -> `e8s` as a decimal string.
1025
- * `accountIdentifierHex` is the 32 byte account identifier (see {@link accountIdentifierFromPrincipal}).
1026
- */
1027
- async function getIcpAccountBalance({ accountIdentifierHex, ledger = exports.ICP_LEDGER, host, timeout }) {
1028
- const account = toBytes(accountIdentifierHex, 'account identifier');
1029
- if (account.length !== 32)
1030
- throw new Error('account identifier must be 32 bytes');
1031
- const res = await callCandid({
1032
- canisterId: ledger,
1033
- method: 'account_balance',
1034
- host,
1035
- timeout,
1036
- labels: ['e8s'],
1037
- args: [{ type: { record: { account: 'blob' } }, value: { account } }],
1038
- });
1039
- return toBigInt(res === null || res === void 0 ? void 0 : res.e8s).toString();
1040
- }