@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,1082 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.XdrReader = exports.XdrWriter = exports.NATIVE_ASSET = exports.STRKEY_VERSION = exports.SC_ADDR = exports.SC_VAL = exports.STELLAR_DECIMALS = exports.PUBLIC_NETWORK_PASSPHRASE = exports.DEFAULT_SOROBAN_ENDPOINTS = exports.DEFAULT_HORIZON = void 0;
4
- exports.getHorizonEndpoints = getHorizonEndpoints;
5
- exports.getHorizonEndpoint = getHorizonEndpoint;
6
- exports.getSorobanEndpoints = getSorobanEndpoints;
7
- exports.base32Encode = base32Encode;
8
- exports.base32Decode = base32Decode;
9
- exports.crc16xmodem = crc16xmodem;
10
- exports.encodeStrKey = encodeStrKey;
11
- exports.decodeStrKey = decodeStrKey;
12
- exports.strKeyToBytes = strKeyToBytes;
13
- exports.isValidStrKey = isValidStrKey;
14
- exports.isContractId = isContractId;
15
- exports.isAccountId = isAccountId;
16
- exports.isNativeAsset = isNativeAsset;
17
- exports.parseAsset = parseAsset;
18
- exports.assetToString = assetToString;
19
- exports.toRaw = toRaw;
20
- exports.fromRaw = fromRaw;
21
- exports.readScVal = readScVal;
22
- exports.parseScVal = parseScVal;
23
- exports.normalizeScArg = normalizeScArg;
24
- exports.writeSymbol = writeSymbol;
25
- exports.writeInt = writeInt;
26
- exports.writeScAddress = writeScAddress;
27
- exports.writeAddress = writeAddress;
28
- exports.writeScVal = writeScVal;
29
- exports.encodeScVal = encodeScVal;
30
- exports.writeAsset = writeAsset;
31
- exports.getNetworkId = getNetworkId;
32
- exports.getSacContractId = getSacContractId;
33
- exports.buildInvokeContractEnvelope = buildInvokeContractEnvelope;
34
- exports.buildContractInstanceLedgerKey = buildContractInstanceLedgerKey;
35
- exports.horizonGet = horizonGet;
36
- exports.getAccount = getAccount;
37
- exports.getAccountBalances = getAccountBalances;
38
- exports.getNativeBalance = getNativeBalance;
39
- exports.getTokenBalance = getTokenBalance;
40
- exports.getAsset = getAsset;
41
- exports.getAssetSupply = getAssetSupply;
42
- exports.getLedger = getLedger;
43
- exports.getLatestLedger = getLatestLedger;
44
- exports.getLedgerAtTimestamp = getLedgerAtTimestamp;
45
- exports.sorobanRpc = sorobanRpc;
46
- exports.getLatestSorobanLedger = getLatestSorobanLedger;
47
- exports.simulateTransaction = simulateTransaction;
48
- exports.callSoroban = callSoroban;
49
- exports.getLedgerEntries = getLedgerEntries;
50
- exports.getContractInstance = getContractInstance;
51
- exports.getContractInstanceStorage = getContractInstanceStorage;
52
- exports.getSorobanTokenBalance = getSorobanTokenBalance;
53
- exports.getSorobanTokenDecimals = getSorobanTokenDecimals;
54
- exports.getSorobanTokenSymbol = getSorobanTokenSymbol;
55
- exports.getSorobanTokenName = getSorobanTokenName;
56
- exports.getSorobanTokenTotalSupply = getSorobanTokenTotalSupply;
57
- exports.getSacClassicAsset = getSacClassicAsset;
58
- exports.getTokenSupply = getTokenSupply;
59
- /**
60
- * Stellar client: Horizon REST + Soroban JSON-RPC with a hand-rolled StrKey / XDR
61
- * codec (RFC 4648 base32, CRC16-XMODEM, ScVal reader/writer) so nothing from
62
- * `@stellar/stellar-sdk` or `hi-base32` is needed.
63
- *
64
- * Replaces the per-repo Stellar helpers:
65
- * - DefiLlama-Adapters/projects/helper/chain/stellar.js (getAssetSupply, getTokenBalance,
66
- * SC_VAL / SC_ADDR / STRKEY_VERSION, decodeStrKey, crc16xmodem, encodeStrKey, parseScVal,
67
- * XDR writers, callSoroban / simulateTransaction envelope, getContractInstanceStorage)
68
- * - server/defi/l2/utils.ts (stellarSacToClassic, isSorobanContractId, getStellarSupplies)
69
- * - server/defi/src/rwa/balances.ts (fetchStellar account balances, CODE-ISSUER parsing)
70
- * - peggedassets-server/src/adapters/peggedAssets/helper/stellar.ts and
71
- * peggedassets-server/src/adapters/peggedAssets/valtorum-usdv/index.ts (Horizon /assets supply)
72
- *
73
- * Endpoints: `STELLAR_HORIZON` env overrides `DEFAULT_HORIZON`, `STELLAR_SOROBAN_RPC`
74
- * (comma separated) overrides `DEFAULT_SOROBAN_ENDPOINTS`.
75
- *
76
- * Amount conventions: Horizon reports 7-decimal display strings ("12.3456789"); every
77
- * `raw` / supply / balance value returned here is the integer stroop amount (x1e7) as a
78
- * decimal string. Soroban i128 / u128 results come back as `bigint` from `parseScVal`
79
- * and are stringified by the token helpers.
80
- */
81
- const crypto_1 = require("crypto");
82
- const rpc_1 = require("./rpc");
83
- const debugLog_1 = require("../util/debugLog");
84
- // ---------------------------------------------------------------------------
85
- // config
86
- // ---------------------------------------------------------------------------
87
- exports.DEFAULT_HORIZON = 'https://horizon.stellar.org';
88
- exports.DEFAULT_SOROBAN_ENDPOINTS = [
89
- 'https://mainnet.sorobanrpc.com',
90
- 'https://soroban-rpc.creit.tech',
91
- ];
92
- exports.PUBLIC_NETWORK_PASSPHRASE = 'Public Global Stellar Network ; September 2015';
93
- /** Classic assets and Stellar Asset Contracts always have 7 decimals. */
94
- exports.STELLAR_DECIMALS = 7;
95
- const HORIZON_CONCURRENCY = 5;
96
- const SOROBAN_CONCURRENCY = 5;
97
- function getHorizonEndpoints() {
98
- return (0, rpc_1.getEndpoints)('stellar_horizon', exports.DEFAULT_HORIZON, { envKey: 'STELLAR_HORIZON' });
99
- }
100
- function getHorizonEndpoint() {
101
- return getHorizonEndpoints()[0];
102
- }
103
- function getSorobanEndpoints() {
104
- return (0, rpc_1.getEndpoints)('stellar_soroban', exports.DEFAULT_SOROBAN_ENDPOINTS, { envKey: 'STELLAR_SOROBAN_RPC' });
105
- }
106
- // ---------------------------------------------------------------------------
107
- // constants (Stellar-contract.x / Stellar-ledger-entries.x / SEP-23)
108
- // ---------------------------------------------------------------------------
109
- /** SCValType discriminants: https://github.com/stellar/stellar-xdr/blob/main/Stellar-contract.x */
110
- exports.SC_VAL = {
111
- BOOL: 0, VOID: 1, ERROR: 2, U32: 3, I32: 4, U64: 5, I64: 6, TIMEPOINT: 7, DURATION: 8,
112
- U128: 9, I128: 10, U256: 11, I256: 12, BYTES: 13, STRING: 14, SYMBOL: 15,
113
- VEC: 16, MAP: 17, ADDRESS: 18,
114
- CONTRACT_INSTANCE: 19, LEDGER_KEY_CONTRACT_INSTANCE: 20, LEDGER_KEY_NONCE: 21,
115
- };
116
- /** SCAddressType discriminants (inside ScVal::Address / InvokeContractArgs). */
117
- exports.SC_ADDR = { ACCOUNT: 0, CONTRACT: 1, MUXED_ACCOUNT: 2, CLAIMABLE_BALANCE: 3, LIQUIDITY_POOL: 4 };
118
- /** StrKey version bytes (SEP-23): the first base32 char of the encoded key. */
119
- exports.STRKEY_VERSION = {
120
- ACCOUNT: 6 << 3, // G
121
- MUXED_ACCOUNT: 12 << 3, // M
122
- SEED: 18 << 3, // S
123
- PRE_AUTH_TX: 19 << 3, // T
124
- SHA256_HASH: 23 << 3, // X
125
- SIGNED_PAYLOAD: 15 << 3, // P
126
- CONTRACT: 2 << 3, // C
127
- CLAIMABLE_BALANCE: 1 << 3, // B
128
- LIQUIDITY_POOL: 11 << 3, // L
129
- };
130
- const ENVELOPE_TYPE_TX = 2;
131
- const ENVELOPE_TYPE_CONTRACT_ID = 8; // EnvelopeType: TX_V0 0, SCP 1, TX 2, AUTH 3, SCPVALUE 4, TX_FEE_BUMP 5, OP_ID 6, POOL_REVOKE_OP_ID 7, CONTRACT_ID 8
132
- const CONTRACT_ID_PREIMAGE_FROM_ASSET = 1;
133
- const OP_INVOKE_HOST_FUNCTION = 24;
134
- const HOST_FUNCTION_TYPE_INVOKE_CONTRACT = 0;
135
- const LEDGER_ENTRY_CONTRACT_DATA = 6;
136
- const CONTRACT_DATA_DURABILITY_PERSISTENT = 1;
137
- const CONTRACT_EXECUTABLE_WASM = 0;
138
- const KEY_TYPE_ED25519 = 0;
139
- const CONTRACT_ID_RE = /^C[A-Z2-7]{55}$/;
140
- const ACCOUNT_ID_RE = /^G[A-Z2-7]{55}$/;
141
- const ASSET_CODE_RE = /^[A-Za-z0-9]{1,12}$/;
142
- // ---------------------------------------------------------------------------
143
- // base32 (RFC 4648, upper-case alphabet, padding optional)
144
- // ---------------------------------------------------------------------------
145
- const B32_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
146
- const B32_LOOKUP = {};
147
- for (let i = 0; i < B32_ALPHABET.length; i++)
148
- B32_LOOKUP[B32_ALPHABET[i]] = i;
149
- function base32Encode(data, { padding = false } = {}) {
150
- let bits = 0, value = 0, out = '';
151
- for (let i = 0; i < data.length; i++) {
152
- value = (value << 8) | data[i];
153
- bits += 8;
154
- while (bits >= 5) {
155
- out += B32_ALPHABET[(value >>> (bits - 5)) & 31];
156
- bits -= 5;
157
- }
158
- value &= (1 << bits) - 1;
159
- }
160
- if (bits > 0)
161
- out += B32_ALPHABET[(value << (5 - bits)) & 31];
162
- if (padding)
163
- while (out.length % 8)
164
- out += '=';
165
- return out;
166
- }
167
- function base32Decode(str) {
168
- const clean = str.replace(/=+$/, '').toUpperCase();
169
- const out = [];
170
- let bits = 0, value = 0;
171
- for (let i = 0; i < clean.length; i++) {
172
- const v = B32_LOOKUP[clean[i]];
173
- if (v === undefined)
174
- throw new Error(`base32: invalid character "${clean[i]}" in "${str}"`);
175
- value = (value << 5) | v;
176
- bits += 5;
177
- if (bits >= 8) {
178
- out.push((value >>> (bits - 8)) & 0xff);
179
- bits -= 8;
180
- value &= (1 << bits) - 1;
181
- }
182
- }
183
- return Buffer.from(out);
184
- }
185
- // ---------------------------------------------------------------------------
186
- // StrKey (SEP-23): version byte + payload + CRC16-XMODEM (little endian), base32 without padding
187
- // ---------------------------------------------------------------------------
188
- function crc16xmodem(data) {
189
- let crc = 0;
190
- for (let i = 0; i < data.length; i++) {
191
- crc ^= data[i] << 8;
192
- for (let j = 0; j < 8; j++)
193
- crc = (crc & 0x8000) ? ((crc << 1) ^ 0x1021) & 0xffff : (crc << 1) & 0xffff;
194
- }
195
- return crc;
196
- }
197
- function encodeStrKey(version, payload) {
198
- const body = Buffer.concat([Buffer.from([version]), Buffer.from(payload)]);
199
- const checksum = Buffer.alloc(2);
200
- checksum.writeUInt16LE(crc16xmodem(body), 0);
201
- return base32Encode(Buffer.concat([body, checksum]));
202
- }
203
- /** Decode a StrKey; validates the checksum and that the encoding is canonical. */
204
- function decodeStrKey(str) {
205
- if (typeof str !== 'string' || !str.length)
206
- throw new Error(`Invalid StrKey: ${str}`);
207
- const raw = base32Decode(str);
208
- if (raw.length < 4)
209
- throw new Error(`Invalid StrKey (too short): ${str}`);
210
- const version = raw[0];
211
- const payload = raw.slice(1, raw.length - 2);
212
- const checksum = raw.readUInt16LE(raw.length - 2);
213
- if (checksum !== crc16xmodem(raw.slice(0, raw.length - 2)))
214
- throw new Error(`Invalid StrKey checksum: ${str}`);
215
- if (encodeStrKey(version, payload) !== str)
216
- throw new Error(`Invalid StrKey (non canonical): ${str}`);
217
- return { version, payload };
218
- }
219
- /** Payload bytes of a StrKey, optionally asserting the version byte. */
220
- function strKeyToBytes(str, expectedVersion) {
221
- const { version, payload } = decodeStrKey(str);
222
- if (expectedVersion !== undefined && version !== expectedVersion)
223
- throw new Error(`StrKey ${str} has version ${version}, expected ${expectedVersion}`);
224
- return payload;
225
- }
226
- function isValidStrKey(str, version) {
227
- try {
228
- const decoded = decodeStrKey(str);
229
- return version === undefined || decoded.version === version;
230
- }
231
- catch {
232
- return false;
233
- }
234
- }
235
- /** Soroban contract id (`C...`, 56 chars). Format check only; use `isValidStrKey` for checksum validation. */
236
- function isContractId(str) {
237
- return typeof str === 'string' && CONTRACT_ID_RE.test(str);
238
- }
239
- /** Classic account id (`G...`, 56 chars). Format check only. */
240
- function isAccountId(str) {
241
- return typeof str === 'string' && ACCOUNT_ID_RE.test(str);
242
- }
243
- exports.NATIVE_ASSET = { code: 'XLM' };
244
- function isNativeAsset(asset) {
245
- return !asset.issuer;
246
- }
247
- /**
248
- * Parse `native` / `XLM`, `CODE-ISSUER` (DefiLlama convention), `CODE:ISSUER`
249
- * (Horizon / stellar.expert convention) or an already parsed `{ code, issuer }`.
250
- */
251
- function parseAsset(asset) {
252
- if (asset && typeof asset === 'object') {
253
- if (!asset.issuer)
254
- return exports.NATIVE_ASSET;
255
- return validateAsset({ code: asset.code, issuer: asset.issuer });
256
- }
257
- if (typeof asset !== 'string')
258
- throw new Error(`Invalid Stellar asset: ${asset}`);
259
- const s = asset.trim();
260
- if (s.toLowerCase() === 'native' || s.toUpperCase() === 'XLM')
261
- return exports.NATIVE_ASSET;
262
- // issuer is always 56 chars, so split on the last separator to allow codes containing '-'/':' (they cannot, but be safe)
263
- const sep = Math.max(s.lastIndexOf('-'), s.lastIndexOf(':'));
264
- if (sep === -1)
265
- throw new Error(`Invalid Stellar asset "${asset}": expected CODE-ISSUER, CODE:ISSUER or native`);
266
- return validateAsset({ code: s.slice(0, sep), issuer: s.slice(sep + 1) });
267
- }
268
- function validateAsset(asset) {
269
- if (!ASSET_CODE_RE.test(asset.code))
270
- throw new Error(`Invalid Stellar asset code "${asset.code}"`);
271
- if (!isAccountId(asset.issuer))
272
- throw new Error(`Invalid Stellar asset issuer "${asset.issuer}"`);
273
- return asset;
274
- }
275
- /** `native` or `CODE-ISSUER` (or `CODE:ISSUER` with `separator: ':'`). */
276
- function assetToString(asset, { separator = '-' } = {}) {
277
- const parsed = parseAsset(asset);
278
- if (isNativeAsset(parsed))
279
- return 'native';
280
- return `${parsed.code}${separator}${parsed.issuer}`;
281
- }
282
- /** Horizon 7-decimal display string -> stroops as a decimal string, using string math (no float rounding). */
283
- function toRaw(amount, decimals = exports.STELLAR_DECIMALS) {
284
- let s = typeof amount === 'number' ? amount.toFixed(decimals) : String(amount).trim();
285
- if (!s)
286
- return '0';
287
- const negative = s.startsWith('-');
288
- if (negative)
289
- s = s.slice(1);
290
- const [intPart, fracPart = ''] = s.split('.');
291
- if (!/^\d*$/.test(intPart) || !/^\d*$/.test(fracPart))
292
- throw new Error(`Invalid decimal amount: ${amount}`);
293
- const frac = (fracPart + '0'.repeat(decimals)).slice(0, decimals);
294
- const value = BigInt((intPart || '0') + frac);
295
- return (negative ? -value : value).toString();
296
- }
297
- /** Stroops -> display string (`"12.3456789"`), trailing zeros trimmed. */
298
- function fromRaw(raw, decimals = exports.STELLAR_DECIMALS) {
299
- let value = BigInt(raw);
300
- const negative = value < BigInt(0);
301
- if (negative)
302
- value = -value;
303
- const s = value.toString().padStart(decimals + 1, '0');
304
- const intPart = s.slice(0, s.length - decimals);
305
- const frac = s.slice(s.length - decimals).replace(/0+$/, '');
306
- return (negative ? '-' : '') + intPart + (frac ? '.' + frac : '');
307
- }
308
- // ---------------------------------------------------------------------------
309
- // XDR reader / writer (RFC 4506: big endian, 4-byte alignment)
310
- // ---------------------------------------------------------------------------
311
- const TWO_64 = BigInt(1) << BigInt(64);
312
- const MASK_64 = TWO_64 - BigInt(1);
313
- function padLength(n) {
314
- return n + ((4 - (n % 4)) % 4);
315
- }
316
- class XdrWriter {
317
- constructor() {
318
- this.chunks = [];
319
- }
320
- u32(value) {
321
- if (!Number.isInteger(value) || value < 0 || value > 0xffffffff)
322
- throw new Error(`u32 out of range: ${value}`);
323
- const b = Buffer.alloc(4);
324
- b.writeUInt32BE(value, 0);
325
- this.chunks.push(b);
326
- return this;
327
- }
328
- i32(value) {
329
- if (!Number.isInteger(value) || value < -0x80000000 || value > 0x7fffffff)
330
- throw new Error(`i32 out of range: ${value}`);
331
- const b = Buffer.alloc(4);
332
- b.writeInt32BE(value, 0);
333
- this.chunks.push(b);
334
- return this;
335
- }
336
- /** unsigned 64-bit, value must already be in range */
337
- u64(value) {
338
- const n = BigInt(value);
339
- if (n < BigInt(0) || n > MASK_64)
340
- throw new Error(`u64 out of range: ${value}`);
341
- return this.u32(Number(n >> BigInt(32))).u32(Number(n & BigInt(0xffffffff)));
342
- }
343
- i64(value) {
344
- const n = BigInt(value);
345
- if (n < -(BigInt(1) << BigInt(63)) || n > (BigInt(1) << BigInt(63)) - BigInt(1))
346
- throw new Error(`i64 out of range: ${value}`);
347
- return this.u64(n < BigInt(0) ? n + TWO_64 : n);
348
- }
349
- /** fixed length opaque, no length prefix, padded to 4 bytes */
350
- bytes(data) {
351
- const b = Buffer.from(data);
352
- this.chunks.push(b);
353
- const pad = padLength(b.length) - b.length;
354
- if (pad)
355
- this.chunks.push(Buffer.alloc(pad));
356
- return this;
357
- }
358
- /** variable length opaque: u32 length + data + padding */
359
- opaque(data) {
360
- return this.u32(data.length).bytes(data);
361
- }
362
- string(value) {
363
- return this.opaque(Buffer.from(value, 'utf8'));
364
- }
365
- toBuffer() {
366
- return Buffer.concat(this.chunks);
367
- }
368
- toBase64() {
369
- return this.toBuffer().toString('base64');
370
- }
371
- }
372
- exports.XdrWriter = XdrWriter;
373
- class XdrReader {
374
- constructor(input, offset = 0) {
375
- this.buf = typeof input === 'string' ? Buffer.from(input, 'base64') : Buffer.from(input);
376
- this.offset = offset;
377
- }
378
- need(n) {
379
- if (this.offset + n > this.buf.length)
380
- throw new Error(`XDR: unexpected end of data (need ${n} bytes at ${this.offset}, have ${this.buf.length})`);
381
- }
382
- u32() {
383
- this.need(4);
384
- const v = this.buf.readUInt32BE(this.offset);
385
- this.offset += 4;
386
- return v;
387
- }
388
- i32() {
389
- this.need(4);
390
- const v = this.buf.readInt32BE(this.offset);
391
- this.offset += 4;
392
- return v;
393
- }
394
- u64() {
395
- const hi = this.u32(), lo = this.u32();
396
- return (BigInt(hi) << BigInt(32)) | BigInt(lo);
397
- }
398
- i64() {
399
- const u = this.u64();
400
- return u >= (BigInt(1) << BigInt(63)) ? u - TWO_64 : u;
401
- }
402
- /** `words` big-endian u64 limbs -> unsigned bigint */
403
- uintN(words) {
404
- let v = BigInt(0);
405
- for (let i = 0; i < words; i++)
406
- v = (v << BigInt(64)) | this.u64();
407
- return v;
408
- }
409
- intN(words) {
410
- const bits = BigInt(words * 64);
411
- const u = this.uintN(words);
412
- return u >= (BigInt(1) << (bits - BigInt(1))) ? u - (BigInt(1) << bits) : u;
413
- }
414
- bytes(n) {
415
- this.need(padLength(n));
416
- const b = Buffer.from(this.buf.slice(this.offset, this.offset + n));
417
- this.offset += padLength(n);
418
- return b;
419
- }
420
- opaque() {
421
- return this.bytes(this.u32());
422
- }
423
- string() {
424
- return this.opaque().toString('utf8');
425
- }
426
- get remaining() {
427
- return this.buf.length - this.offset;
428
- }
429
- }
430
- exports.XdrReader = XdrReader;
431
- /** Keys of ScMap / instance storage: contracttype enum keys encode as Vec[Symbol(variant), ...] -> use the variant name. */
432
- function mapKey(k) {
433
- if (Array.isArray(k))
434
- return k.length && typeof k[0] === 'string' ? k[0] : JSON.stringify(k, jsonReplacer);
435
- if (k !== null && typeof k === 'object')
436
- return JSON.stringify(k, jsonReplacer);
437
- return String(k);
438
- }
439
- function jsonReplacer(_, v) {
440
- return typeof v === 'bigint' ? v.toString() : v;
441
- }
442
- function readScAddress(r) {
443
- const type = r.u32();
444
- switch (type) {
445
- case exports.SC_ADDR.ACCOUNT: {
446
- const keyType = r.u32();
447
- if (keyType !== KEY_TYPE_ED25519)
448
- throw new Error(`Unsupported PublicKey type: ${keyType}`);
449
- return encodeStrKey(exports.STRKEY_VERSION.ACCOUNT, r.bytes(32));
450
- }
451
- case exports.SC_ADDR.CONTRACT: return encodeStrKey(exports.STRKEY_VERSION.CONTRACT, r.bytes(32));
452
- case exports.SC_ADDR.MUXED_ACCOUNT: {
453
- // MuxedEd25519Account { uint64 id; uint256 ed25519 } -> M strkey payload = ed25519 ++ id (big endian)
454
- const id = r.bytes(8), key = r.bytes(32);
455
- return encodeStrKey(exports.STRKEY_VERSION.MUXED_ACCOUNT, Buffer.concat([key, id]));
456
- }
457
- case exports.SC_ADDR.CLAIMABLE_BALANCE: {
458
- // ClaimableBalanceID { u32 type (CLAIMABLE_BALANCE_ID_TYPE_V0 = 0); Hash v0 } -> B strkey payload = type byte ++ hash
459
- const idType = r.u32();
460
- return encodeStrKey(exports.STRKEY_VERSION.CLAIMABLE_BALANCE, Buffer.concat([Buffer.from([idType]), r.bytes(32)]));
461
- }
462
- case exports.SC_ADDR.LIQUIDITY_POOL: return encodeStrKey(exports.STRKEY_VERSION.LIQUIDITY_POOL, r.bytes(32));
463
- default: throw new Error(`Unsupported SCAddressType: ${type}`);
464
- }
465
- }
466
- /** Read one ScVal from the reader's current position. */
467
- function readScVal(r) {
468
- const type = r.u32();
469
- switch (type) {
470
- case exports.SC_VAL.BOOL: return r.u32() !== 0;
471
- case exports.SC_VAL.VOID: return null;
472
- case exports.SC_VAL.ERROR: {
473
- // SCError { SCErrorType type; union { u32 contractCode | SCErrorCode code } }
474
- const errType = r.u32();
475
- return { error: errType, code: r.u32() };
476
- }
477
- case exports.SC_VAL.U32: return r.u32();
478
- case exports.SC_VAL.I32: return r.i32();
479
- case exports.SC_VAL.U64:
480
- case exports.SC_VAL.TIMEPOINT:
481
- case exports.SC_VAL.DURATION: return r.u64();
482
- case exports.SC_VAL.I64: return r.i64();
483
- case exports.SC_VAL.U128: return r.uintN(2);
484
- case exports.SC_VAL.I128: return r.intN(2);
485
- case exports.SC_VAL.U256: return r.uintN(4);
486
- case exports.SC_VAL.I256: return r.intN(4);
487
- case exports.SC_VAL.BYTES: return '0x' + r.opaque().toString('hex');
488
- case exports.SC_VAL.STRING:
489
- case exports.SC_VAL.SYMBOL: return r.string();
490
- case exports.SC_VAL.VEC: {
491
- if (!r.u32())
492
- return null; // SCVec* absent
493
- const len = r.u32();
494
- const arr = [];
495
- for (let i = 0; i < len; i++)
496
- arr.push(readScVal(r));
497
- return arr;
498
- }
499
- case exports.SC_VAL.MAP: {
500
- if (!r.u32())
501
- return null; // SCMap* absent
502
- const len = r.u32();
503
- const map = {};
504
- for (let i = 0; i < len; i++) {
505
- const k = readScVal(r);
506
- map[mapKey(k)] = readScVal(r);
507
- }
508
- return map;
509
- }
510
- case exports.SC_VAL.ADDRESS: return readScAddress(r);
511
- case exports.SC_VAL.LEDGER_KEY_CONTRACT_INSTANCE: return null; // void body
512
- case exports.SC_VAL.LEDGER_KEY_NONCE: return r.i64();
513
- case exports.SC_VAL.CONTRACT_INSTANCE: {
514
- // SCContractInstance { ContractExecutable executable; SCMap* storage; }
515
- const execType = r.u32();
516
- const executable = execType === CONTRACT_EXECUTABLE_WASM
517
- ? { type: 'wasm', hash: r.bytes(32).toString('hex') }
518
- : { type: 'stellar_asset' };
519
- const storage = {};
520
- if (r.u32()) {
521
- const len = r.u32();
522
- for (let i = 0; i < len; i++) {
523
- const k = readScVal(r);
524
- storage[mapKey(k)] = readScVal(r);
525
- }
526
- }
527
- return { executable, storage };
528
- }
529
- default: throw new Error(`Unsupported ScVal type: ${type}`);
530
- }
531
- }
532
- /**
533
- * Decode an ScVal from raw XDR bytes or a base64 string.
534
- * u64/i64/u128/i128/u256/i256 -> bigint, bytes -> `0x` hex, addresses -> StrKey,
535
- * vec -> array, map -> object keyed by the (stringified) key, void -> null.
536
- */
537
- function parseScVal(input, offset = 0) {
538
- return readScVal(new XdrReader(input, offset));
539
- }
540
- function normalizeScArg(arg) {
541
- if (arg === null || arg === undefined)
542
- return { type: 'void' };
543
- if (Array.isArray(arg))
544
- return { type: 'vec', value: arg.map(normalizeScArg) };
545
- if (typeof arg === 'object') {
546
- if (!('type' in arg))
547
- throw new Error(`Untyped object argument, pass { type, value }: ${JSON.stringify(arg, jsonReplacer)}`);
548
- return arg;
549
- }
550
- if (typeof arg === 'string') {
551
- if (isAccountId(arg))
552
- return { type: 'account', value: arg };
553
- if (isContractId(arg))
554
- return { type: 'address', value: arg };
555
- throw new Error(`Ambiguous string argument "${arg}": tag it as { type: 'symbol' | 'string' | 'bytes' | 'i128' ..., value }`);
556
- }
557
- if (typeof arg === 'number')
558
- return { type: 'u32', value: arg };
559
- if (typeof arg === 'bigint')
560
- return { type: 'i128', value: arg };
561
- if (typeof arg === 'boolean')
562
- return { type: 'bool', value: arg };
563
- throw new Error(`Unsupported argument type: ${typeof arg}`);
564
- }
565
- /** ScVal::Symbol */
566
- function writeSymbol(w, name) {
567
- if (name.length > 32)
568
- throw new Error(`Symbol longer than 32 chars: ${name}`);
569
- return w.u32(exports.SC_VAL.SYMBOL).string(name);
570
- }
571
- /** Tagged integer ScVal (u32/i32/u64/i64/u128/i128/u256/i256, timepoint/duration) with range check. */
572
- function writeInt(w, tag, value, bits, signed) {
573
- const n = BigInt(value);
574
- const b = BigInt(bits);
575
- const min = signed ? -(BigInt(1) << (b - BigInt(1))) : BigInt(0);
576
- const max = signed ? (BigInt(1) << (b - BigInt(1))) - BigInt(1) : (BigInt(1) << b) - BigInt(1);
577
- if (n < min || n > max)
578
- throw new Error(`${signed ? 'i' : 'u'}${bits} out of range: ${value}`);
579
- w.u32(tag);
580
- if (bits === 32)
581
- return signed ? w.i32(Number(n)) : w.u32(Number(n));
582
- // two's complement, emitted as big-endian u64 limbs (Int128Parts / Int256Parts)
583
- const u = n < BigInt(0) ? n + (BigInt(1) << b) : n;
584
- for (let shift = bits - 64; shift >= 0; shift -= 64)
585
- w.u64((u >> BigInt(shift)) & MASK_64);
586
- return w;
587
- }
588
- /** SCAddress (no ScVal tag) for a `G...` / `C...` StrKey. */
589
- function writeScAddress(w, address) {
590
- const { version, payload } = decodeStrKey(address);
591
- if (version === exports.STRKEY_VERSION.CONTRACT)
592
- return w.u32(exports.SC_ADDR.CONTRACT).bytes(payload);
593
- if (version === exports.STRKEY_VERSION.ACCOUNT)
594
- return w.u32(exports.SC_ADDR.ACCOUNT).u32(KEY_TYPE_ED25519).bytes(payload);
595
- throw new Error(`Unsupported address for SCAddress: ${address}`);
596
- }
597
- /** ScVal::Address */
598
- function writeAddress(w, address) {
599
- w.u32(exports.SC_VAL.ADDRESS);
600
- return writeScAddress(w, address);
601
- }
602
- function toBytes(value) {
603
- if (Buffer.isBuffer(value))
604
- return value;
605
- if (value instanceof Uint8Array)
606
- return Buffer.from(value);
607
- if (typeof value === 'string')
608
- return Buffer.from(value.replace(/^0x/, ''), 'hex');
609
- throw new Error(`bytes expects Buffer/Uint8Array/hex string, got ${typeof value}`);
610
- }
611
- /** Append one ScVal for a (typed or untyped) argument. */
612
- function writeScVal(w, arg) {
613
- const { type, value } = normalizeScArg(arg);
614
- switch (type) {
615
- case 'void': return w.u32(exports.SC_VAL.VOID);
616
- case 'bool':
617
- if (typeof value !== 'boolean')
618
- throw new Error(`bool expects boolean, got ${typeof value}`);
619
- return w.u32(exports.SC_VAL.BOOL).u32(value ? 1 : 0);
620
- case 'u32': return writeInt(w, exports.SC_VAL.U32, value, 32, false);
621
- case 'i32': return writeInt(w, exports.SC_VAL.I32, value, 32, true);
622
- case 'u64': return writeInt(w, exports.SC_VAL.U64, value, 64, false);
623
- case 'i64': return writeInt(w, exports.SC_VAL.I64, value, 64, true);
624
- case 'timepoint': return writeInt(w, exports.SC_VAL.TIMEPOINT, value, 64, false);
625
- case 'duration': return writeInt(w, exports.SC_VAL.DURATION, value, 64, false);
626
- case 'u128': return writeInt(w, exports.SC_VAL.U128, value, 128, false);
627
- case 'i128': return writeInt(w, exports.SC_VAL.I128, value, 128, true);
628
- case 'u256': return writeInt(w, exports.SC_VAL.U256, value, 256, false);
629
- case 'i256': return writeInt(w, exports.SC_VAL.I256, value, 256, true);
630
- case 'symbol': return writeSymbol(w, String(value));
631
- case 'string': return w.u32(exports.SC_VAL.STRING).string(String(value));
632
- case 'bytes': return w.u32(exports.SC_VAL.BYTES).opaque(toBytes(value));
633
- case 'address':
634
- case 'account': return writeAddress(w, String(value));
635
- case 'vec': {
636
- const items = Array.isArray(value) ? value : [];
637
- w.u32(exports.SC_VAL.VEC).u32(1).u32(items.length);
638
- items.forEach(i => writeScVal(w, i));
639
- return w;
640
- }
641
- case 'map': {
642
- // #[contracttype] struct: SCMap keyed by field-name symbols, host requires ascending key order
643
- if (!value || typeof value !== 'object')
644
- throw new Error(`map expects an object, got ${typeof value}`);
645
- const entries = Object.entries(value).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
646
- w.u32(exports.SC_VAL.MAP).u32(1).u32(entries.length);
647
- for (const [key, entry] of entries) {
648
- writeSymbol(w, key);
649
- writeScVal(w, entry);
650
- }
651
- return w;
652
- }
653
- default: throw new Error(`Unsupported ScVal arg type: '${type}'`);
654
- }
655
- }
656
- /** Encode a single ScVal to bytes. */
657
- function encodeScVal(arg) {
658
- return writeScVal(new XdrWriter(), arg).toBuffer();
659
- }
660
- // ---------------------------------------------------------------------------
661
- // XDR structures used for reads
662
- // ---------------------------------------------------------------------------
663
- /** Classic `Asset` XDR (native / alphanum4 / alphanum12). */
664
- function writeAsset(w, asset) {
665
- const parsed = parseAsset(asset);
666
- if (isNativeAsset(parsed))
667
- return w.u32(0);
668
- const codeLen = parsed.code.length <= 4 ? 4 : 12;
669
- const code = Buffer.alloc(codeLen);
670
- code.write(parsed.code, 0, 'ascii');
671
- w.u32(codeLen === 4 ? 1 : 2).bytes(code);
672
- return w.u32(KEY_TYPE_ED25519).bytes(strKeyToBytes(parsed.issuer, exports.STRKEY_VERSION.ACCOUNT));
673
- }
674
- function getNetworkId(passphrase = exports.PUBLIC_NETWORK_PASSPHRASE) {
675
- return (0, crypto_1.createHash)('sha256').update(passphrase, 'utf8').digest();
676
- }
677
- /**
678
- * Stellar Asset Contract id of a classic asset (or `native`):
679
- * sha256(HashIDPreimage::ENVELOPE_TYPE_CONTRACT_ID { networkId, ContractIDPreimage::FROM_ASSET(asset) }).
680
- */
681
- function getSacContractId({ asset, networkPassphrase = exports.PUBLIC_NETWORK_PASSPHRASE }) {
682
- const w = new XdrWriter();
683
- w.u32(ENVELOPE_TYPE_CONTRACT_ID).bytes(getNetworkId(networkPassphrase)).u32(CONTRACT_ID_PREIMAGE_FROM_ASSET);
684
- writeAsset(w, asset);
685
- return encodeStrKey(exports.STRKEY_VERSION.CONTRACT, (0, crypto_1.createHash)('sha256').update(w.toBuffer()).digest());
686
- }
687
- /**
688
- * Unsigned TransactionV1Envelope with a single InvokeHostFunction(InvokeContract)
689
- * operation, as accepted by `simulateTransaction`. `source` defaults to the zero key.
690
- */
691
- function buildInvokeContractEnvelope({ contractId, method, args = [], source, fee = 100 }) {
692
- if (!isContractId(contractId))
693
- throw new Error(`Invalid contract id: ${contractId}`);
694
- const w = new XdrWriter();
695
- w.u32(ENVELOPE_TYPE_TX);
696
- w.u32(KEY_TYPE_ED25519); // MuxedAccount.KEY_TYPE_ED25519
697
- w.bytes(source ? strKeyToBytes(source, exports.STRKEY_VERSION.ACCOUNT) : Buffer.alloc(32)); // source account
698
- w.u32(fee);
699
- w.i64(0); // seqNum
700
- w.u32(0); // Preconditions.PRECOND_NONE
701
- w.u32(0); // Memo.MEMO_NONE
702
- w.u32(1); // operations<>
703
- w.u32(0); // op.sourceAccount absent
704
- w.u32(OP_INVOKE_HOST_FUNCTION);
705
- w.u32(HOST_FUNCTION_TYPE_INVOKE_CONTRACT);
706
- writeScAddress(w, contractId); // InvokeContractArgs.contractAddress
707
- w.string(method); // functionName (SCSymbol)
708
- w.u32(args.length);
709
- args.forEach(a => writeScVal(w, a));
710
- w.u32(0); // auth<>
711
- w.u32(0); // Transaction.ext v0
712
- w.u32(0); // signatures<>
713
- return w.toBuffer();
714
- }
715
- /** LedgerKey::ContractData { contract, key: LedgerKeyContractInstance, durability: PERSISTENT } */
716
- function buildContractInstanceLedgerKey({ contractId }) {
717
- const w = new XdrWriter();
718
- w.u32(LEDGER_ENTRY_CONTRACT_DATA);
719
- writeScAddress(w, contractId);
720
- w.u32(exports.SC_VAL.LEDGER_KEY_CONTRACT_INSTANCE);
721
- w.u32(CONTRACT_DATA_DURABILITY_PERSISTENT);
722
- return w.toBuffer();
723
- }
724
- function isNotFoundError(e) {
725
- var _a, _b;
726
- 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 : '');
727
- return /\[404\]|not_found|not found/i.test(message);
728
- }
729
- /** GET `path` on Horizon with query `params`; rotates configured endpoints and retries transient failures. */
730
- async function horizonGet({ path, params }) {
731
- const endpoints = getHorizonEndpoints();
732
- return (0, rpc_1.getLimiter)('STELLAR_HORIZON', HORIZON_CONCURRENCY)(() => (0, rpc_1.httpGet)(endpoints, { path, params, retries: Math.max(3, endpoints.length) }));
733
- }
734
- /** Raw Horizon account record (`/accounts/{id}`). Throws on unknown account. */
735
- async function getAccount({ address }) {
736
- if (!isAccountId(address))
737
- throw new Error(`Invalid Stellar account id: ${address}`);
738
- return horizonGet({ path: `/accounts/${address}` });
739
- }
740
- function toAccountBalance(b) {
741
- const res = {
742
- asset: 'native',
743
- assetType: b.asset_type,
744
- balance: b.balance,
745
- raw: toRaw(b.balance),
746
- };
747
- if (b.asset_type === 'liquidity_pool_shares') {
748
- res.asset = `pool:${b.liquidity_pool_id}`;
749
- res.liquidityPoolId = b.liquidity_pool_id;
750
- }
751
- else if (b.asset_type !== 'native') {
752
- res.asset = `${b.asset_code}-${b.asset_issuer}`;
753
- res.code = b.asset_code;
754
- res.issuer = b.asset_issuer;
755
- res.isAuthorized = b.is_authorized;
756
- }
757
- if (b.limit !== undefined)
758
- res.limit = b.limit;
759
- return res;
760
- }
761
- /**
762
- * All balances (native, trustlines, pool shares) of a classic account.
763
- * A non-existent (never funded) account resolves to `[]`.
764
- */
765
- async function getAccountBalances({ address }) {
766
- var _a;
767
- let account;
768
- try {
769
- account = await getAccount({ address });
770
- }
771
- catch (e) {
772
- if (!isNotFoundError(e))
773
- throw e;
774
- (0, debugLog_1.debugLog)(`[stellar] account ${address} not found on Horizon, treating as empty`);
775
- return [];
776
- }
777
- const balances = (_a = account === null || account === void 0 ? void 0 : account.balances) !== null && _a !== void 0 ? _a : [];
778
- return balances.map(toAccountBalance);
779
- }
780
- /** XLM balance of an account in stroops. */
781
- async function getNativeBalance({ address }) {
782
- var _a, _b;
783
- const balances = await getAccountBalances({ address });
784
- return (_b = (_a = balances.find(b => b.asset === 'native')) === null || _a === void 0 ? void 0 : _a.raw) !== null && _b !== void 0 ? _b : '0';
785
- }
786
- /**
787
- * Balance of `asset` held by `address`, in stroops (7 decimals for classic assets and SACs,
788
- * the token's own decimals for other Soroban tokens).
789
- * - `asset` is a `C...` contract id -> Soroban `balance(address)`
790
- * - `address` is a `C...` contract holding a classic asset -> `balance` on the asset's SAC
791
- * - otherwise the Horizon trustline balance (`0` when there is no trustline / account)
792
- */
793
- async function getTokenBalance({ asset, address }) {
794
- var _a, _b;
795
- if (typeof asset === 'string' && isContractId(asset))
796
- return getSorobanTokenBalance({ contractId: asset, address });
797
- const parsed = parseAsset(asset);
798
- if (isContractId(address))
799
- return getSorobanTokenBalance({ contractId: getSacContractId({ asset: parsed }), address });
800
- const key = assetToString(parsed);
801
- const balances = await getAccountBalances({ address });
802
- return (_b = (_a = balances.find(b => b.asset === key)) === null || _a === void 0 ? void 0 : _a.raw) !== null && _b !== void 0 ? _b : '0';
803
- }
804
- /** Horizon `/assets` record for a classic asset, or `undefined` when Horizon does not know it. */
805
- async function getAsset({ code, issuer, asset }) {
806
- var _a, _b;
807
- const parsed = asset !== undefined ? parseAsset(asset) : parseAsset({ code: code, issuer });
808
- if (isNativeAsset(parsed))
809
- throw new Error('getAsset: the native asset has no /assets record, use getAssetSupply');
810
- const res = await horizonGet({ path: '/assets', params: { asset_code: parsed.code, asset_issuer: parsed.issuer, limit: 1 } });
811
- return (_b = (_a = res === null || res === void 0 ? void 0 : res._embedded) === null || _a === void 0 ? void 0 : _a.records) === null || _b === void 0 ? void 0 : _b[0];
812
- }
813
- /**
814
- * Circulating supply of a classic asset in stroops: authorized trustline balances plus
815
- * amounts held by Soroban contracts (SAC), liquidity pools and claimable balances.
816
- * `native` returns the ledger's `total_coins`.
817
- */
818
- async function getAssetSupply({ asset, code, issuer }) {
819
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
820
- const parsed = asset !== undefined ? parseAsset(asset) : parseAsset({ code: code, issuer });
821
- const key = assetToString(parsed);
822
- if (isNativeAsset(parsed)) {
823
- const ledger = await getLatestLedger();
824
- const total = (_a = ledger.totalCoins) !== null && _a !== void 0 ? _a : '0';
825
- return {
826
- asset: key, supply: total, decimals: exports.STELLAR_DECIMALS, authorized: total, authorizedToMaintainLiabilities: '0', unauthorized: '0',
827
- contracts: '0', liquidityPools: '0', claimableBalances: '0', amount: total,
828
- };
829
- }
830
- const record = await getAsset({ asset: parsed });
831
- if (!record)
832
- throw new Error(`Asset ${key} not found on Horizon`);
833
- const authorized = toRaw((_c = (_b = record.balances) === null || _b === void 0 ? void 0 : _b.authorized) !== null && _c !== void 0 ? _c : '0');
834
- const contracts = toRaw((_d = record.contracts_amount) !== null && _d !== void 0 ? _d : '0');
835
- const liquidityPools = toRaw((_e = record.liquidity_pools_amount) !== null && _e !== void 0 ? _e : '0');
836
- const claimableBalances = toRaw((_f = record.claimable_balances_amount) !== null && _f !== void 0 ? _f : '0');
837
- const supply = (BigInt(authorized) + BigInt(contracts) + BigInt(liquidityPools) + BigInt(claimableBalances)).toString();
838
- return {
839
- asset: key,
840
- supply,
841
- decimals: exports.STELLAR_DECIMALS,
842
- authorized,
843
- authorizedToMaintainLiabilities: toRaw((_h = (_g = record.balances) === null || _g === void 0 ? void 0 : _g.authorized_to_maintain_liabilities) !== null && _h !== void 0 ? _h : '0'),
844
- unauthorized: toRaw((_k = (_j = record.balances) === null || _j === void 0 ? void 0 : _j.unauthorized) !== null && _k !== void 0 ? _k : '0'),
845
- contracts,
846
- liquidityPools,
847
- claimableBalances,
848
- amount: toRaw((_l = record.amount) !== null && _l !== void 0 ? _l : '0'),
849
- // Horizon >= 2.x dropped `num_accounts` in favour of `accounts.{authorized,...}`
850
- numAccounts: (_m = record.num_accounts) !== null && _m !== void 0 ? _m : (_o = record.accounts) === null || _o === void 0 ? void 0 : _o.authorized,
851
- numContracts: record.num_contracts,
852
- numClaimableBalances: record.num_claimable_balances,
853
- numLiquidityPools: record.num_liquidity_pools,
854
- };
855
- }
856
- function toLedgerInfo(record) {
857
- return {
858
- number: Number(record.sequence),
859
- timestamp: Math.floor(Date.parse(record.closed_at) / 1000),
860
- closedAt: record.closed_at,
861
- hash: record.hash,
862
- protocolVersion: record.protocol_version,
863
- totalCoins: record.total_coins !== undefined ? toRaw(record.total_coins) : undefined,
864
- successfulTransactionCount: record.successful_transaction_count,
865
- failedTransactionCount: record.failed_transaction_count,
866
- operationCount: record.operation_count,
867
- };
868
- }
869
- /** Horizon ledger by sequence number, or the latest closed ledger. */
870
- async function getLedger({ sequence = 'latest' } = {}) {
871
- var _a, _b;
872
- if (sequence === 'latest') {
873
- const res = await horizonGet({ path: '/ledgers', params: { order: 'desc', limit: 1 } });
874
- const record = (_b = (_a = res === null || res === void 0 ? void 0 : res._embedded) === null || _a === void 0 ? void 0 : _a.records) === null || _b === void 0 ? void 0 : _b[0];
875
- if (!record)
876
- throw new Error('Horizon returned no ledgers');
877
- return toLedgerInfo(record);
878
- }
879
- if (!Number.isInteger(sequence) || sequence < 1)
880
- throw new Error(`Invalid ledger sequence: ${sequence}`);
881
- return toLedgerInfo(await horizonGet({ path: `/ledgers/${sequence}` }));
882
- }
883
- async function getLatestLedger() {
884
- return getLedger({ sequence: 'latest' });
885
- }
886
- /** Ledgers close every ~5-6s; used only as a first guess in `getLedgerAtTimestamp`. */
887
- const AVG_LEDGER_CLOSE_SECONDS = 5.5;
888
- /**
889
- * Last ledger closed at or before `timestamp` (unix seconds, ms accepted). Horizon has no
890
- * time filter, so this is an interpolation search over `/ledgers/{seq}` (typically 4-8 requests).
891
- */
892
- async function getLedgerAtTimestamp({ timestamp }) {
893
- if (timestamp > 1e11)
894
- timestamp = Math.floor(timestamp / 1000);
895
- const latest = await getLatestLedger();
896
- if (timestamp >= latest.timestamp)
897
- return latest;
898
- // ledger 1 is the genesis ledger (closed_at 1970), so it is a valid lower bound for any timestamp
899
- let lo = { number: 1, timestamp: 0, closedAt: '1970-01-01T00:00:00Z', hash: '' };
900
- let hi = latest;
901
- for (let iteration = 0; hi.number - lo.number > 1; iteration++) {
902
- if (iteration > 64)
903
- throw new Error(`getLedgerAtTimestamp: did not converge for ${timestamp}`);
904
- let guess;
905
- if (iteration % 2 === 1) {
906
- guess = lo.number + Math.floor((hi.number - lo.number) / 2); // bisection step guarantees progress
907
- }
908
- else if (lo.number === 1) {
909
- guess = hi.number - Math.ceil((hi.timestamp - timestamp) / AVG_LEDGER_CLOSE_SECONDS);
910
- }
911
- else {
912
- const span = hi.timestamp - lo.timestamp;
913
- guess = span > 0 ? lo.number + Math.floor((timestamp - lo.timestamp) * (hi.number - lo.number) / span) : lo.number + 1;
914
- }
915
- guess = Math.min(Math.max(guess, lo.number + 1), hi.number - 1);
916
- const ledger = await getLedger({ sequence: guess });
917
- if (ledger.timestamp <= timestamp)
918
- lo = ledger;
919
- else
920
- hi = ledger;
921
- }
922
- if (lo.number === 1)
923
- return getLedger({ sequence: 1 });
924
- return lo;
925
- }
926
- // ---------------------------------------------------------------------------
927
- // Soroban RPC
928
- // ---------------------------------------------------------------------------
929
- /** Raw Soroban JSON-RPC call; rotates configured endpoints and retries transport / rate-limit errors. */
930
- async function sorobanRpc(method, params = {}) {
931
- const endpoints = getSorobanEndpoints();
932
- return (0, rpc_1.getLimiter)('STELLAR_SOROBAN', SOROBAN_CONCURRENCY)(() => (0, rpc_1.jsonRpc)(method, params, { endpoints, chain: 'stellar' }));
933
- }
934
- async function getLatestSorobanLedger() {
935
- const res = await sorobanRpc('getLatestLedger');
936
- return { number: Number(res.sequence), hash: res.id, protocolVersion: Number(res.protocolVersion) };
937
- }
938
- /**
939
- * `simulateTransaction` on a base64 (or raw) TransactionEnvelope. Returns the RPC result;
940
- * throws when the simulation itself failed (`result.error`).
941
- */
942
- async function simulateTransaction({ transaction, resourceConfig }) {
943
- const params = { transaction: typeof transaction === 'string' ? transaction : transaction.toString('base64') };
944
- if (resourceConfig)
945
- params.resourceConfig = resourceConfig;
946
- const res = await sorobanRpc('simulateTransaction', params);
947
- if (res === null || res === void 0 ? void 0 : res.error)
948
- throw new Error(`Soroban simulation failed: ${String(res.error).slice(0, 500)}`);
949
- return res;
950
- }
951
- /**
952
- * Read-only contract call via `simulateTransaction`. Returns the decoded ScVal result
953
- * (see `parseScVal` for the mapping). See `ScArgInput` for how untyped args are encoded.
954
- */
955
- async function callSoroban({ contractId, method, args = [], source }) {
956
- var _a, _b;
957
- const envelope = buildInvokeContractEnvelope({ contractId, method, args, source });
958
- const res = await simulateTransaction({ transaction: envelope });
959
- const xdr = (_b = (_a = res === null || res === void 0 ? void 0 : res.results) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.xdr;
960
- if (!xdr)
961
- throw new Error(`No result from ${contractId}.${method}()`);
962
- return parseScVal(xdr);
963
- }
964
- /** `getLedgerEntries` for base64 (or raw) LedgerKey XDRs. Missing entries are simply absent from `entries`. */
965
- async function getLedgerEntries({ keys }) {
966
- var _a, _b;
967
- if (!keys.length)
968
- return { entries: [], latestLedger: 0 };
969
- const encoded = keys.map(k => typeof k === 'string' ? k : k.toString('base64'));
970
- const res = await sorobanRpc('getLedgerEntries', { keys: encoded });
971
- return { entries: (_a = res === null || res === void 0 ? void 0 : res.entries) !== null && _a !== void 0 ? _a : [], latestLedger: Number((_b = res === null || res === void 0 ? void 0 : res.latestLedger) !== null && _b !== void 0 ? _b : 0) };
972
- }
973
- /** Decoded SCContractInstance (executable + instance storage) of a contract. */
974
- async function getContractInstance({ contractId }) {
975
- var _a;
976
- const key = buildContractInstanceLedgerKey({ contractId });
977
- const { entries } = await getLedgerEntries({ keys: [key] });
978
- const xdr = (_a = entries[0]) === null || _a === void 0 ? void 0 : _a.xdr;
979
- if (!xdr)
980
- throw new Error(`No instance storage ledger entry for ${contractId}`);
981
- // LedgerEntryData(CONTRACT_DATA) { ext, SCAddress contract, SCVal key, durability, SCVal val }
982
- const r = new XdrReader(xdr);
983
- const type = r.u32();
984
- if (type !== LEDGER_ENTRY_CONTRACT_DATA)
985
- throw new Error(`Unexpected LedgerEntryType ${type} for ${contractId}`);
986
- r.u32(); // ExtensionPoint
987
- readScAddress(r); // contract
988
- readScVal(r); // key (LedgerKeyContractInstance, void)
989
- r.u32(); // durability
990
- const instance = readScVal(r);
991
- if (!instance || typeof instance !== 'object' || !('storage' in instance))
992
- throw new Error(`Unexpected instance entry for ${contractId}`);
993
- return instance;
994
- }
995
- /**
996
- * Instance storage of a contract keyed by storage key (enum keys collapse to the variant
997
- * name). Reads data not reachable through contract functions.
998
- */
999
- async function getContractInstanceStorage({ contractId }) {
1000
- return (await getContractInstance({ contractId })).storage;
1001
- }
1002
- // ---------------------------------------------------------------------------
1003
- // Soroban token interface (SEP-41 / SAC)
1004
- // ---------------------------------------------------------------------------
1005
- const tokenMetadataCache = {};
1006
- function cached(key, fn) {
1007
- if (!tokenMetadataCache[key]) {
1008
- tokenMetadataCache[key] = fn().catch(e => {
1009
- delete tokenMetadataCache[key];
1010
- throw e;
1011
- });
1012
- }
1013
- return tokenMetadataCache[key];
1014
- }
1015
- /** `balance(address)` as a decimal string in the token's smallest unit. */
1016
- async function getSorobanTokenBalance({ contractId, address }) {
1017
- const value = await callSoroban({ contractId, method: 'balance', args: [address] });
1018
- return String(value);
1019
- }
1020
- async function getSorobanTokenDecimals({ contractId }) {
1021
- return cached(`decimals:${contractId}`, async () => Number(await callSoroban({ contractId, method: 'decimals' })));
1022
- }
1023
- async function getSorobanTokenSymbol({ contractId }) {
1024
- return cached(`symbol:${contractId}`, async () => String(await callSoroban({ contractId, method: 'symbol' })));
1025
- }
1026
- /** `name()`; a SAC returns `CODE:ISSUER` (or `native`), which is how `getSacClassicAsset` resolves it. */
1027
- async function getSorobanTokenName({ contractId }) {
1028
- return cached(`name:${contractId}`, async () => String(await callSoroban({ contractId, method: 'name' })));
1029
- }
1030
- function isMissingFunctionError(e) {
1031
- var _a, _b;
1032
- 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 : '');
1033
- return /MissingValue|InvalidAction|InvalidInput|unknown function|not found|does not exist|no such function|MissingFunction|function.*not.*export/i.test(message);
1034
- }
1035
- /**
1036
- * `total_supply()` of a Soroban token as a decimal string, or `undefined` when the contract
1037
- * does not implement it (SACs do not; use `getAssetSupply` on the classic asset instead).
1038
- */
1039
- async function getSorobanTokenTotalSupply({ contractId }) {
1040
- try {
1041
- return String(await callSoroban({ contractId, method: 'total_supply' }));
1042
- }
1043
- catch (e) {
1044
- if (!isMissingFunctionError(e))
1045
- throw e;
1046
- (0, debugLog_1.debugLog)(`[stellar] ${contractId} has no total_supply(): ${String(e === null || e === void 0 ? void 0 : e.message).slice(0, 160)}`);
1047
- return undefined;
1048
- }
1049
- }
1050
- /** Classic asset wrapped by a Stellar Asset Contract, or `undefined` for a non-SAC token. */
1051
- async function getSacClassicAsset({ contractId }) {
1052
- const name = await getSorobanTokenName({ contractId });
1053
- let asset;
1054
- try {
1055
- asset = parseAsset(name);
1056
- }
1057
- catch {
1058
- return undefined;
1059
- }
1060
- // the name is only trusted when the derived SAC id matches (a custom token could name itself "USDC:G...")
1061
- return getSacContractId({ asset }) === contractId ? asset : undefined;
1062
- }
1063
- /**
1064
- * Total supply of any Stellar token id used by DefiLlama: `native`, `CODE-ISSUER`, or a
1065
- * `C...` contract (SAC -> Horizon supply of the wrapped asset, other tokens -> `total_supply()`).
1066
- * Resolves to `undefined` when a Soroban token exposes no `total_supply`.
1067
- */
1068
- async function getTokenSupply({ token }) {
1069
- if (typeof token === 'string' && isContractId(token)) {
1070
- const classic = await getSacClassicAsset({ contractId: token });
1071
- if (classic) {
1072
- const { supply, decimals } = await getAssetSupply({ asset: classic });
1073
- return { supply, decimals };
1074
- }
1075
- const supply = await getSorobanTokenTotalSupply({ contractId: token });
1076
- if (supply === undefined)
1077
- return undefined;
1078
- return { supply, decimals: await getSorobanTokenDecimals({ contractId: token }) };
1079
- }
1080
- const { supply, decimals } = await getAssetSupply({ asset: token });
1081
- return { supply, decimals };
1082
- }