@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,884 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cairoErc20Abis = exports.erc20AbisCairo1 = exports.erc20Abis = exports.DEFAULT_EVENTS_CHUNK_SIZE = exports.number = exports.FIELD_PRIME = exports.ADDR_BOUND = exports.BATCH_CHUNK_SIZE = exports.AGGREGATE_CHUNK_SIZE = exports.DEFAULT_MULTICALL_ADDRESS = exports.DEFAULT_ENDPOINTS = exports.CHAIN = void 0;
4
- exports.getEndpoints = getEndpoints;
5
- exports.getMulticallAddress = getMulticallAddress;
6
- exports.toBigInt = toBigInt;
7
- exports.toHex = toHex;
8
- exports.addAddressPadding = addAddressPadding;
9
- exports.validateAndParseAddress = validateAndParseAddress;
10
- exports.isStarknetAddress = isStarknetAddress;
11
- exports.starknetKeccak = starknetKeccak;
12
- exports.getSelectorFromName = getSelectorFromName;
13
- exports.parseUint256 = parseUint256;
14
- exports.shortStringToFelt = shortStringToFelt;
15
- exports.feltToShortString = feltToShortString;
16
- exports.feltArrToStr = feltArrToStr;
17
- exports.encodeCalldata = encodeCalldata;
18
- exports.decodeOutput = decodeOutput;
19
- exports.toBlockId = toBlockId;
20
- exports.formCallBody = formCallBody;
21
- exports.parseOutput = parseOutput;
22
- exports.rpc = rpc;
23
- exports.getBlockNumber = getBlockNumber;
24
- exports.getBlock = getBlock;
25
- exports.getBlockAtTimestamp = getBlockAtTimestamp;
26
- exports.getNonce = getNonce;
27
- exports.getClassHashAt = getClassHashAt;
28
- exports.call = call;
29
- exports.multiCall = multiCall;
30
- exports.getLogs = getLogs;
31
- /**
32
- * Starknet client: dependency-free JSON-RPC transport + Cairo ABI codec.
33
- *
34
- * Replaces (and consolidates) these per-repo copies:
35
- * - DefiLlama-Adapters projects/helper/utils/starknet.js (codec: selectors, addresses, encodeCalldata, decodeOutput)
36
- * - DefiLlama-Adapters projects/helper/chain/starknet.js (call, multiCall via aggregator / batched, rpc, getBlockNumber, getLogs)
37
- * - DefiLlama-Adapters projects/helper/env.js (STARKNET_RPC / STARKNET_MULTICALL defaults)
38
- * - coins src/adapters/utils/starknet.ts (feltArrToStr, cairoErc20Abis, aggregate result layout)
39
- * - defi l2/utils.ts (starknetU256ToNumber, hardcoded total_supply / aggregate selectors)
40
- * - peggedassets-server src/adapters/peggedAssets/helper/starknet.js (defaultAbis shape)
41
- *
42
- * Only the chain plumbing is ported: no TVL helpers (sumTokens / dexExport live
43
- * with their callers) and no on-disk log cache.
44
- *
45
- * Decoding mirrors starknet.js v5 (CallData.parse) so existing ABIs keep working:
46
- * - scalars (felt, felt252, uN, ContractAddress, ...) decode to BigInt
47
- * - core::bool decodes to boolean
48
- * - core::integer::u256 decodes to a single BigInt (low + high << 128)
49
- * - bare Cairo 0 "Uint256" WITHOUT a struct definition decodes as ONE felt
50
- * (that is what starknet.js did, and adapters such as jediswap reordered
51
- * their ABIs around it); with a struct definition it decodes to { low, high }
52
- * - structs decode to objects keyed by member name, tuples to objects keyed
53
- * by index (or member name for Cairo 0 named tuples), arrays to arrays
54
- * - a function with a single unnamed output returns the value directly,
55
- * otherwise an object keyed by output name
56
- *
57
- * Env: `STARKNET_RPC` (comma separated list, rotated on failure) overrides
58
- * `DEFAULT_ENDPOINTS`; `STARKNET_MULTICALL` overrides the aggregator address;
59
- * `STARKNET_RPC_CONCURRENCY` overrides the (default 1) request concurrency.
60
- */
61
- const ethers_1 = require("ethers");
62
- const env_1 = require("../util/env");
63
- const debugLog_1 = require("../util/debugLog");
64
- const rpc_1 = require("./rpc");
65
- // ---------------------------------------------------------------------------
66
- // config
67
- // ---------------------------------------------------------------------------
68
- exports.CHAIN = 'starknet';
69
- exports.DEFAULT_ENDPOINTS = [
70
- 'https://api.zan.top/public/starknet-mainnet',
71
- 'https://starknet-mainnet.public.blastapi.io',
72
- ];
73
- // On-chain Multicall aggregator. Collapses N starknet_call executions into a
74
- // single one (the node executes all sub-calls in one call frame), which is the
75
- // real cost win when the RPC bills per sub-call rather than per HTTP request.
76
- // aggregate(calls: Array<Call>) -> (block_number: u64, results: Array<Span<felt252>>)
77
- // NOTE: aggregate reverts atomically: if any sub-call reverts, the whole call
78
- // reverts, so multiCall falls back to per-call batching to preserve permitFailure.
79
- exports.DEFAULT_MULTICALL_ADDRESS = '0x01a33330996310a1e3fa1df5b16c1e07f0491fdd20c441126e02613b948f0225';
80
- exports.AGGREGATE_CHUNK_SIZE = 50;
81
- exports.BATCH_CHUNK_SIZE = 25;
82
- const CHUNK_SLEEP_MS = 200;
83
- function getEndpoints() {
84
- return (0, rpc_1.getEndpoints)(exports.CHAIN, exports.DEFAULT_ENDPOINTS);
85
- }
86
- function getMulticallAddress() {
87
- return (0, env_1.getEnvValue)('STARKNET_MULTICALL', exports.DEFAULT_MULTICALL_ADDRESS);
88
- }
89
- const rpcOptions = () => ({ chain: exports.CHAIN, defaultEndpoints: exports.DEFAULT_ENDPOINTS });
90
- // Public Starknet RPCs are stingy, so everything funnels through one limiter
91
- // (override with STARKNET_RPC_CONCURRENCY).
92
- const limiter = () => (0, rpc_1.getLimiter)('STARKNET', 1);
93
- // ---------------------------------------------------------------------------
94
- // numbers / addresses / selectors
95
- // ---------------------------------------------------------------------------
96
- const ZERO = BigInt(0);
97
- const ONE = BigInt(1);
98
- const SHIFT_128 = BigInt(128);
99
- const MASK_250 = (ONE << BigInt(250)) - ONE;
100
- const MASK_128 = (ONE << SHIFT_128) - ONE;
101
- exports.ADDR_BOUND = (ONE << BigInt(251)) - BigInt(256);
102
- exports.FIELD_PRIME = (ONE << BigInt(251)) + BigInt(17) * (ONE << BigInt(192)) + ONE;
103
- function toBigInt(value) {
104
- if (typeof value === 'bigint')
105
- return value;
106
- if (typeof value === 'number')
107
- return BigInt(value);
108
- if (typeof value === 'string')
109
- return BigInt(value.trim());
110
- if (typeof value === 'boolean')
111
- return value ? ONE : ZERO;
112
- throw new Error(`starknet: cannot convert ${value} to BigInt`);
113
- }
114
- function toHex(value) {
115
- return '0x' + toBigInt(value).toString(16);
116
- }
117
- function addAddressPadding(address) {
118
- return '0x' + toBigInt(address).toString(16).padStart(64, '0');
119
- }
120
- function validateAndParseAddress(address) {
121
- let n;
122
- try {
123
- n = toBigInt(address);
124
- }
125
- catch (e) {
126
- throw new Error(`Starknet Address is not a number: ${address}`);
127
- }
128
- if (n < ZERO || n >= exports.ADDR_BOUND)
129
- throw new Error(`Starknet Address out of range: ${address}`);
130
- return addAddressPadding(n);
131
- }
132
- /**
133
- * Loose check for a Starknet address: 0x-prefixed hex, non-zero, inside the
134
- * address bound, and not shaped like an EVM address (exactly 40 hex chars).
135
- */
136
- function isStarknetAddress(value) {
137
- if (typeof value !== 'string')
138
- return false;
139
- const v = value.trim();
140
- if (!/^0x[0-9a-fA-F]{1,64}$/.test(v))
141
- return false;
142
- if (v.length === 42)
143
- return false;
144
- const n = BigInt(v);
145
- return n > ZERO && n < exports.ADDR_BOUND;
146
- }
147
- /** starknet_keccak: keccak256 of the utf8 name, masked to 250 bits */
148
- function starknetKeccak(str) {
149
- return BigInt((0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)(str))) & MASK_250;
150
- }
151
- function getSelectorFromName(name) {
152
- return toHex(starknetKeccak(name));
153
- }
154
- /** u256 as { low, high } object or [low, high] felt pair -> bigint */
155
- function parseUint256(value) {
156
- if (Array.isArray(value)) {
157
- if (value.length < 2)
158
- throw new Error('starknet: u256 needs [low, high]');
159
- return toBigInt(value[0]) + (toBigInt(value[1]) << SHIFT_128);
160
- }
161
- if (value !== null && typeof value === 'object')
162
- return toBigInt(value.low) + (toBigInt(value.high) << SHIFT_128);
163
- return toBigInt(value);
164
- }
165
- /** Cairo short string (<= 31 utf8 bytes) -> hex felt */
166
- function shortStringToFelt(str) {
167
- const bytes = Buffer.from(str, 'utf8');
168
- if (bytes.length > 31)
169
- throw new Error(`starknet: short string too long: ${str}`);
170
- return '0x' + (bytes.toString('hex') || '0');
171
- }
172
- /** hex/decimal/bigint felt -> utf8 short string (leading zero bytes dropped) */
173
- function feltToShortString(felt) {
174
- const n = toBigInt(felt);
175
- if (n === ZERO)
176
- return '';
177
- let hex = n.toString(16);
178
- if (hex.length % 2)
179
- hex = '0' + hex;
180
- return Buffer.from(hex, 'hex').toString('utf8');
181
- }
182
- /** concatenate an array of short-string felts (e.g. a felt* name) */
183
- function feltArrToStr(felts) {
184
- return felts.reduce((memo, felt) => memo + feltToShortString(felt), '');
185
- }
186
- exports.number = {
187
- toHex,
188
- toBigInt,
189
- toBN: toBigInt,
190
- hexToDecimalString: (v) => toBigInt(v).toString(),
191
- };
192
- const isLen = (name) => /_len$/.test(name !== null && name !== void 0 ? name : '');
193
- const isCairo1Type = (type) => type.includes('::');
194
- const isTypeArray = (type) => /\*/.test(type) || type.startsWith('core::array::Array::') || type.startsWith('core::array::Span::');
195
- const isTypeTuple = (type) => /^\(.*\)$/.test(type);
196
- const isTypeU256 = (type) => type === 'core::integer::u256';
197
- const isTypeLegacyU256 = (type) => type === 'Uint256';
198
- const isTypeBool = (type) => type === 'core::bool';
199
- const isTypeOption = (type) => type.startsWith('core::option::Option::');
200
- const isTypeResult = (type) => type.startsWith('core::result::Result::');
201
- function getArrayType(type) {
202
- if (isCairo1Type(type))
203
- return type.substring(type.indexOf('<') + 1, type.lastIndexOf('>'));
204
- return type.replace('*', '');
205
- }
206
- // "(a, (b, c), core::array::Array::<x>)" -> ["a", "(b, c)", "core::array::Array::<x>"]
207
- // Cairo 0 named tuples "(x: felt, y: felt)" -> [{ name: 'x', type: 'felt' }, ...]
208
- function extractTupleMemberTypes(type) {
209
- const inner = type.replace(/\s/g, '').slice(1, -1);
210
- const members = [];
211
- let depth = 0, current = '';
212
- for (const ch of inner) {
213
- if (ch === '(' || ch === '<')
214
- depth++;
215
- else if (ch === ')' || ch === '>')
216
- depth--;
217
- if (ch === ',' && depth === 0) {
218
- members.push(current);
219
- current = '';
220
- }
221
- else
222
- current += ch;
223
- }
224
- if (current)
225
- members.push(current);
226
- return members.map((m) => {
227
- if (isCairo1Type(m) || !m.includes(':'))
228
- return m;
229
- const idx = m.indexOf(':');
230
- return { name: m.slice(0, idx), type: m.slice(idx + 1) };
231
- });
232
- }
233
- const memberType = (m) => typeof m === 'string' ? m : m.type;
234
- const memberName = (m, i) => typeof m === 'string' ? i : m.name;
235
- function getAbiStructs(abi) {
236
- const structs = {};
237
- abi.forEach((entry) => { if (entry && entry.type === 'struct')
238
- structs[entry.name] = entry; });
239
- return structs;
240
- }
241
- function getAbiEnums(abi) {
242
- const enums = {};
243
- abi.forEach((entry) => { if (entry && entry.type === 'enum')
244
- enums[entry.name] = entry; });
245
- delete enums['core::bool'];
246
- return enums;
247
- }
248
- // ---------------------------------------------------------------------------
249
- // calldata encoding
250
- // ---------------------------------------------------------------------------
251
- const isHexString = (v) => /^0x[0-9a-fA-F]+$/.test(v);
252
- const isDecimalString = (v) => /^\d+$/.test(v);
253
- /** encode a single felt (returns hex string) */
254
- function felt(value) {
255
- if (typeof value === 'bigint' || typeof value === 'number' || typeof value === 'boolean')
256
- return toHex(value);
257
- if (typeof value === 'string') {
258
- const v = value.trim();
259
- if (isHexString(v) || isDecimalString(v))
260
- return toHex(v);
261
- return shortStringToFelt(v);
262
- }
263
- throw new Error(`starknet: cannot encode ${JSON.stringify(value)} as felt`);
264
- }
265
- function encodeU256(value) {
266
- if (value !== null && typeof value === 'object' && !Array.isArray(value))
267
- return [felt(value.low), felt(value.high)];
268
- if (Array.isArray(value))
269
- return [felt(value[0]), felt(value[1])];
270
- const n = toBigInt(value);
271
- return [toHex(n & MASK_128), toHex(n >> SHIFT_128)];
272
- }
273
- function encodeValue(value, type, structs, enums) {
274
- var _a;
275
- if (value === undefined)
276
- throw new Error(`starknet: missing parameter for type ${type}`);
277
- if (isTypeU256(type) || isTypeLegacyU256(type))
278
- return encodeU256(value);
279
- if (Array.isArray(value)) {
280
- const itemType = getArrayType(type);
281
- const out = [felt(value.length)];
282
- value.forEach((v) => out.push(...encodeValue(v, itemType, structs, enums)));
283
- return out;
284
- }
285
- if (structs[type] && ((_a = structs[type].members) === null || _a === void 0 ? void 0 : _a.length)) {
286
- const out = [];
287
- structs[type].members.forEach((m) => out.push(...encodeValue(value[m.name], m.type, structs, enums)));
288
- return out;
289
- }
290
- if (isTypeTuple(type)) {
291
- const memberTypes = extractTupleMemberTypes(type);
292
- const elements = Object.values(value);
293
- if (elements.length !== memberTypes.length)
294
- throw new Error(`starknet: tuple size mismatch for ${type}`);
295
- const out = [];
296
- memberTypes.forEach((m, i) => out.push(...encodeValue(elements[i], memberType(m), structs, enums)));
297
- return out;
298
- }
299
- if (enums[type])
300
- throw new Error(`starknet: enum inputs are not supported (${type})`);
301
- if (typeof value === 'object')
302
- throw new Error(`starknet: parameter ${JSON.stringify(value)} does not match abi type ${type}`);
303
- return [felt(value)];
304
- }
305
- function asFnAbi(abiOrParams, key) {
306
- if (Array.isArray(abiOrParams))
307
- return { name: '', type: 'function', [key]: abiOrParams };
308
- return abiOrParams;
309
- }
310
- /**
311
- * Encode function arguments into calldata (array of hex felts).
312
- * @param fnAbi function abi entry (or just its `inputs` array)
313
- * @param params positional arguments
314
- * @param allAbi struct/enum definitions referenced by the function
315
- */
316
- function encodeCalldata(fnAbi, params = [], allAbi = []) {
317
- var _a;
318
- const abi = asFnAbi(fnAbi, 'inputs');
319
- if (!Array.isArray(params))
320
- params = [params];
321
- const structs = getAbiStructs([abi, ...allAbi]);
322
- const enums = getAbiEnums([abi, ...allAbi]);
323
- const inputs = (_a = abi.inputs) !== null && _a !== void 0 ? _a : [];
324
- const calldata = [];
325
- let idx = 0;
326
- for (const input of inputs) {
327
- // Cairo 0: `foo_len` inputs are derived from the array that follows
328
- if (isLen(input.name) && !isCairo1Type(input.type))
329
- continue;
330
- calldata.push(...encodeValue(params[idx++], input.type, structs, enums));
331
- }
332
- return calldata;
333
- }
334
- function next(it) {
335
- const { value, done } = it.next();
336
- if (done)
337
- throw new Error('starknet: response too short for abi');
338
- return value;
339
- }
340
- function decodeBase(type, it) {
341
- if (isTypeBool(type))
342
- return Boolean(BigInt(next(it)));
343
- if (isTypeU256(type)) {
344
- const low = BigInt(next(it));
345
- const high = BigInt(next(it));
346
- return (high << SHIFT_128) + low;
347
- }
348
- return BigInt(next(it));
349
- }
350
- function decodeValue(it, type, structs, enums) {
351
- var _a, _b;
352
- if (type === '()')
353
- return {};
354
- if (isTypeU256(type))
355
- return decodeBase(type, it);
356
- if (isTypeArray(type)) {
357
- const itemType = getArrayType(type);
358
- const len = BigInt(next(it));
359
- const out = [];
360
- while (out.length < len)
361
- out.push(decodeValue(it, itemType, structs, enums));
362
- return out;
363
- }
364
- if (structs[type]) {
365
- const out = {};
366
- ((_a = structs[type].members) !== null && _a !== void 0 ? _a : []).forEach((m) => { out[m.name] = decodeValue(it, m.type, structs, enums); });
367
- return out;
368
- }
369
- if (enums[type]) {
370
- const variantNum = Number(BigInt(next(it)));
371
- const variant = ((_b = enums[type].variants) !== null && _b !== void 0 ? _b : [])[variantNum];
372
- if (!variant)
373
- throw new Error(`starknet: unknown variant ${variantNum} for ${type}`);
374
- const content = decodeValue(it, variant.type, structs, enums);
375
- if (isTypeOption(type))
376
- return variantNum === 0 ? content : undefined;
377
- if (isTypeResult(type))
378
- return variantNum === 0 ? { Ok: content } : { Err: content };
379
- return { [variant.name]: content };
380
- }
381
- if (isTypeTuple(type)) {
382
- const out = {};
383
- extractTupleMemberTypes(type).forEach((m, i) => {
384
- out[memberName(m, i)] = decodeValue(it, memberType(m), structs, enums);
385
- });
386
- return out;
387
- }
388
- return decodeBase(type, it);
389
- }
390
- function decodeField(it, output, structs, enums, parsed) {
391
- var _a;
392
- const { name, type } = output;
393
- if (isLen(name))
394
- return BigInt(next(it));
395
- if (structs[type] || isTypeTuple(type) || enums[type])
396
- return decodeValue(it, type, structs, enums);
397
- if (isTypeArray(type)) {
398
- if (isCairo1Type(type))
399
- return decodeValue(it, type, structs, enums);
400
- // Cairo 0 `foo: felt*` is preceded by a `foo_len: felt` output
401
- const out = [];
402
- const len = (_a = parsed[`${name}_len`]) !== null && _a !== void 0 ? _a : ZERO;
403
- const itemType = type.replace('*', '');
404
- while (out.length < len)
405
- out.push(decodeValue(it, itemType, structs, enums));
406
- return out;
407
- }
408
- return decodeBase(type, it);
409
- }
410
- /**
411
- * Decode a starknet_call result according to the function abi.
412
- * @param fnAbi function abi entry (or just its `outputs` array)
413
- * @param result array of felts returned by the node
414
- * @param allAbi struct/enum definitions referenced by the function
415
- */
416
- function decodeOutput(fnAbi, result, allAbi = []) {
417
- var _a;
418
- const abi = asFnAbi(fnAbi, 'outputs');
419
- const structs = getAbiStructs([abi, ...allAbi]);
420
- const enums = getAbiEnums([abi, ...allAbi]);
421
- const it = result.flat()[Symbol.iterator]();
422
- const parsed = {};
423
- const outputs = (_a = abi.outputs) !== null && _a !== void 0 ? _a : [];
424
- outputs.forEach((output, idx) => {
425
- var _a;
426
- const key = (_a = output.name) !== null && _a !== void 0 ? _a : idx;
427
- parsed[key] = decodeField(it, output, structs, enums, parsed);
428
- if (parsed[key] && parsed[`${key}_len`])
429
- delete parsed[`${key}_len`];
430
- });
431
- return Object.keys(parsed).length === 1 && 0 in parsed ? parsed[0] : parsed;
432
- }
433
- // ---------------------------------------------------------------------------
434
- // call bodies / output post-processing
435
- // ---------------------------------------------------------------------------
436
- function toBlockId(block) {
437
- if (block === undefined || block === null)
438
- return 'latest';
439
- if (typeof block === 'number')
440
- return { block_number: block };
441
- if (typeof block === 'string') {
442
- if (['latest', 'pending', 'pre_confirmed', 'l1_accepted'].includes(block))
443
- return block;
444
- if (/^0x[0-9a-fA-F]+$/.test(block))
445
- return { block_hash: block };
446
- if (/^\d+$/.test(block))
447
- return { block_number: +block };
448
- throw new Error(`starknet: invalid block id ${block}`);
449
- }
450
- return block;
451
- }
452
- /**
453
- * Build a `starknet_call` JSON-RPC request. `abi.customInput === 'address'`
454
- * passes params through as raw felts (u256 inputs pre-split by the caller).
455
- */
456
- function formCallBody({ abi, target, params = [], allAbi = [], block }, id = 0) {
457
- if (!abi)
458
- throw new Error('starknet: missing abi');
459
- if (!target)
460
- throw new Error(`starknet: missing target for ${abi.name}`);
461
- if ((params || params === 0) && !Array.isArray(params))
462
- params = [params];
463
- if (params === undefined || params === null)
464
- params = [];
465
- let calldata = abi.customInput === 'address' ? params : encodeCalldata(abi, params, allAbi);
466
- // The RPC rejects calldata felts without a 0x prefix, normalize everything.
467
- calldata = calldata.map((i) => toHex(i));
468
- const requestData = {
469
- contract_address: String(target).toLowerCase(),
470
- entry_point_selector: getSelectorFromName(abi.name),
471
- calldata,
472
- };
473
- return { jsonrpc: '2.0', id, method: 'starknet_call', params: [requestData, toBlockId(block)] };
474
- }
475
- /**
476
- * Decode a call result and apply the legacy post-processing: BigInts at depth 1
477
- * become strings, a single non-Cairo 1 output is unwrapped, `Uint256` outputs
478
- * (or `customType: 'Uint256' | 'number'`) become numbers, `customType: 'address'`
479
- * is padded.
480
- */
481
- function parseOutput(result, abi, allAbi = [], { permitFailure = false, error } = {}) {
482
- var _a, _b;
483
- if (!result) {
484
- if (permitFailure)
485
- return null;
486
- throw new Error(`Starknet call ${(_a = abi === null || abi === void 0 ? void 0 : abi.name) !== null && _a !== void 0 ? _a : ''} failed: ${formatRpcError(error) || 'no result'}`);
487
- }
488
- let response = decodeOutput(abi, result, allAbi);
489
- if (typeof response === 'bigint')
490
- response = response.toString();
491
- else if (response && typeof response === 'object') {
492
- for (const key in response) {
493
- if (typeof response[key] === 'bigint')
494
- response[key] = response[key].toString();
495
- }
496
- }
497
- const outputs = (_b = abi.outputs) !== null && _b !== void 0 ? _b : [];
498
- if (outputs.length === 1 && !outputs[0].type.includes('::')) {
499
- const name = outputs[0].name;
500
- if (name !== undefined && response && typeof response === 'object')
501
- response = response[name];
502
- if (outputs[0].type === 'Uint256')
503
- return +response;
504
- }
505
- if (outputs.length === 1) {
506
- switch (abi.customType) {
507
- case 'address': return validateAndParseAddress(response);
508
- case 'Uint256':
509
- case 'number': return +response;
510
- }
511
- }
512
- return response;
513
- }
514
- function formatRpcError(e) {
515
- var _a, _b, _c, _d, _e, _f;
516
- if (!e)
517
- return '';
518
- const data = (_a = e.data) !== null && _a !== void 0 ? _a : (_b = e.error) === null || _b === void 0 ? void 0 : _b.data;
519
- const message = (_c = e.message) !== null && _c !== void 0 ? _c : (_d = e.error) === null || _d === void 0 ? void 0 : _d.message;
520
- const revert = (_f = (_e = data === null || data === void 0 ? void 0 : data.revert_error) !== null && _e !== void 0 ? _e : data === null || data === void 0 ? void 0 : data.execution_error) !== null && _f !== void 0 ? _f : (typeof data === 'string' ? data : undefined);
521
- if (revert) {
522
- const text = typeof revert === 'string' ? revert : JSON.stringify(revert);
523
- return message ? `${message}: ${text}` : text;
524
- }
525
- return message ? String(message) : JSON.stringify(e);
526
- }
527
- // ---------------------------------------------------------------------------
528
- // json-rpc
529
- // ---------------------------------------------------------------------------
530
- /** Raw JSON-RPC call against the Starknet endpoints (STARKNET_RPC rotation + retries) */
531
- async function rpc(method, params = []) {
532
- try {
533
- return await (0, rpc_1.jsonRpc)(method, params, rpcOptions());
534
- }
535
- catch (e) {
536
- if (e instanceof rpc_1.JsonRpcError)
537
- throw new Error(`Starknet ${method} failed: ${formatRpcError(e)}`);
538
- throw e;
539
- }
540
- }
541
- async function getBlockNumber() {
542
- return +(await rpc('starknet_blockNumber'));
543
- }
544
- async function getBlock({ blockNumber, block } = {}) {
545
- const id = toBlockId(block !== null && block !== void 0 ? block : blockNumber);
546
- const res = await rpc('starknet_getBlockWithTxHashes', [id]);
547
- return { number: +res.block_number, timestamp: +res.timestamp, hash: res.block_hash };
548
- }
549
- /** Last block whose timestamp is <= `timestamp` (binary search, no cache) */
550
- async function getBlockAtTimestamp({ timestamp }) {
551
- if (timestamp > 1e12)
552
- timestamp = Math.floor(timestamp / 1000);
553
- let hi = await getBlock({ blockNumber: 'latest' });
554
- if (hi.timestamp <= timestamp)
555
- return { number: hi.number, timestamp: hi.timestamp };
556
- let lo = { number: 0, timestamp: 0 };
557
- while (hi.number - lo.number > 1) {
558
- const mid = Math.floor((lo.number + hi.number) / 2);
559
- const b = await getBlock({ blockNumber: mid });
560
- if (b.timestamp <= timestamp)
561
- lo = { number: b.number, timestamp: b.timestamp };
562
- else
563
- hi = b;
564
- }
565
- if (lo.number === 0 && lo.timestamp === 0) {
566
- const b = await getBlock({ blockNumber: 0 });
567
- if (b.timestamp > timestamp)
568
- throw new Error(`starknet: timestamp ${timestamp} is before genesis`);
569
- return { number: b.number, timestamp: b.timestamp };
570
- }
571
- return lo;
572
- }
573
- async function getNonce({ address, block }) {
574
- return rpc('starknet_getNonce', [toBlockId(block), String(address).toLowerCase()]);
575
- }
576
- async function getClassHashAt({ address, block }) {
577
- return rpc('starknet_getClassHashAt', [toBlockId(block), String(address).toLowerCase()]);
578
- }
579
- // ---------------------------------------------------------------------------
580
- // call / multiCall
581
- // ---------------------------------------------------------------------------
582
- async function rawCall(request, block, permitFailure, abiName) {
583
- try {
584
- return await (0, rpc_1.jsonRpc)('starknet_call', [request, toBlockId(block)], rpcOptions());
585
- }
586
- catch (e) {
587
- if (permitFailure) {
588
- (0, debugLog_1.debugLog)(`[starknet] call ${abiName} on ${request.contract_address} failed (permitted): ${formatRpcError(e)}`);
589
- return null;
590
- }
591
- throw new Error(`Starknet call ${abiName} on ${request.contract_address} failed: ${formatRpcError(e)}`);
592
- }
593
- }
594
- async function call({ abi, target, params = [], allAbi = [], permitFailure = false, block }) {
595
- const body = formCallBody({ abi, target, params, allAbi, block });
596
- const result = await limiter()(() => rawCall(body.params[0], block, permitFailure, abi.name));
597
- return parseOutput(result, abi, allAbi, { permitFailure });
598
- }
599
- function normalizeCalls({ abi: rootAbi, target: rootTarget, calls, allAbi = [] }) {
600
- return calls.map((callArgs, i) => {
601
- var _a;
602
- let item;
603
- if (callArgs === null || typeof callArgs !== 'object') {
604
- if (!rootTarget)
605
- item = { target: callArgs, params: [], abi: rootAbi, allAbi };
606
- else
607
- item = { target: rootTarget, params: callArgs, abi: rootAbi, allAbi };
608
- }
609
- else {
610
- const { target, params, abi } = callArgs;
611
- item = { target: (target || rootTarget), params, abi: (abi || rootAbi), allAbi: (_a = callArgs.allAbi) !== null && _a !== void 0 ? _a : allAbi };
612
- }
613
- if (!item.abi)
614
- throw new Error(`starknet: multiCall item ${i} has no abi`);
615
- if (!item.target)
616
- throw new Error(`starknet: multiCall item ${i} has no target`);
617
- return item;
618
- });
619
- }
620
- /**
621
- * Run many `starknet_call`s. By default one on-chain `aggregate` call per 50
622
- * sub-calls; if the aggregator reverts (any sub-call reverting reverts the whole
623
- * batch) or `useAggregator` is false, falls back to JSON-RPC batches of 25 so
624
- * `permitFailure` still applies per call. Results are in call order.
625
- */
626
- async function multiCall(options) {
627
- const { calls = [], permitFailure = false, useAggregator = true, block } = options;
628
- if (!calls.length)
629
- return [];
630
- const normalized = normalizeCalls(options);
631
- return limiter()(async () => {
632
- if (useAggregator) {
633
- try {
634
- return await aggregateMultiCall(normalized, block);
635
- }
636
- catch (e) {
637
- (0, debugLog_1.debugLog)(`[starknet] aggregate multicall failed, falling back to batched calls: ${formatRpcError(e)}`);
638
- }
639
- }
640
- return batchedMultiCall(normalized, permitFailure, block);
641
- });
642
- }
643
- /** One starknet_call to the on-chain aggregator covering all sub-calls. */
644
- async function aggregateMultiCall(calls, block) {
645
- const aggregator = getMulticallAddress();
646
- const aggSelector = getSelectorFromName('aggregate');
647
- const response = [];
648
- const chunks = (0, rpc_1.sliceIntoChunks)(calls, exports.AGGREGATE_CHUNK_SIZE);
649
- let offset = 0;
650
- for (let c = 0; c < chunks.length; c++) {
651
- const chunk = chunks[c];
652
- if (c > 0)
653
- await (0, rpc_1.sleep)(CHUNK_SLEEP_MS);
654
- // Build the Call[] calldata: [n, (to, selector, calldata_len, ...calldata) x n]
655
- const aggCalldata = [toHex(chunk.length)];
656
- chunk.forEach((item) => {
657
- const body = formCallBody(item).params[0];
658
- aggCalldata.push(body.contract_address, body.entry_point_selector, toHex(body.calldata.length), ...body.calldata);
659
- });
660
- const request = { contract_address: aggregator, entry_point_selector: aggSelector, calldata: aggCalldata };
661
- const result = await (0, rpc_1.jsonRpc)('starknet_call', [request, toBlockId(block)], rpcOptions());
662
- if (!Array.isArray(result))
663
- throw new Error('aggregate failed: empty result');
664
- // result layout: [block_number, results_len, (span_len, ...span_felts) x results_len]
665
- let i = 1; // skip block_number
666
- const resultsLen = Number(toBigInt(result[i++]));
667
- if (resultsLen !== chunk.length)
668
- throw new Error(`aggregate returned ${resultsLen} results for ${chunk.length} calls`);
669
- for (let j = 0; j < resultsLen; j++) {
670
- const spanLen = Number(toBigInt(result[i++]));
671
- const span = result.slice(i, i + spanLen);
672
- i += spanLen;
673
- const item = chunk[j];
674
- response[offset + j] = parseOutput(span, item.abi, item.allAbi);
675
- }
676
- offset += chunk.length;
677
- }
678
- return response;
679
- }
680
- /** N individual starknet_call requests packed into JSON-RPC batches. */
681
- async function batchedMultiCall(calls, permitFailure, block) {
682
- const bodies = calls.map((item, id) => formCallBody({ ...item, block }, id));
683
- const response = new Array(calls.length);
684
- const chunks = (0, rpc_1.sliceIntoChunks)(bodies, exports.BATCH_CHUNK_SIZE);
685
- for (let c = 0; c < chunks.length; c++) {
686
- const chunk = chunks[c];
687
- if (c > 0)
688
- await (0, rpc_1.sleep)(CHUNK_SLEEP_MS);
689
- let results;
690
- if (chunk.length === 1) {
691
- // some providers (e.g. lava.build) answer a one-element batch with a bare
692
- // object; use a plain call for that case
693
- const body = chunk[0];
694
- results = [await rawCall(body.params[0], block, permitFailure, calls[body.id].abi.name)];
695
- }
696
- else {
697
- try {
698
- results = await (0, rpc_1.jsonRpcBatch)(chunk.map((b) => ({ method: b.method, params: b.params, id: b.id })), { ...rpcOptions(), permitFailure });
699
- }
700
- catch (e) {
701
- if (e instanceof rpc_1.JsonRpcError)
702
- throw new Error(`Starknet call ${e.method} failed: ${formatRpcError(e)}`);
703
- throw e;
704
- }
705
- }
706
- chunk.forEach((body, i) => {
707
- const id = body.id;
708
- const item = calls[id];
709
- response[id] = parseOutput(results[i], item.abi, item.allAbi, { permitFailure });
710
- });
711
- }
712
- return response;
713
- }
714
- // ---------------------------------------------------------------------------
715
- // events
716
- // ---------------------------------------------------------------------------
717
- /** starknet_getEvents page size; public providers reject larger pages ("Requested page size is too big") */
718
- exports.DEFAULT_EVENTS_CHUNK_SIZE = 1000;
719
- const MIN_EVENTS_CHUNK_SIZE = 100;
720
- function isPageSizeError(e) {
721
- var _a, _b;
722
- const message = String((_b = (_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : e) !== null && _b !== void 0 ? _b : '').toLowerCase();
723
- return message.includes('page size') || message.includes('chunk_size') || message.includes('chunk size');
724
- }
725
- /**
726
- * Fetch events emitted by `target` via `starknet_getEvents`, following
727
- * `continuation_token` until the range [fromBlock, toBlock] is exhausted.
728
- * Returns raw events: { block_number, transaction_hash, from_address, keys, data }.
729
- */
730
- async function getLogs({ target, fromBlock, toBlock, topics, keys, chunkSize = exports.DEFAULT_EVENTS_CHUNK_SIZE }) {
731
- if (!target)
732
- throw new Error('Missing target!');
733
- if (fromBlock === undefined || fromBlock === null)
734
- throw new Error('Missing fromBlock!');
735
- if (!keys && topics)
736
- keys = [topics];
737
- const keyFilter = (keys !== null && keys !== void 0 ? keys : []).map((k) => (Array.isArray(k) ? k : [k]).map((i) => toHex(i)));
738
- const address = String(target).toLowerCase();
739
- return limiter()(async () => {
740
- var _a;
741
- const end = toBlock !== null && toBlock !== void 0 ? toBlock : await getBlockNumber();
742
- if (fromBlock > end)
743
- return [];
744
- const filter = {
745
- from_block: { block_number: fromBlock },
746
- to_block: { block_number: end },
747
- address,
748
- keys: keyFilter,
749
- chunk_size: chunkSize,
750
- };
751
- const logs = [];
752
- let pages = 0;
753
- while (true) {
754
- let page;
755
- try {
756
- page = await rpc('starknet_getEvents', [filter]);
757
- }
758
- catch (e) {
759
- // providers cap chunk_size at different values; shrink and retry the same page
760
- if (isPageSizeError(e) && filter.chunk_size > MIN_EVENTS_CHUNK_SIZE) {
761
- filter.chunk_size = Math.max(MIN_EVENTS_CHUNK_SIZE, Math.floor(filter.chunk_size / 2));
762
- (0, debugLog_1.debugLog)(`[starknet] getLogs page size rejected, retrying with chunk_size ${filter.chunk_size}`);
763
- continue;
764
- }
765
- throw e;
766
- }
767
- logs.push(...((_a = page === null || page === void 0 ? void 0 : page.events) !== null && _a !== void 0 ? _a : []));
768
- pages++;
769
- if (!(page === null || page === void 0 ? void 0 : page.continuation_token))
770
- break;
771
- filter.continuation_token = page.continuation_token;
772
- }
773
- (0, debugLog_1.debugLog)(`[starknet] getLogs ${address} [${fromBlock}, ${end}]: ${logs.length} events in ${pages} page(s)`);
774
- return logs;
775
- });
776
- }
777
- // ---------------------------------------------------------------------------
778
- // ERC20 ABIs
779
- // ---------------------------------------------------------------------------
780
- /**
781
- * Cairo 0 style ERC20 ABIs (camelCase entrypoints, `felt` / `Uint256` types).
782
- * `balanceOf` uses `customInput: 'address'` so the owner felt is passed through
783
- * untouched; `decimals` casts to a number.
784
- */
785
- exports.erc20Abis = {
786
- balanceOf: {
787
- name: 'balanceOf',
788
- type: 'function',
789
- inputs: [{ name: 'account', type: 'felt' }],
790
- outputs: [{ name: 'balance', type: 'Uint256' }],
791
- stateMutability: 'view',
792
- customInput: 'address',
793
- },
794
- totalSupply: {
795
- name: 'totalSupply',
796
- type: 'function',
797
- inputs: [],
798
- outputs: [{ name: 'totalSupply', type: 'Uint256' }],
799
- stateMutability: 'view',
800
- },
801
- decimals: {
802
- name: 'decimals',
803
- type: 'function',
804
- inputs: [],
805
- outputs: [{ name: 'decimals', type: 'felt' }],
806
- stateMutability: 'view',
807
- customType: 'number',
808
- },
809
- name: {
810
- name: 'name',
811
- type: 'function',
812
- inputs: [],
813
- outputs: [{ name: 'name', type: 'felt' }],
814
- stateMutability: 'view',
815
- },
816
- symbol: {
817
- name: 'symbol',
818
- type: 'function',
819
- inputs: [],
820
- outputs: [{ name: 'symbol', type: 'felt' }],
821
- stateMutability: 'view',
822
- },
823
- allowance: {
824
- name: 'allowance',
825
- type: 'function',
826
- inputs: [{ name: 'owner', type: 'felt' }, { name: 'spender', type: 'felt' }],
827
- outputs: [{ name: 'remaining', type: 'Uint256' }],
828
- stateMutability: 'view',
829
- },
830
- };
831
- /**
832
- * Cairo 1 style ERC20 ABIs (snake_case entrypoints, `core::` types). u256
833
- * outputs decode to a bigint (returned as a decimal string by `call`).
834
- */
835
- exports.erc20AbisCairo1 = {
836
- balanceOf: {
837
- name: 'balance_of',
838
- type: 'function',
839
- inputs: [{ name: 'account', type: 'core::starknet::contract_address::ContractAddress' }],
840
- outputs: [{ type: 'core::integer::u256' }],
841
- state_mutability: 'view',
842
- },
843
- totalSupply: {
844
- name: 'total_supply',
845
- type: 'function',
846
- inputs: [],
847
- outputs: [{ type: 'core::integer::u256' }],
848
- state_mutability: 'view',
849
- },
850
- decimals: {
851
- name: 'decimals',
852
- type: 'function',
853
- inputs: [],
854
- outputs: [{ type: 'core::integer::u8' }],
855
- state_mutability: 'view',
856
- customType: 'number',
857
- },
858
- name: {
859
- name: 'name',
860
- type: 'function',
861
- inputs: [],
862
- outputs: [{ type: 'core::felt252' }],
863
- state_mutability: 'view',
864
- },
865
- symbol: {
866
- name: 'symbol',
867
- type: 'function',
868
- inputs: [],
869
- outputs: [{ type: 'core::felt252' }],
870
- state_mutability: 'view',
871
- },
872
- allowance: {
873
- name: 'allowance',
874
- type: 'function',
875
- inputs: [
876
- { name: 'owner', type: 'core::starknet::contract_address::ContractAddress' },
877
- { name: 'spender', type: 'core::starknet::contract_address::ContractAddress' },
878
- ],
879
- outputs: [{ type: 'core::integer::u256' }],
880
- state_mutability: 'view',
881
- },
882
- };
883
- /** alias matching the coins repo export */
884
- exports.cairoErc20Abis = exports.erc20AbisCairo1;