@defillama/sdk 5.0.238 → 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.
- package/package.json +1 -1
- package/build/Balances.d.ts +0 -139
- package/build/Balances.js +0 -363
- package/build/ChainApi.d.ts +0 -142
- package/build/ChainApi.js +0 -310
- package/build/abi/abi2.d.ts +0 -5
- package/build/abi/abi2.js +0 -215
- package/build/abi/cachedABIs.d.ts +0 -4
- package/build/abi/cachedABIs.js +0 -8
- package/build/abi/convertResults.d.ts +0 -5
- package/build/abi/convertResults.js +0 -60
- package/build/abi/index.d.ts +0 -31
- package/build/abi/index.js +0 -327
- package/build/abi/multicall.d.ts +0 -23
- package/build/abi/multicall.js +0 -382
- package/build/abi/multicall3.d.ts +0 -7
- package/build/abi/multicall3.js +0 -397
- package/build/abi/rpcCall.d.ts +0 -4
- package/build/abi/rpcCall.js +0 -62
- package/build/abi/tron.d.ts +0 -33
- package/build/abi/tron.js +0 -116
- package/build/api.d.ts +0 -10
- package/build/api.js +0 -45
- package/build/api2.d.ts +0 -5
- package/build/api2.js +0 -41
- package/build/chains/algorand.d.ts +0 -277
- package/build/chains/algorand.js +0 -618
- package/build/chains/aptos.d.ts +0 -230
- package/build/chains/aptos.js +0 -612
- package/build/chains/cardano.d.ts +0 -242
- package/build/chains/cardano.js +0 -407
- package/build/chains/cosmos.d.ts +0 -252
- package/build/chains/cosmos.js +0 -618
- package/build/chains/icp.d.ts +0 -235
- package/build/chains/icp.js +0 -1040
- package/build/chains/index.d.ts +0 -23
- package/build/chains/index.js +0 -59
- package/build/chains/near.d.ts +0 -192
- package/build/chains/near.js +0 -446
- package/build/chains/rpc.d.ts +0 -125
- package/build/chains/rpc.js +0 -326
- package/build/chains/starknet.d.ts +0 -205
- package/build/chains/starknet.js +0 -884
- package/build/chains/stellar.d.ts +0 -410
- package/build/chains/stellar.js +0 -1082
- package/build/chains/substrate.d.ts +0 -333
- package/build/chains/substrate.js +0 -1042
- package/build/chains/sui.d.ts +0 -365
- package/build/chains/sui.js +0 -1135
- package/build/chains/svm.d.ts +0 -340
- package/build/chains/svm.js +0 -760
- package/build/chains/tezos.d.ts +0 -225
- package/build/chains/tezos.js +0 -412
- package/build/chains/ton.d.ts +0 -353
- package/build/chains/ton.js +0 -788
- package/build/chains/tron.d.ts +0 -45
- package/build/chains/tron.js +0 -110
- package/build/chains/utxo.d.ts +0 -202
- package/build/chains/utxo.js +0 -592
- package/build/chains/xrpl.d.ts +0 -179
- package/build/chains/xrpl.js +0 -467
- package/build/computeTVL/blocks.d.ts +0 -1
- package/build/computeTVL/blocks.js +0 -12
- package/build/computeTVL/humanizeNumber.d.ts +0 -1
- package/build/computeTVL/humanizeNumber.js +0 -19
- package/build/erc20/index.d.ts +0 -31
- package/build/erc20/index.js +0 -56
- package/build/eth/index.d.ts +0 -22
- package/build/eth/index.js +0 -118
- package/build/general.d.ts +0 -5
- package/build/general.js +0 -20
- package/build/generalUtil.d.ts +0 -8
- package/build/generalUtil.js +0 -73
- package/build/index.d.ts +0 -32
- package/build/index.js +0 -74
- package/build/providers.json +0 -1
- package/build/types.d.ts +0 -76
- package/build/types.js +0 -2
- package/build/util/LlamaProvider.d.ts +0 -46
- package/build/util/LlamaProvider.js +0 -367
- package/build/util/blocks.d.ts +0 -36
- package/build/util/blocks.js +0 -500
- package/build/util/cache.d.ts +0 -45
- package/build/util/cache.js +0 -309
- package/build/util/chainUtils/data.json +0 -1425
- package/build/util/chainUtils/index.d.ts +0 -11
- package/build/util/chainUtils/index.js +0 -136
- package/build/util/coins.d.ts +0 -19
- package/build/util/coins.js +0 -124
- package/build/util/common.d.ts +0 -34
- package/build/util/common.js +0 -376
- package/build/util/computeTVL.d.ts +0 -19
- package/build/util/computeTVL.js +0 -102
- package/build/util/cosmos.d.ts +0 -1
- package/build/util/cosmos.js +0 -8
- package/build/util/debugLog.d.ts +0 -4
- package/build/util/debugLog.js +0 -18
- package/build/util/discord.d.ts +0 -1
- package/build/util/discord.js +0 -33
- package/build/util/elastic.d.ts +0 -43
- package/build/util/elastic.js +0 -113
- package/build/util/env.d.ts +0 -20
- package/build/util/env.js +0 -175
- package/build/util/graph.d.ts +0 -8
- package/build/util/graph.js +0 -50
- package/build/util/index.d.ts +0 -32
- package/build/util/index.js +0 -227
- package/build/util/indexer.compatibility.d.ts +0 -6
- package/build/util/indexer.compatibility.js +0 -64
- package/build/util/indexer.d.ts +0 -92
- package/build/util/indexer.js +0 -850
- package/build/util/indexerSql.d.ts +0 -9
- package/build/util/indexerSql.js +0 -102
- package/build/util/internal-cache.d.ts +0 -11
- package/build/util/internal-cache.js +0 -77
- package/build/util/logs.d.ts +0 -58
- package/build/util/logs.decode.shared.d.ts +0 -8
- package/build/util/logs.decode.shared.js +0 -289
- package/build/util/logs.js +0 -432
- package/build/util/promisePool.d.ts +0 -8
- package/build/util/promisePool.js +0 -31
- package/build/util/r2.d.ts +0 -4
- package/build/util/r2.js +0 -52
- package/build/util/removeRedundantRPCs.d.ts +0 -1
- package/build/util/removeRedundantRPCs.js +0 -49
- package/build/util/transactions.d.ts +0 -35
- package/build/util/transactions.js +0 -22
- package/build/util/updateChainLabels.d.ts +0 -1
- package/build/util/updateChainLabels.js +0 -5
- package/build/util/updateProviderList.d.ts +0 -1
- package/build/util/updateProviderList.js +0 -275
|
@@ -1,1042 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bifrost = exports.getLatestBlock = exports.getRuntimeVersion = exports.getFinalizedHead = exports.storagePrefix = exports.DEFAULT_HASHER = exports.hashers = exports.identity = exports.blake2_128Concat = exports.twox64Concat = exports.ScaleReader = exports.encodeU128 = exports.encodeU64 = exports.encodeU32 = exports.encodeU16 = exports.encodeU8 = exports.blake2_512 = exports.blake2_256 = exports.blake2_128 = exports.twox256 = exports.twox128 = exports.twox64 = exports.DEFAULT_ENDPOINTS = void 0;
|
|
4
|
-
exports.toBuf = toBuf;
|
|
5
|
-
exports.hex = hex;
|
|
6
|
-
exports.u64le = u64le;
|
|
7
|
-
exports.xxhash64 = xxhash64;
|
|
8
|
-
exports.blake2b = blake2b;
|
|
9
|
-
exports.base58Decode = base58Decode;
|
|
10
|
-
exports.base58Encode = base58Encode;
|
|
11
|
-
exports.ss58DecodeFull = ss58DecodeFull;
|
|
12
|
-
exports.ss58Decode = ss58Decode;
|
|
13
|
-
exports.ss58Encode = ss58Encode;
|
|
14
|
-
exports.encodeUint = encodeUint;
|
|
15
|
-
exports.encodeCompact = encodeCompact;
|
|
16
|
-
exports.decodeUint = decodeUint;
|
|
17
|
-
exports.decodeCompact = decodeCompact;
|
|
18
|
-
exports.getHasher = getHasher;
|
|
19
|
-
exports.storageKey = storageKey;
|
|
20
|
-
exports.stripHasher = stripHasher;
|
|
21
|
-
exports.getEndpoints = getEndpoints;
|
|
22
|
-
exports.rpc = rpc;
|
|
23
|
-
exports.getBlockHash = getBlockHash;
|
|
24
|
-
exports.getHeader = getHeader;
|
|
25
|
-
exports.decodeTimestampInherent = decodeTimestampInherent;
|
|
26
|
-
exports.getTimestampAt = getTimestampAt;
|
|
27
|
-
exports.getBlock = getBlock;
|
|
28
|
-
exports.getBlockAtTimestamp = getBlockAtTimestamp;
|
|
29
|
-
exports.getStorageRaw = getStorageRaw;
|
|
30
|
-
exports.getStorage = getStorage;
|
|
31
|
-
exports.getStorageBatch = getStorageBatch;
|
|
32
|
-
exports.getKeysPaged = getKeysPaged;
|
|
33
|
-
exports.getAllKeys = getAllKeys;
|
|
34
|
-
exports.getStorageEntries = getStorageEntries;
|
|
35
|
-
exports.stateCall = stateCall;
|
|
36
|
-
exports.decodeAccountInfo = decodeAccountInfo;
|
|
37
|
-
exports.getSystemAccount = getSystemAccount;
|
|
38
|
-
exports.getFreeBalance = getFreeBalance;
|
|
39
|
-
exports.getTotalIssuance = getTotalIssuance;
|
|
40
|
-
exports.decodeOrmlAccountData = decodeOrmlAccountData;
|
|
41
|
-
exports.getTokensAccount = getTokensAccount;
|
|
42
|
-
/**
|
|
43
|
-
* Substrate / Polkadot JSON-RPC client with a dependency free SCALE + storage-key codec.
|
|
44
|
-
*
|
|
45
|
-
* Replaces (and unifies) the ad-hoc substrate helpers spread across the llama repos:
|
|
46
|
-
* - DefiLlama-Adapters `projects/helper/chain/substrate.js` (endpoints, rpc, xxhash64/twox, blake2, ss58,
|
|
47
|
-
* SCALE encode/decode, ScaleReader, storage keys, getStorage/Batch/Entries, stateCall,
|
|
48
|
-
* System.Account / orml Tokens.Accounts decoding)
|
|
49
|
-
* - DefiLlama-Adapters `projects/helper/chain/bifrostCurrency.js` (bifrost CurrencyId codec -> `bifrost`)
|
|
50
|
-
* - DefiLlama-Adapters `projects/helper/chain/polkadot.js` (System.Account key + AccountInfo decoding)
|
|
51
|
-
* - DefiLlama-Adapters `projects/helper/chain/bittensor.js` (SubtensorModule prefixes, free balance, u64 balances)
|
|
52
|
-
* - server/coins `src/adapters/other/bittensorSubnets.ts` (state_getKeysPaged pagination, twox128 prefixes)
|
|
53
|
-
*
|
|
54
|
-
* No `@polkadot/*`, `blakejs` or `bs58`: blake2b, xxhash64 and base58 are implemented here.
|
|
55
|
-
* Only plain storage items and (double) maps whose values are made of fixed width integers,
|
|
56
|
-
* options and compacts are decoded; anything that needs chain metadata is decoded by the caller
|
|
57
|
-
* with the SCALE helpers (`ScaleReader`, `decodeUint`, `decodeCompact`).
|
|
58
|
-
*
|
|
59
|
-
* Endpoints: `<CHAIN>_SUBSTRATE_RPC` env first (comma separated), then `DEFAULT_ENDPOINTS`, then
|
|
60
|
-
* `<CHAIN>_RPC` only when the chain is not an EVM chain (astar/acala/moonbeam use `<CHAIN>_RPC` for
|
|
61
|
-
* their EVM RPC). A literal `https://` url can be passed as `chain`.
|
|
62
|
-
*
|
|
63
|
-
* Usage: `sdk.chains.substrate.getSystemAccount({ chain: 'polkadot', address })`
|
|
64
|
-
*/
|
|
65
|
-
const debugLog_1 = require("../util/debugLog");
|
|
66
|
-
const env_1 = require("../util/env");
|
|
67
|
-
const LlamaProvider_1 = require("../util/LlamaProvider");
|
|
68
|
-
const rpc_1 = require("./rpc");
|
|
69
|
-
exports.DEFAULT_ENDPOINTS = {
|
|
70
|
-
polkadot: 'https://rpc.polkadot.io,https://polkadot-rpc.publicnode.com,https://dot-rpc.stakeworld.io',
|
|
71
|
-
polkadot_assethub: 'https://polkadot-asset-hub-rpc.polkadot.io,https://statemint.api.onfinality.io/public',
|
|
72
|
-
kusama: 'https://kusama-rpc.polkadot.io,https://kusama-rpc.publicnode.com',
|
|
73
|
-
acala: 'https://acala-rpc.aca-api.network',
|
|
74
|
-
karura: 'https://karura-rpc.aca-api.network',
|
|
75
|
-
bifrost: 'https://eu.bifrost-polkadot-rpc.liebi.com',
|
|
76
|
-
bifrost_kusama: 'https://bifrost-rpc.liebi.com,https://api-bifrost-kusama.n.dwellir.com/b523cf66-7a5a-4fe8-8d67-f604fd0492c2',
|
|
77
|
-
bittensor: 'https://entrypoint-finney.opentensor.ai',
|
|
78
|
-
polymesh: 'https://mainnet-rpc.polymesh.network',
|
|
79
|
-
astar: 'https://astar.api.onfinality.io/public,https://rpc.astar.network,https://astar-rpc.dwellir.com',
|
|
80
|
-
sora: 'https://mof2.sora.org',
|
|
81
|
-
hydration: 'https://rpc.hydradx.cloud',
|
|
82
|
-
};
|
|
83
|
-
const DEFAULT_CONCURRENCY = 10;
|
|
84
|
-
const DEFAULT_PAGE_SIZE = 1000;
|
|
85
|
-
const DEFAULT_BATCH_CHUNK = 1000;
|
|
86
|
-
/** assumed block time (seconds) used to bracket the binary search in getBlockAtTimestamp */
|
|
87
|
-
const BLOCK_TIME = 6;
|
|
88
|
-
// ---------------------------------------------------------------------------
|
|
89
|
-
// bytes
|
|
90
|
-
// ---------------------------------------------------------------------------
|
|
91
|
-
/** `Buffer` from a `0x` hex string, utf8 string, byte array or Buffer/Uint8Array */
|
|
92
|
-
function toBuf(value) {
|
|
93
|
-
if (value === undefined || value === null)
|
|
94
|
-
return Buffer.alloc(0);
|
|
95
|
-
if (Buffer.isBuffer(value))
|
|
96
|
-
return value;
|
|
97
|
-
if (value instanceof Uint8Array)
|
|
98
|
-
return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
99
|
-
if (Array.isArray(value))
|
|
100
|
-
return Buffer.from(value);
|
|
101
|
-
if (typeof value === 'string') {
|
|
102
|
-
if (value.startsWith('0x') || value.startsWith('0X'))
|
|
103
|
-
return Buffer.from(value.slice(2), 'hex');
|
|
104
|
-
return Buffer.from(value, 'utf8');
|
|
105
|
-
}
|
|
106
|
-
throw new Error(`substrate.toBuf: unsupported value ${typeof value}`);
|
|
107
|
-
}
|
|
108
|
-
/** `0x` prefixed lowercase hex */
|
|
109
|
-
function hex(value) {
|
|
110
|
-
return '0x' + toBuf(value).toString('hex');
|
|
111
|
-
}
|
|
112
|
-
/** little endian u64 (8 bytes) */
|
|
113
|
-
function u64le(n) {
|
|
114
|
-
const b = Buffer.alloc(8);
|
|
115
|
-
b.writeBigUInt64LE(BigInt(n));
|
|
116
|
-
return b;
|
|
117
|
-
}
|
|
118
|
-
function concat(parts) {
|
|
119
|
-
return Buffer.concat(parts.map(p => Buffer.isBuffer(p) ? p : Buffer.from(p)));
|
|
120
|
-
}
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
|
-
// xxhash64 / twox
|
|
123
|
-
// ---------------------------------------------------------------------------
|
|
124
|
-
const P1 = BigInt('11400714785074694791');
|
|
125
|
-
const P2 = BigInt('14029467366897019727');
|
|
126
|
-
const P3 = BigInt('1609587929392839161');
|
|
127
|
-
const P4 = BigInt('9650029242287828579');
|
|
128
|
-
const P5 = BigInt('2870177450012600261');
|
|
129
|
-
const M64 = (BigInt(1) << BigInt(64)) - BigInt(1);
|
|
130
|
-
const B0 = BigInt(0);
|
|
131
|
-
const B64 = BigInt(64);
|
|
132
|
-
const rotl64 = (x, r) => ((x << BigInt(r)) | (x >> (B64 - BigInt(r)))) & M64;
|
|
133
|
-
const xxRound = (acc, input) => (rotl64((acc + input * P2) & M64, 31) * P1) & M64;
|
|
134
|
-
const xxMerge = (acc, val) => ((acc ^ xxRound(B0, val)) * P1 + P4) & M64;
|
|
135
|
-
/** xxHash64 of `data` with `seed` -> unsigned 64 bit bigint */
|
|
136
|
-
function xxhash64(data, seed = 0) {
|
|
137
|
-
const buf = toBuf(data);
|
|
138
|
-
const s = BigInt(seed) & M64;
|
|
139
|
-
const len = buf.length;
|
|
140
|
-
let p = 0;
|
|
141
|
-
let h;
|
|
142
|
-
if (len >= 32) {
|
|
143
|
-
let v1 = (s + P1 + P2) & M64;
|
|
144
|
-
let v2 = (s + P2) & M64;
|
|
145
|
-
let v3 = s;
|
|
146
|
-
let v4 = (s - P1) & M64;
|
|
147
|
-
for (; p + 32 <= len; p += 32) {
|
|
148
|
-
v1 = xxRound(v1, buf.readBigUInt64LE(p));
|
|
149
|
-
v2 = xxRound(v2, buf.readBigUInt64LE(p + 8));
|
|
150
|
-
v3 = xxRound(v3, buf.readBigUInt64LE(p + 16));
|
|
151
|
-
v4 = xxRound(v4, buf.readBigUInt64LE(p + 24));
|
|
152
|
-
}
|
|
153
|
-
h = (rotl64(v1, 1) + rotl64(v2, 7) + rotl64(v3, 12) + rotl64(v4, 18)) & M64;
|
|
154
|
-
h = xxMerge(h, v1);
|
|
155
|
-
h = xxMerge(h, v2);
|
|
156
|
-
h = xxMerge(h, v3);
|
|
157
|
-
h = xxMerge(h, v4);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
h = (s + P5) & M64;
|
|
161
|
-
}
|
|
162
|
-
h = (h + BigInt(len)) & M64;
|
|
163
|
-
for (; p + 8 <= len; p += 8) {
|
|
164
|
-
h ^= xxRound(B0, buf.readBigUInt64LE(p));
|
|
165
|
-
h = (rotl64(h, 27) * P1 + P4) & M64;
|
|
166
|
-
}
|
|
167
|
-
if (p + 4 <= len) {
|
|
168
|
-
h ^= (BigInt(buf.readUInt32LE(p)) * P1) & M64;
|
|
169
|
-
h = (rotl64(h, 23) * P2 + P3) & M64;
|
|
170
|
-
p += 4;
|
|
171
|
-
}
|
|
172
|
-
for (; p < len; p++) {
|
|
173
|
-
h ^= (BigInt(buf[p]) * P5) & M64;
|
|
174
|
-
h = (rotl64(h, 11) * P1) & M64;
|
|
175
|
-
}
|
|
176
|
-
h ^= h >> BigInt(33);
|
|
177
|
-
h = (h * P2) & M64;
|
|
178
|
-
h ^= h >> BigInt(29);
|
|
179
|
-
h = (h * P3) & M64;
|
|
180
|
-
h ^= h >> BigInt(32);
|
|
181
|
-
return h;
|
|
182
|
-
}
|
|
183
|
-
/** twox64: xxhash64(data, 0) as 8 LE bytes */
|
|
184
|
-
const twox64 = (data) => u64le(xxhash64(data, 0));
|
|
185
|
-
exports.twox64 = twox64;
|
|
186
|
-
/** twox128: xxhash64(data, 0) ++ xxhash64(data, 1) */
|
|
187
|
-
const twox128 = (data) => concat([u64le(xxhash64(data, 0)), u64le(xxhash64(data, 1))]);
|
|
188
|
-
exports.twox128 = twox128;
|
|
189
|
-
/** twox256: xxhash64 with seeds 0..3 */
|
|
190
|
-
const twox256 = (data) => concat([0, 1, 2, 3].map(seed => u64le(xxhash64(data, seed))));
|
|
191
|
-
exports.twox256 = twox256;
|
|
192
|
-
// ---------------------------------------------------------------------------
|
|
193
|
-
// blake2b (RFC 7693, keyless, 1..64 byte digest) on 32 bit word pairs
|
|
194
|
-
// ---------------------------------------------------------------------------
|
|
195
|
-
const BLAKE2B_IV32 = new Uint32Array([
|
|
196
|
-
0xf3bcc908, 0x6a09e667, 0x84caa73b, 0xbb67ae85,
|
|
197
|
-
0xfe94f82b, 0x3c6ef372, 0x5f1d36f1, 0xa54ff53a,
|
|
198
|
-
0xade682d1, 0x510e527f, 0x2b3e6c1f, 0x9b05688c,
|
|
199
|
-
0xfb41bd6b, 0x1f83d9ab, 0x137e2179, 0x5be0cd19,
|
|
200
|
-
]);
|
|
201
|
-
const SIGMA8 = [
|
|
202
|
-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
203
|
-
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
|
|
204
|
-
11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4,
|
|
205
|
-
7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8,
|
|
206
|
-
9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13,
|
|
207
|
-
2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9,
|
|
208
|
-
12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11,
|
|
209
|
-
13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10,
|
|
210
|
-
6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5,
|
|
211
|
-
10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0,
|
|
212
|
-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
213
|
-
14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3,
|
|
214
|
-
];
|
|
215
|
-
// message word index * 2 (each 64 bit word is a pair of 32 bit words)
|
|
216
|
-
const SIGMA82 = new Uint8Array(SIGMA8.map(x => x * 2));
|
|
217
|
-
// working vector (32 x u32 = 16 x u64) and message block (32 x u32)
|
|
218
|
-
const bv = new Uint32Array(32);
|
|
219
|
-
const bm = new Uint32Array(32);
|
|
220
|
-
// v[a] += v[b] (64 bit, little word first)
|
|
221
|
-
function add64AA(v, a, b) {
|
|
222
|
-
const o0 = v[a] + v[b];
|
|
223
|
-
let o1 = v[a + 1] + v[b + 1];
|
|
224
|
-
if (o0 >= 0x100000000)
|
|
225
|
-
o1++;
|
|
226
|
-
v[a] = o0;
|
|
227
|
-
v[a + 1] = o1;
|
|
228
|
-
}
|
|
229
|
-
// v[a] += (b0, b1) where b0/b1 may be signed 32 bit
|
|
230
|
-
function add64AC(v, a, b0, b1) {
|
|
231
|
-
let o0 = v[a] + b0;
|
|
232
|
-
if (b0 < 0)
|
|
233
|
-
o0 += 0x100000000;
|
|
234
|
-
let o1 = v[a + 1] + b1;
|
|
235
|
-
if (o0 >= 0x100000000)
|
|
236
|
-
o1++;
|
|
237
|
-
v[a] = o0;
|
|
238
|
-
v[a + 1] = o1;
|
|
239
|
-
}
|
|
240
|
-
function get32(arr, i) {
|
|
241
|
-
return arr[i] ^ (arr[i + 1] << 8) ^ (arr[i + 2] << 16) ^ (arr[i + 3] << 24);
|
|
242
|
-
}
|
|
243
|
-
function b2bG(a, b, c, d, ix, iy) {
|
|
244
|
-
const x0 = bm[ix], x1 = bm[ix + 1], y0 = bm[iy], y1 = bm[iy + 1];
|
|
245
|
-
add64AA(bv, a, b);
|
|
246
|
-
add64AC(bv, a, x0, x1);
|
|
247
|
-
// v[d] = rotr64(v[d] ^ v[a], 32)
|
|
248
|
-
let xor0 = bv[d] ^ bv[a], xor1 = bv[d + 1] ^ bv[a + 1];
|
|
249
|
-
bv[d] = xor1;
|
|
250
|
-
bv[d + 1] = xor0;
|
|
251
|
-
add64AA(bv, c, d);
|
|
252
|
-
// v[b] = rotr64(v[b] ^ v[c], 24)
|
|
253
|
-
xor0 = bv[b] ^ bv[c];
|
|
254
|
-
xor1 = bv[b + 1] ^ bv[c + 1];
|
|
255
|
-
bv[b] = (xor0 >>> 24) ^ (xor1 << 8);
|
|
256
|
-
bv[b + 1] = (xor1 >>> 24) ^ (xor0 << 8);
|
|
257
|
-
add64AA(bv, a, b);
|
|
258
|
-
add64AC(bv, a, y0, y1);
|
|
259
|
-
// v[d] = rotr64(v[d] ^ v[a], 16)
|
|
260
|
-
xor0 = bv[d] ^ bv[a];
|
|
261
|
-
xor1 = bv[d + 1] ^ bv[a + 1];
|
|
262
|
-
bv[d] = (xor0 >>> 16) ^ (xor1 << 16);
|
|
263
|
-
bv[d + 1] = (xor1 >>> 16) ^ (xor0 << 16);
|
|
264
|
-
add64AA(bv, c, d);
|
|
265
|
-
// v[b] = rotr64(v[b] ^ v[c], 63)
|
|
266
|
-
xor0 = bv[b] ^ bv[c];
|
|
267
|
-
xor1 = bv[b + 1] ^ bv[c + 1];
|
|
268
|
-
bv[b] = (xor1 >>> 31) ^ (xor0 << 1);
|
|
269
|
-
bv[b + 1] = (xor0 >>> 31) ^ (xor1 << 1);
|
|
270
|
-
}
|
|
271
|
-
function blake2bCompress(ctx, last) {
|
|
272
|
-
let i;
|
|
273
|
-
for (i = 0; i < 16; i++) {
|
|
274
|
-
bv[i] = ctx.h[i];
|
|
275
|
-
bv[i + 16] = BLAKE2B_IV32[i];
|
|
276
|
-
}
|
|
277
|
-
// low 64 bits of the byte counter (inputs here are far below 2^53 bytes)
|
|
278
|
-
bv[24] = bv[24] ^ ctx.t;
|
|
279
|
-
bv[25] = bv[25] ^ (ctx.t / 0x100000000);
|
|
280
|
-
if (last) {
|
|
281
|
-
bv[28] = ~bv[28];
|
|
282
|
-
bv[29] = ~bv[29];
|
|
283
|
-
}
|
|
284
|
-
for (i = 0; i < 32; i++)
|
|
285
|
-
bm[i] = get32(ctx.b, 4 * i);
|
|
286
|
-
for (i = 0; i < 12; i++) {
|
|
287
|
-
const s = i * 16;
|
|
288
|
-
b2bG(0, 8, 16, 24, SIGMA82[s + 0], SIGMA82[s + 1]);
|
|
289
|
-
b2bG(2, 10, 18, 26, SIGMA82[s + 2], SIGMA82[s + 3]);
|
|
290
|
-
b2bG(4, 12, 20, 28, SIGMA82[s + 4], SIGMA82[s + 5]);
|
|
291
|
-
b2bG(6, 14, 22, 30, SIGMA82[s + 6], SIGMA82[s + 7]);
|
|
292
|
-
b2bG(0, 10, 20, 30, SIGMA82[s + 8], SIGMA82[s + 9]);
|
|
293
|
-
b2bG(2, 12, 22, 24, SIGMA82[s + 10], SIGMA82[s + 11]);
|
|
294
|
-
b2bG(4, 14, 16, 26, SIGMA82[s + 12], SIGMA82[s + 13]);
|
|
295
|
-
b2bG(6, 8, 18, 28, SIGMA82[s + 14], SIGMA82[s + 15]);
|
|
296
|
-
}
|
|
297
|
-
for (i = 0; i < 16; i++)
|
|
298
|
-
ctx.h[i] = ctx.h[i] ^ bv[i] ^ bv[i + 16];
|
|
299
|
-
}
|
|
300
|
-
/** blake2b digest of `data`, `outLen` bytes (1..64, default 32), no key */
|
|
301
|
-
function blake2b(data, outLen = 32) {
|
|
302
|
-
if (!(outLen > 0 && outLen <= 64))
|
|
303
|
-
throw new Error(`blake2b: illegal output length ${outLen}`);
|
|
304
|
-
const input = toBuf(data);
|
|
305
|
-
const ctx = { b: new Uint8Array(128), h: new Uint32Array(16), t: 0, c: 0, outlen: outLen };
|
|
306
|
-
for (let i = 0; i < 16; i++)
|
|
307
|
-
ctx.h[i] = BLAKE2B_IV32[i];
|
|
308
|
-
ctx.h[0] ^= 0x01010000 ^ outLen; // parameter block: digest length, key length 0, fanout 1, depth 1
|
|
309
|
-
for (let i = 0; i < input.length; i++) {
|
|
310
|
-
if (ctx.c === 128) {
|
|
311
|
-
ctx.t += ctx.c;
|
|
312
|
-
blake2bCompress(ctx, false);
|
|
313
|
-
ctx.c = 0;
|
|
314
|
-
}
|
|
315
|
-
ctx.b[ctx.c++] = input[i];
|
|
316
|
-
}
|
|
317
|
-
ctx.t += ctx.c;
|
|
318
|
-
while (ctx.c < 128)
|
|
319
|
-
ctx.b[ctx.c++] = 0;
|
|
320
|
-
blake2bCompress(ctx, true);
|
|
321
|
-
const out = Buffer.alloc(outLen);
|
|
322
|
-
for (let i = 0; i < outLen; i++)
|
|
323
|
-
out[i] = ctx.h[i >> 2] >> (8 * (i & 3));
|
|
324
|
-
return out;
|
|
325
|
-
}
|
|
326
|
-
const blake2_128 = (data) => blake2b(data, 16);
|
|
327
|
-
exports.blake2_128 = blake2_128;
|
|
328
|
-
const blake2_256 = (data) => blake2b(data, 32);
|
|
329
|
-
exports.blake2_256 = blake2_256;
|
|
330
|
-
const blake2_512 = (data) => blake2b(data, 64);
|
|
331
|
-
exports.blake2_512 = blake2_512;
|
|
332
|
-
// ---------------------------------------------------------------------------
|
|
333
|
-
// base58 / ss58
|
|
334
|
-
// ---------------------------------------------------------------------------
|
|
335
|
-
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
|
|
336
|
-
const BASE58_MAP = {};
|
|
337
|
-
for (let i = 0; i < BASE58_ALPHABET.length; i++)
|
|
338
|
-
BASE58_MAP[BASE58_ALPHABET[i]] = i;
|
|
339
|
-
/** base58 (bitcoin alphabet) decode, keeps leading zero bytes */
|
|
340
|
-
function base58Decode(str) {
|
|
341
|
-
if (typeof str !== 'string')
|
|
342
|
-
throw new Error('base58Decode: expected a string');
|
|
343
|
-
if (!str.length)
|
|
344
|
-
return Buffer.alloc(0);
|
|
345
|
-
let zeros = 0;
|
|
346
|
-
while (zeros < str.length && str[zeros] === '1')
|
|
347
|
-
zeros++;
|
|
348
|
-
const bytes = [];
|
|
349
|
-
for (let i = zeros; i < str.length; i++) {
|
|
350
|
-
const c = str[i];
|
|
351
|
-
let carry = BASE58_MAP[c];
|
|
352
|
-
if (carry === undefined)
|
|
353
|
-
throw new Error(`base58Decode: invalid character "${c}"`);
|
|
354
|
-
for (let j = 0; j < bytes.length; j++) {
|
|
355
|
-
carry += bytes[j] * 58;
|
|
356
|
-
bytes[j] = carry & 0xff;
|
|
357
|
-
carry >>= 8;
|
|
358
|
-
}
|
|
359
|
-
while (carry > 0) {
|
|
360
|
-
bytes.push(carry & 0xff);
|
|
361
|
-
carry >>= 8;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
const out = Buffer.alloc(zeros + bytes.length);
|
|
365
|
-
for (let i = 0; i < bytes.length; i++)
|
|
366
|
-
out[zeros + i] = bytes[bytes.length - 1 - i];
|
|
367
|
-
return out;
|
|
368
|
-
}
|
|
369
|
-
/** base58 (bitcoin alphabet) encode */
|
|
370
|
-
function base58Encode(data) {
|
|
371
|
-
const buf = toBuf(data);
|
|
372
|
-
if (!buf.length)
|
|
373
|
-
return '';
|
|
374
|
-
let zeros = 0;
|
|
375
|
-
while (zeros < buf.length && buf[zeros] === 0)
|
|
376
|
-
zeros++;
|
|
377
|
-
const digits = [];
|
|
378
|
-
for (let i = zeros; i < buf.length; i++) {
|
|
379
|
-
let carry = buf[i];
|
|
380
|
-
for (let j = 0; j < digits.length; j++) {
|
|
381
|
-
carry += digits[j] << 8;
|
|
382
|
-
digits[j] = carry % 58;
|
|
383
|
-
carry = (carry / 58) | 0;
|
|
384
|
-
}
|
|
385
|
-
while (carry > 0) {
|
|
386
|
-
digits.push(carry % 58);
|
|
387
|
-
carry = (carry / 58) | 0;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
let out = '';
|
|
391
|
-
for (let i = 0; i < zeros; i++)
|
|
392
|
-
out += '1';
|
|
393
|
-
for (let i = digits.length - 1; i >= 0; i--)
|
|
394
|
-
out += BASE58_ALPHABET[digits[i]];
|
|
395
|
-
return out;
|
|
396
|
-
}
|
|
397
|
-
const SS58_PREFIX_BYTES = Buffer.from('SS58PRE', 'utf8');
|
|
398
|
-
function ss58Checksum(prefixBytes, pubkey) {
|
|
399
|
-
return blake2b(concat([SS58_PREFIX_BYTES, prefixBytes, pubkey]), 64).subarray(0, 2);
|
|
400
|
-
}
|
|
401
|
-
function ss58PrefixBytes(prefix) {
|
|
402
|
-
if (!Number.isInteger(prefix) || prefix < 0 || prefix > 16383)
|
|
403
|
-
throw new Error(`ss58: invalid network prefix ${prefix}`);
|
|
404
|
-
if (prefix < 64)
|
|
405
|
-
return Buffer.from([prefix]);
|
|
406
|
-
// 14 bit prefix over two bytes: 01LLLLLL HHHHHHLL (L = low 8 bits, H = high 6 bits)
|
|
407
|
-
return Buffer.from([((prefix & 0xfc) >> 2) | 0x40, (prefix >> 8) | ((prefix & 0x03) << 6)]);
|
|
408
|
-
}
|
|
409
|
-
/** ss58 address -> { prefix, pubkey } (checksum verified) */
|
|
410
|
-
function ss58DecodeFull(address) {
|
|
411
|
-
const bytes = base58Decode(address);
|
|
412
|
-
if (bytes.length < 3)
|
|
413
|
-
throw new Error(`ss58Decode: address too short "${address}"`);
|
|
414
|
-
let prefixLen;
|
|
415
|
-
let prefix;
|
|
416
|
-
if (bytes[0] < 64) {
|
|
417
|
-
prefixLen = 1;
|
|
418
|
-
prefix = bytes[0];
|
|
419
|
-
}
|
|
420
|
-
else if (bytes[0] < 128) {
|
|
421
|
-
prefixLen = 2;
|
|
422
|
-
const lower = ((bytes[0] & 0x3f) << 2) | (bytes[1] >> 6);
|
|
423
|
-
const upper = bytes[1] & 0x3f;
|
|
424
|
-
prefix = lower | (upper << 8);
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
throw new Error(`ss58Decode: reserved address format "${address}"`);
|
|
428
|
-
}
|
|
429
|
-
const pubkey = bytes.subarray(prefixLen, bytes.length - 2);
|
|
430
|
-
const checksum = bytes.subarray(bytes.length - 2);
|
|
431
|
-
const expected = ss58Checksum(bytes.subarray(0, prefixLen), pubkey);
|
|
432
|
-
if (!checksum.equals(expected))
|
|
433
|
-
throw new Error(`ss58Decode: bad checksum for "${address}"`);
|
|
434
|
-
return { prefix, pubkey: Buffer.from(pubkey) };
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* ss58 address -> 32 byte account id. A Buffer / Uint8Array / `0x` hex account id is
|
|
438
|
-
* returned as-is so callers can accept both address formats.
|
|
439
|
-
*/
|
|
440
|
-
function ss58Decode(address) {
|
|
441
|
-
if (Buffer.isBuffer(address) || address instanceof Uint8Array)
|
|
442
|
-
return toBuf(address);
|
|
443
|
-
if (typeof address === 'string' && /^0x[0-9a-fA-F]{64}$/.test(address))
|
|
444
|
-
return toBuf(address);
|
|
445
|
-
return ss58DecodeFull(address).pubkey;
|
|
446
|
-
}
|
|
447
|
-
/** account id (32 bytes) -> ss58 address with `prefix` (0 = polkadot, 2 = kusama, 42 = generic) */
|
|
448
|
-
function ss58Encode(pubkey, prefix = 0) {
|
|
449
|
-
const key = toBuf(pubkey);
|
|
450
|
-
if (![32, 33, 1, 2, 4, 8].includes(key.length))
|
|
451
|
-
throw new Error(`ss58Encode: unexpected public key length ${key.length}`);
|
|
452
|
-
const prefixBytes = ss58PrefixBytes(prefix);
|
|
453
|
-
return base58Encode(concat([prefixBytes, key, ss58Checksum(prefixBytes, key)]));
|
|
454
|
-
}
|
|
455
|
-
// ---------------------------------------------------------------------------
|
|
456
|
-
// SCALE
|
|
457
|
-
// ---------------------------------------------------------------------------
|
|
458
|
-
const encodeU8 = (n) => Buffer.from([n & 0xff]);
|
|
459
|
-
exports.encodeU8 = encodeU8;
|
|
460
|
-
const encodeU16 = (n) => { const b = Buffer.alloc(2); b.writeUInt16LE(n); return b; };
|
|
461
|
-
exports.encodeU16 = encodeU16;
|
|
462
|
-
const encodeU32 = (n) => { const b = Buffer.alloc(4); b.writeUInt32LE(n >>> 0); return b; };
|
|
463
|
-
exports.encodeU32 = encodeU32;
|
|
464
|
-
const encodeU64 = (n) => u64le(BigInt(n));
|
|
465
|
-
exports.encodeU64 = encodeU64;
|
|
466
|
-
const encodeU128 = (n) => encodeUint(n, 16);
|
|
467
|
-
exports.encodeU128 = encodeU128;
|
|
468
|
-
/** little endian unsigned integer of `bytes` bytes */
|
|
469
|
-
function encodeUint(n, bytes) {
|
|
470
|
-
let v = BigInt(n);
|
|
471
|
-
if (v < B0)
|
|
472
|
-
throw new Error(`encodeUint: negative value ${n}`);
|
|
473
|
-
const b = Buffer.alloc(bytes);
|
|
474
|
-
for (let i = 0; i < bytes; i++) {
|
|
475
|
-
b[i] = Number(v & BigInt(0xff));
|
|
476
|
-
v >>= BigInt(8);
|
|
477
|
-
}
|
|
478
|
-
if (v !== B0)
|
|
479
|
-
throw new Error(`encodeUint: ${n} does not fit in ${bytes} bytes`);
|
|
480
|
-
return b;
|
|
481
|
-
}
|
|
482
|
-
/** SCALE Compact<uN> */
|
|
483
|
-
function encodeCompact(value) {
|
|
484
|
-
let n = BigInt(value);
|
|
485
|
-
if (n < B0)
|
|
486
|
-
throw new Error(`encodeCompact: negative value ${value}`);
|
|
487
|
-
if (n < BigInt(64))
|
|
488
|
-
return Buffer.from([Number(n) << 2]);
|
|
489
|
-
if (n < BigInt(16384))
|
|
490
|
-
return (0, exports.encodeU16)((Number(n) << 2) | 1);
|
|
491
|
-
if (n < BigInt(1073741824))
|
|
492
|
-
return (0, exports.encodeU32)(((Number(n) << 2) | 2) >>> 0);
|
|
493
|
-
const bytes = [];
|
|
494
|
-
while (n > B0) {
|
|
495
|
-
bytes.push(Number(n & BigInt(0xff)));
|
|
496
|
-
n >>= BigInt(8);
|
|
497
|
-
}
|
|
498
|
-
if (bytes.length > 67)
|
|
499
|
-
throw new Error('encodeCompact: value too large');
|
|
500
|
-
return Buffer.from([((bytes.length - 4) << 2) | 3, ...bytes]);
|
|
501
|
-
}
|
|
502
|
-
/** little endian unsigned integer at `offset`, `bytes` wide (default u128); missing bytes read as 0 */
|
|
503
|
-
function decodeUint(value, { offset = 0, bytes = 16 } = {}) {
|
|
504
|
-
if (!value)
|
|
505
|
-
return B0;
|
|
506
|
-
const b = toBuf(value);
|
|
507
|
-
let n = B0;
|
|
508
|
-
for (let i = bytes - 1; i >= 0; i--) {
|
|
509
|
-
const byte = b[offset + i];
|
|
510
|
-
n = (n << BigInt(8)) | BigInt(byte === undefined ? 0 : byte);
|
|
511
|
-
}
|
|
512
|
-
return n;
|
|
513
|
-
}
|
|
514
|
-
/** SCALE Compact<uN> at `offset` -> { value, length: bytes consumed } */
|
|
515
|
-
function decodeCompact(value, offset = 0) {
|
|
516
|
-
const b = toBuf(value);
|
|
517
|
-
if (offset >= b.length)
|
|
518
|
-
throw new Error('decodeCompact: out of bounds');
|
|
519
|
-
const mode = b[offset] & 0b11;
|
|
520
|
-
if (mode === 0)
|
|
521
|
-
return { value: BigInt(b[offset] >> 2), length: 1 };
|
|
522
|
-
if (mode === 1)
|
|
523
|
-
return { value: BigInt(b.readUInt16LE(offset) >> 2), length: 2 };
|
|
524
|
-
if (mode === 2)
|
|
525
|
-
return { value: BigInt(b.readUInt32LE(offset) >>> 2), length: 4 };
|
|
526
|
-
const len = (b[offset] >> 2) + 4;
|
|
527
|
-
return { value: decodeUint(b, { offset: offset + 1, bytes: len }), length: len + 1 };
|
|
528
|
-
}
|
|
529
|
-
/** Sequential SCALE reader for hand decoding structs */
|
|
530
|
-
class ScaleReader {
|
|
531
|
-
constructor(value) {
|
|
532
|
-
this.buf = toBuf(value);
|
|
533
|
-
this.offset = 0;
|
|
534
|
-
}
|
|
535
|
-
get remaining() { return this.buf.length - this.offset; }
|
|
536
|
-
need(n) {
|
|
537
|
-
if (this.offset + n > this.buf.length)
|
|
538
|
-
throw new Error(`ScaleReader: out of bounds (need ${n} at ${this.offset}, length ${this.buf.length})`);
|
|
539
|
-
}
|
|
540
|
-
/** next `n` raw bytes (view, not a copy) */
|
|
541
|
-
bytes(n) {
|
|
542
|
-
this.need(n);
|
|
543
|
-
const b = this.buf.subarray(this.offset, this.offset + n);
|
|
544
|
-
this.offset += n;
|
|
545
|
-
return b;
|
|
546
|
-
}
|
|
547
|
-
skip(n) { this.need(n); this.offset += n; return this; }
|
|
548
|
-
u8() { this.need(1); return this.buf[this.offset++]; }
|
|
549
|
-
u16() { this.need(2); const v = this.buf.readUInt16LE(this.offset); this.offset += 2; return v; }
|
|
550
|
-
u32() { this.need(4); const v = this.buf.readUInt32LE(this.offset); this.offset += 4; return v; }
|
|
551
|
-
u64() { return decodeUint(this.bytes(8), { bytes: 8 }); }
|
|
552
|
-
u128() { return decodeUint(this.bytes(16), { bytes: 16 }); }
|
|
553
|
-
u256() { return decodeUint(this.bytes(32), { bytes: 32 }); }
|
|
554
|
-
i32() { this.need(4); const v = this.buf.readInt32LE(this.offset); this.offset += 4; return v; }
|
|
555
|
-
i64() { this.need(8); const v = this.buf.readBigInt64LE(this.offset); this.offset += 8; return v; }
|
|
556
|
-
bool() { return this.u8() === 1; }
|
|
557
|
-
compact() {
|
|
558
|
-
const { value, length } = decodeCompact(this.buf, this.offset);
|
|
559
|
-
this.offset += length;
|
|
560
|
-
return value;
|
|
561
|
-
}
|
|
562
|
-
/** Option<T>: `null` when the tag byte is 0 */
|
|
563
|
-
option(fn) { return this.u8() === 0 ? null : fn(this); }
|
|
564
|
-
/** Vec<T> */
|
|
565
|
-
vec(fn) {
|
|
566
|
-
const len = Number(this.compact());
|
|
567
|
-
const out = [];
|
|
568
|
-
for (let i = 0; i < len; i++)
|
|
569
|
-
out.push(fn(this));
|
|
570
|
-
return out;
|
|
571
|
-
}
|
|
572
|
-
/** Vec<u8> / BoundedVec<u8> */
|
|
573
|
-
bytesVec() { return this.bytes(Number(this.compact())); }
|
|
574
|
-
string() { return this.bytesVec().toString('utf8'); }
|
|
575
|
-
/** 32 byte AccountId as `0x` hex */
|
|
576
|
-
accountId() { return hex(this.bytes(32)); }
|
|
577
|
-
/** H256 as `0x` hex */
|
|
578
|
-
hash() { return hex(this.bytes(32)); }
|
|
579
|
-
}
|
|
580
|
-
exports.ScaleReader = ScaleReader;
|
|
581
|
-
const twox64Concat = (key) => concat([(0, exports.twox64)(key), toBuf(key)]);
|
|
582
|
-
exports.twox64Concat = twox64Concat;
|
|
583
|
-
const blake2_128Concat = (key) => concat([(0, exports.blake2_128)(key), toBuf(key)]);
|
|
584
|
-
exports.blake2_128Concat = blake2_128Concat;
|
|
585
|
-
const identity = (key) => toBuf(key);
|
|
586
|
-
exports.identity = identity;
|
|
587
|
-
/** key hashers as used in pallet storage definitions (looked up case-insensitively) */
|
|
588
|
-
exports.hashers = {
|
|
589
|
-
Twox64Concat: { encode: exports.twox64Concat, hashLength: 8, concat: true },
|
|
590
|
-
Blake2_128Concat: { encode: exports.blake2_128Concat, hashLength: 16, concat: true },
|
|
591
|
-
Identity: { encode: exports.identity, hashLength: 0, concat: true },
|
|
592
|
-
Twox128: { encode: exports.twox128, hashLength: 16, concat: false },
|
|
593
|
-
Twox256: { encode: exports.twox256, hashLength: 32, concat: false },
|
|
594
|
-
Blake2_128: { encode: exports.blake2_128, hashLength: 16, concat: false },
|
|
595
|
-
Blake2_256: { encode: exports.blake2_256, hashLength: 32, concat: false },
|
|
596
|
-
};
|
|
597
|
-
const hashersByName = {};
|
|
598
|
-
Object.keys(exports.hashers).forEach(name => hashersByName[name.toLowerCase()] = exports.hashers[name]);
|
|
599
|
-
exports.DEFAULT_HASHER = 'Twox64Concat';
|
|
600
|
-
function getHasher(name = exports.DEFAULT_HASHER) {
|
|
601
|
-
const hasher = hashersByName[String(name).toLowerCase()];
|
|
602
|
-
if (!hasher)
|
|
603
|
-
throw new Error(`substrate: unknown storage hasher "${name}" (known: ${Object.keys(exports.hashers).join(', ')})`);
|
|
604
|
-
return hasher;
|
|
605
|
-
}
|
|
606
|
-
/** twox128(pallet) ++ twox128(item) */
|
|
607
|
-
const storagePrefix = (pallet, item) => concat([(0, exports.twox128)(pallet), (0, exports.twox128)(item)]);
|
|
608
|
-
exports.storagePrefix = storagePrefix;
|
|
609
|
-
/** full storage key as `0x` hex */
|
|
610
|
-
function storageKey({ pallet, item, key, hasher = exports.DEFAULT_HASHER, keys = [] }) {
|
|
611
|
-
const parts = [(0, exports.storagePrefix)(pallet, item)];
|
|
612
|
-
const all = key !== undefined ? [{ hasher, key }, ...keys] : keys;
|
|
613
|
-
for (const entry of all)
|
|
614
|
-
parts.push(getHasher(entry.hasher).encode(entry.key));
|
|
615
|
-
return hex(concat(parts));
|
|
616
|
-
}
|
|
617
|
-
/** strip the hash part of a concat hasher from an entry's `rest` buffer -> raw SCALE key */
|
|
618
|
-
function stripHasher(rest, hasher = exports.DEFAULT_HASHER) {
|
|
619
|
-
return toBuf(rest).subarray(getHasher(hasher).hashLength);
|
|
620
|
-
}
|
|
621
|
-
// ---------------------------------------------------------------------------
|
|
622
|
-
// endpoints / transport
|
|
623
|
-
// ---------------------------------------------------------------------------
|
|
624
|
-
function getEndpoints({ chain }) {
|
|
625
|
-
if (!chain)
|
|
626
|
-
throw new Error('substrate: chain is required');
|
|
627
|
-
if (chain.includes('://'))
|
|
628
|
-
return (0, rpc_1.toEndpointList)(chain);
|
|
629
|
-
const key = chain.toUpperCase();
|
|
630
|
-
// `<CHAIN>_RPC` is the EVM rpc for chains like astar / acala / moonbeam, only fall back to it for non-EVM chains
|
|
631
|
-
const fallback = (0, LlamaProvider_1.isEvmChain)(chain) ? undefined : (0, env_1.getEnvRPC)(chain);
|
|
632
|
-
return (0, rpc_1.getEndpoints)(chain, exports.DEFAULT_ENDPOINTS[chain], { envKey: `${key}_SUBSTRATE_RPC`, fallback });
|
|
633
|
-
}
|
|
634
|
-
const chainLabel = (chain) => chain.includes('://') ? 'substrate' : chain;
|
|
635
|
-
/** Raw JSON-RPC call; rotates endpoints, retries transient failures, runs under a per-chain limiter */
|
|
636
|
-
async function rpc({ chain, method, params = [], retries }) {
|
|
637
|
-
const endpoints = getEndpoints({ chain });
|
|
638
|
-
const limiter = (0, rpc_1.getLimiter)(`SUBSTRATE_${chainLabel(chain).toUpperCase()}`, DEFAULT_CONCURRENCY);
|
|
639
|
-
return limiter(() => (0, rpc_1.jsonRpc)(method, params, { chain: chainLabel(chain), endpoints, retries }));
|
|
640
|
-
}
|
|
641
|
-
const getFinalizedHead = ({ chain, retries }) => rpc({ chain, method: 'chain_getFinalizedHead', retries });
|
|
642
|
-
exports.getFinalizedHead = getFinalizedHead;
|
|
643
|
-
/** block hash of `number` (latest best block when omitted); `null` when unknown */
|
|
644
|
-
async function getBlockHash({ chain, number, retries }) {
|
|
645
|
-
const params = number === undefined ? [] : [number];
|
|
646
|
-
return rpc({ chain, method: 'chain_getBlockHash', params, retries });
|
|
647
|
-
}
|
|
648
|
-
function toHeader(raw, hash) {
|
|
649
|
-
if (!raw)
|
|
650
|
-
throw new Error('substrate: block/header not found');
|
|
651
|
-
return {
|
|
652
|
-
number: parseInt(raw.number, 16),
|
|
653
|
-
hash,
|
|
654
|
-
parentHash: raw.parentHash,
|
|
655
|
-
stateRoot: raw.stateRoot,
|
|
656
|
-
extrinsicsRoot: raw.extrinsicsRoot,
|
|
657
|
-
digest: raw.digest,
|
|
658
|
-
};
|
|
659
|
-
}
|
|
660
|
-
/** header at `hash` (finalized head when omitted) */
|
|
661
|
-
async function getHeader({ chain, hash, retries }) {
|
|
662
|
-
if (!hash)
|
|
663
|
-
hash = await (0, exports.getFinalizedHead)({ chain, retries });
|
|
664
|
-
const raw = await rpc({ chain, method: 'chain_getHeader', params: [hash], retries });
|
|
665
|
-
return toHeader(raw, hash);
|
|
666
|
-
}
|
|
667
|
-
/** `state_getRuntimeVersion` */
|
|
668
|
-
const getRuntimeVersion = ({ chain, at, retries }) => rpc({ chain, method: 'state_getRuntimeVersion', params: at ? [at] : [], retries });
|
|
669
|
-
exports.getRuntimeVersion = getRuntimeVersion;
|
|
670
|
-
const MIN_MS = 1e12; // 2001
|
|
671
|
-
const MAX_MS = 1e13; // 2286
|
|
672
|
-
/**
|
|
673
|
-
* Decode the `timestamp.set` inherent (first bare extrinsic, call index 0, Compact<u64> ms).
|
|
674
|
-
* Returns unix seconds or undefined when the block has no recognisable timestamp inherent.
|
|
675
|
-
*/
|
|
676
|
-
function decodeTimestampInherent(extrinsics) {
|
|
677
|
-
if (!(extrinsics === null || extrinsics === void 0 ? void 0 : extrinsics.length))
|
|
678
|
-
return undefined;
|
|
679
|
-
for (const ext of extrinsics.slice(0, 3)) {
|
|
680
|
-
try {
|
|
681
|
-
const r = new ScaleReader(ext);
|
|
682
|
-
r.compact(); // length prefix
|
|
683
|
-
const version = r.u8();
|
|
684
|
-
if (version & 0xc0)
|
|
685
|
-
continue; // signed / general extrinsic: not an inherent
|
|
686
|
-
r.u8(); // pallet index (chain specific)
|
|
687
|
-
if (r.u8() !== 0)
|
|
688
|
-
continue; // Call::set is index 0 of pallet_timestamp
|
|
689
|
-
const ms = Number(r.compact());
|
|
690
|
-
if (ms >= MIN_MS && ms < MAX_MS)
|
|
691
|
-
return Math.floor(ms / 1000);
|
|
692
|
-
}
|
|
693
|
-
catch {
|
|
694
|
-
// not a timestamp inherent
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
return undefined;
|
|
698
|
-
}
|
|
699
|
-
/** Timestamp.Now (u64 ms) at `at` -> unix seconds */
|
|
700
|
-
async function getTimestampAt({ chain, at, retries }) {
|
|
701
|
-
const value = await getStorage({ chain, pallet: 'Timestamp', item: 'Now', at, retries });
|
|
702
|
-
if (!value)
|
|
703
|
-
throw new Error(`substrate ${chainLabel(chain)}: Timestamp.Now not found at ${at !== null && at !== void 0 ? at : 'head'}`);
|
|
704
|
-
return Math.floor(Number(decodeUint(value, { bytes: 8 })) / 1000);
|
|
705
|
-
}
|
|
706
|
-
/** block by `hash` or `number` (finalized head when neither is given), with its timestamp */
|
|
707
|
-
async function getBlock({ chain, hash, number, retries }) {
|
|
708
|
-
var _a, _b;
|
|
709
|
-
if (!hash) {
|
|
710
|
-
if (number !== undefined) {
|
|
711
|
-
const h = await getBlockHash({ chain, number, retries });
|
|
712
|
-
if (!h)
|
|
713
|
-
throw new Error(`substrate ${chainLabel(chain)}: block ${number} not found`);
|
|
714
|
-
hash = h;
|
|
715
|
-
}
|
|
716
|
-
else
|
|
717
|
-
hash = await (0, exports.getFinalizedHead)({ chain, retries });
|
|
718
|
-
}
|
|
719
|
-
const raw = await rpc({ chain, method: 'chain_getBlock', params: [hash], retries });
|
|
720
|
-
if (!(raw === null || raw === void 0 ? void 0 : raw.block))
|
|
721
|
-
throw new Error(`substrate ${chainLabel(chain)}: block ${hash} not found`);
|
|
722
|
-
const header = toHeader(raw.block.header, hash);
|
|
723
|
-
const extrinsics = (_a = raw.block.extrinsics) !== null && _a !== void 0 ? _a : [];
|
|
724
|
-
let timestamp = decodeTimestampInherent(extrinsics);
|
|
725
|
-
if (timestamp === undefined) {
|
|
726
|
-
try {
|
|
727
|
-
timestamp = await getTimestampAt({ chain, at: hash, retries });
|
|
728
|
-
}
|
|
729
|
-
catch (e) {
|
|
730
|
-
(0, debugLog_1.debugLog)(`[chains.substrate] ${chainLabel(chain)}: no timestamp for block ${header.number}: ${(_b = e === null || e === void 0 ? void 0 : e.message) !== null && _b !== void 0 ? _b : e}`);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
return { number: header.number, hash, parentHash: header.parentHash, timestamp, extrinsics, header };
|
|
734
|
-
}
|
|
735
|
-
const getLatestBlock = (options) => getBlock(options);
|
|
736
|
-
exports.getLatestBlock = getLatestBlock;
|
|
737
|
-
/**
|
|
738
|
-
* Last block whose timestamp is <= `timestamp` (unix seconds, ms accepted). Brackets the
|
|
739
|
-
* range assuming ~6s blocks then binary searches on Timestamp.Now at each block hash
|
|
740
|
-
* (falls back to the timestamp inherent on nodes with pruned state).
|
|
741
|
-
*/
|
|
742
|
-
async function getBlockAtTimestamp({ chain, timestamp, retries }) {
|
|
743
|
-
if (!timestamp || !Number.isFinite(timestamp))
|
|
744
|
-
throw new Error('substrate getBlockAtTimestamp: invalid timestamp');
|
|
745
|
-
if (timestamp > 1e12)
|
|
746
|
-
timestamp = Math.floor(timestamp / 1000);
|
|
747
|
-
const latest = await getBlock({ chain, retries });
|
|
748
|
-
if (latest.timestamp === undefined)
|
|
749
|
-
throw new Error(`substrate ${chainLabel(chain)}: cannot read block timestamps`);
|
|
750
|
-
if (latest.timestamp <= timestamp)
|
|
751
|
-
return latest;
|
|
752
|
-
const hashCache = new Map();
|
|
753
|
-
const tsCache = new Map();
|
|
754
|
-
tsCache.set(latest.number, latest.timestamp);
|
|
755
|
-
const hashAt = async (n) => {
|
|
756
|
-
let h = hashCache.get(n);
|
|
757
|
-
if (!h) {
|
|
758
|
-
const res = await getBlockHash({ chain, number: n, retries });
|
|
759
|
-
if (!res)
|
|
760
|
-
throw new Error(`substrate ${chainLabel(chain)}: block ${n} not found`);
|
|
761
|
-
hashCache.set(n, res);
|
|
762
|
-
h = res;
|
|
763
|
-
}
|
|
764
|
-
return h;
|
|
765
|
-
};
|
|
766
|
-
const tsAt = async (n) => {
|
|
767
|
-
var _a;
|
|
768
|
-
const cached = tsCache.get(n);
|
|
769
|
-
if (cached !== undefined)
|
|
770
|
-
return cached;
|
|
771
|
-
const h = await hashAt(n);
|
|
772
|
-
let ts;
|
|
773
|
-
try {
|
|
774
|
-
ts = await getTimestampAt({ chain, at: h, retries });
|
|
775
|
-
}
|
|
776
|
-
catch (e) {
|
|
777
|
-
(0, debugLog_1.debugLog)(`[chains.substrate] ${chainLabel(chain)}: Timestamp.Now at #${n} failed (${(_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : e}), reading block inherent`);
|
|
778
|
-
const block = await getBlock({ chain, hash: h, retries });
|
|
779
|
-
if (block.timestamp === undefined)
|
|
780
|
-
throw new Error(`substrate ${chainLabel(chain)}: no timestamp for block ${n}`);
|
|
781
|
-
ts = block.timestamp;
|
|
782
|
-
}
|
|
783
|
-
tsCache.set(n, ts);
|
|
784
|
-
return ts;
|
|
785
|
-
};
|
|
786
|
-
// bracket: estimated distance in blocks +- 5%, widened until lo <= target < hi
|
|
787
|
-
const estimate = Math.ceil((latest.timestamp - timestamp) / BLOCK_TIME);
|
|
788
|
-
let margin = Math.max(50, Math.ceil(estimate * 0.05));
|
|
789
|
-
let lo = Math.max(0, latest.number - estimate - margin);
|
|
790
|
-
let hi = Math.min(latest.number, latest.number - estimate + margin);
|
|
791
|
-
while ((await tsAt(lo)) > timestamp) {
|
|
792
|
-
if (lo === 0)
|
|
793
|
-
throw new Error(`substrate ${chainLabel(chain)}: timestamp ${timestamp} predates the chain`);
|
|
794
|
-
margin *= 2;
|
|
795
|
-
lo = Math.max(0, lo - margin);
|
|
796
|
-
}
|
|
797
|
-
while (hi < latest.number && (await tsAt(hi)) <= timestamp) {
|
|
798
|
-
margin *= 2;
|
|
799
|
-
hi = Math.min(latest.number, hi + margin);
|
|
800
|
-
}
|
|
801
|
-
// invariant: ts(lo) <= target, ts(hi) > target (or hi is latest which is > target)
|
|
802
|
-
while (hi - lo > 1) {
|
|
803
|
-
const mid = lo + Math.floor((hi - lo) / 2);
|
|
804
|
-
if ((await tsAt(mid)) <= timestamp)
|
|
805
|
-
lo = mid;
|
|
806
|
-
else
|
|
807
|
-
hi = mid;
|
|
808
|
-
}
|
|
809
|
-
const block = await getBlock({ chain, hash: await hashAt(lo), retries });
|
|
810
|
-
(0, debugLog_1.debugLog)(`[chains.substrate] ${chainLabel(chain)} getBlockAtTimestamp(${timestamp}) -> #${block.number} @ ${block.timestamp}`);
|
|
811
|
-
return block;
|
|
812
|
-
}
|
|
813
|
-
/** `state_getStorage` for a raw storage key -> `0x` hex value or null */
|
|
814
|
-
async function getStorageRaw({ chain, key, at, retries }) {
|
|
815
|
-
const res = await rpc({ chain, method: 'state_getStorage', params: [hex(key), at !== null && at !== void 0 ? at : null], retries });
|
|
816
|
-
return res !== null && res !== void 0 ? res : null;
|
|
817
|
-
}
|
|
818
|
-
/** plain item or a single (double) map entry -> raw `0x` hex value or null */
|
|
819
|
-
async function getStorage({ chain, pallet, item, key, hasher, keys, at, retries }) {
|
|
820
|
-
return getStorageRaw({ chain, key: storageKey({ pallet, item, key, hasher, keys }), at, retries });
|
|
821
|
-
}
|
|
822
|
-
/** `state_queryStorageAt` for many keys -> values in key order (null when unset) */
|
|
823
|
-
async function getStorageBatch({ chain, storageKeys, at, chunkSize = DEFAULT_BATCH_CHUNK, retries }) {
|
|
824
|
-
var _a, _b;
|
|
825
|
-
if (!storageKeys.length)
|
|
826
|
-
return [];
|
|
827
|
-
const out = [];
|
|
828
|
-
for (const chunk of (0, rpc_1.sliceIntoChunks)(storageKeys, chunkSize)) {
|
|
829
|
-
const res = await rpc({ chain, method: 'state_queryStorageAt', params: [chunk, at !== null && at !== void 0 ? at : null], retries });
|
|
830
|
-
const byKey = {};
|
|
831
|
-
for (const changeSet of res !== null && res !== void 0 ? res : [])
|
|
832
|
-
for (const [k, v] of (_a = changeSet.changes) !== null && _a !== void 0 ? _a : [])
|
|
833
|
-
byKey[String(k).toLowerCase()] = v !== null && v !== void 0 ? v : null;
|
|
834
|
-
for (const k of chunk)
|
|
835
|
-
out.push((_b = byKey[k.toLowerCase()]) !== null && _b !== void 0 ? _b : null);
|
|
836
|
-
}
|
|
837
|
-
return out;
|
|
838
|
-
}
|
|
839
|
-
/** one page of `state_getKeysPaged` */
|
|
840
|
-
async function getKeysPaged({ chain, prefix, pageSize = DEFAULT_PAGE_SIZE, startKey, at, retries }) {
|
|
841
|
-
const res = await rpc({ chain, method: 'state_getKeysPaged', params: [hex(prefix), pageSize, startKey !== null && startKey !== void 0 ? startKey : null, at !== null && at !== void 0 ? at : null], retries });
|
|
842
|
-
return res !== null && res !== void 0 ? res : [];
|
|
843
|
-
}
|
|
844
|
-
/** every storage key under `prefix` (paginates `state_getKeysPaged`) */
|
|
845
|
-
async function getAllKeys({ chain, prefix, pageSize = DEFAULT_PAGE_SIZE, at, retries }) {
|
|
846
|
-
const allKeys = [];
|
|
847
|
-
let startKey = null;
|
|
848
|
-
while (true) {
|
|
849
|
-
const page = await getKeysPaged({ chain, prefix, pageSize, startKey, at, retries });
|
|
850
|
-
allKeys.push(...page);
|
|
851
|
-
if (page.length < pageSize)
|
|
852
|
-
break;
|
|
853
|
-
startKey = page[page.length - 1];
|
|
854
|
-
}
|
|
855
|
-
return allKeys;
|
|
856
|
-
}
|
|
857
|
-
/**
|
|
858
|
-
* Every entry of a map (optionally under partial `keys` for double maps) -> [{ key, value, rest }].
|
|
859
|
-
* Use `stripHasher(entry.rest, hasher)` to recover the raw SCALE key of concat hashers.
|
|
860
|
-
*/
|
|
861
|
-
async function getStorageEntries({ chain, pallet, item, keys = [], pageSize = DEFAULT_PAGE_SIZE, at, retries }) {
|
|
862
|
-
const prefix = storageKey({ pallet, item, keys });
|
|
863
|
-
const allKeys = await getAllKeys({ chain, prefix, pageSize, at, retries });
|
|
864
|
-
if (!allKeys.length)
|
|
865
|
-
return [];
|
|
866
|
-
const values = await getStorageBatch({ chain, storageKeys: allKeys, at, retries });
|
|
867
|
-
return allKeys.map((key, i) => ({ key, value: values[i], rest: Buffer.from(key.slice(prefix.length), 'hex') }));
|
|
868
|
-
}
|
|
869
|
-
/** runtime api call (`state_call`), e.g. `stateCall({ chain, method: 'CurrenciesApi_account', data })` -> `0x` hex */
|
|
870
|
-
async function stateCall({ chain, method, data, at, retries }) {
|
|
871
|
-
return rpc({ chain, method: 'state_call', params: [method, hex(data), at !== null && at !== void 0 ? at : null], retries });
|
|
872
|
-
}
|
|
873
|
-
/**
|
|
874
|
-
* frame_system AccountInfo: nonce u32, consumers u32, providers u32, sufficients u32,
|
|
875
|
-
* data { free, reserved, frozen|miscFrozen, flags|feeFrozen }. Balances are u128 on most
|
|
876
|
-
* chains; `balanceBytes: 8` for u64 balance chains (e.g. bittensor), auto-detected from
|
|
877
|
-
* the value length when omitted.
|
|
878
|
-
*/
|
|
879
|
-
function decodeAccountInfo(value, { balanceBytes } = {}) {
|
|
880
|
-
const zero = { nonce: 0, consumers: 0, providers: 0, sufficients: 0, free: '0', reserved: '0', frozen: '0', miscFrozen: '0', feeFrozen: '0', flags: '0' };
|
|
881
|
-
if (!value)
|
|
882
|
-
return zero;
|
|
883
|
-
const buf = toBuf(value);
|
|
884
|
-
if (!buf.length)
|
|
885
|
-
return zero;
|
|
886
|
-
if (!balanceBytes)
|
|
887
|
-
balanceBytes = buf.length === 16 + 4 * 8 ? 8 : 16;
|
|
888
|
-
const r = new ScaleReader(buf);
|
|
889
|
-
const nonce = r.u32();
|
|
890
|
-
const consumers = r.u32();
|
|
891
|
-
const providers = r.u32();
|
|
892
|
-
const sufficients = r.u32();
|
|
893
|
-
const balance = () => r.remaining >= balanceBytes ? decodeUint(r.bytes(balanceBytes), { bytes: balanceBytes }).toString() : '0';
|
|
894
|
-
const free = balance();
|
|
895
|
-
const reserved = balance();
|
|
896
|
-
const frozen = balance();
|
|
897
|
-
const flags = balance();
|
|
898
|
-
return { nonce, consumers, providers, sufficients, free, reserved, frozen, miscFrozen: frozen, feeFrozen: flags, flags };
|
|
899
|
-
}
|
|
900
|
-
/** System.Account of an ss58 address (or raw 32 byte account id) */
|
|
901
|
-
async function getSystemAccount({ chain, address, at, balanceBytes, retries }) {
|
|
902
|
-
const value = await getStorage({ chain, pallet: 'System', item: 'Account', key: ss58Decode(address), hasher: 'Blake2_128Concat', at, retries });
|
|
903
|
-
return decodeAccountInfo(value, { balanceBytes });
|
|
904
|
-
}
|
|
905
|
-
/** free native balance (raw units, decimal string) */
|
|
906
|
-
async function getFreeBalance({ chain, address, at, balanceBytes, retries }) {
|
|
907
|
-
const { free } = await getSystemAccount({ chain, address, at, balanceBytes, retries });
|
|
908
|
-
return free;
|
|
909
|
-
}
|
|
910
|
-
/** Balances.TotalIssuance (raw units, decimal string) */
|
|
911
|
-
async function getTotalIssuance({ chain, at, pallet = 'Balances', retries }) {
|
|
912
|
-
const value = await getStorage({ chain, pallet, item: 'TotalIssuance', at, retries });
|
|
913
|
-
if (!value)
|
|
914
|
-
return '0';
|
|
915
|
-
const buf = toBuf(value);
|
|
916
|
-
return decodeUint(buf, { bytes: buf.length >= 16 ? 16 : 8 }).toString();
|
|
917
|
-
}
|
|
918
|
-
/** orml_tokens AccountData: free u128, reserved u128, frozen u128 */
|
|
919
|
-
function decodeOrmlAccountData(value) {
|
|
920
|
-
if (!value)
|
|
921
|
-
return { free: '0', reserved: '0', frozen: '0' };
|
|
922
|
-
const r = new ScaleReader(value);
|
|
923
|
-
if (!r.remaining)
|
|
924
|
-
return { free: '0', reserved: '0', frozen: '0' };
|
|
925
|
-
return { free: r.u128().toString(), reserved: r.u128().toString(), frozen: r.u128().toString() };
|
|
926
|
-
}
|
|
927
|
-
/** orml Tokens.Accounts(AccountId: Blake2_128Concat, CurrencyId: Twox64Concat); `currencyId` is the SCALE encoded id (hex / bytes) */
|
|
928
|
-
async function getTokensAccount({ chain, address, currencyId, at, pallet = 'Tokens', retries }) {
|
|
929
|
-
const value = await getStorage({
|
|
930
|
-
chain, pallet, item: 'Accounts', at, retries,
|
|
931
|
-
keys: [{ hasher: 'Blake2_128Concat', key: ss58Decode(address) }, { hasher: 'Twox64Concat', key: currencyId }],
|
|
932
|
-
});
|
|
933
|
-
return decodeOrmlAccountData(value);
|
|
934
|
-
}
|
|
935
|
-
const BIFROST_CURRENCY = {
|
|
936
|
-
Native: 0, VToken: 1, Token: 2, Stable: 3, VSToken: 4, VSBond: 5, LPToken: 6, ForeignAsset: 7,
|
|
937
|
-
Token2: 8, VToken2: 9, VSToken2: 10, VSBond2: 11, StableLpToken: 12, BLP: 13, Lend: 14,
|
|
938
|
-
};
|
|
939
|
-
const BIFROST_VARIANT_NAMES = {};
|
|
940
|
-
Object.keys(BIFROST_CURRENCY).forEach(name => BIFROST_VARIANT_NAMES[BIFROST_CURRENCY[name]] = name);
|
|
941
|
-
const BIFROST_TOKEN_SYMBOLS = { 0: 'ASG', 1: 'BNC', 2: 'KUSD', 3: 'DOT', 4: 'KSM', 5: 'ETH', 6: 'KAR', 7: 'ZLK', 8: 'PHA', 9: 'RMRK', 10: 'MOVR' };
|
|
942
|
-
const BIFROST_TOKEN_IDS = {};
|
|
943
|
-
Object.keys(BIFROST_TOKEN_SYMBOLS).forEach(id => BIFROST_TOKEN_IDS[BIFROST_TOKEN_SYMBOLS[+id]] = +id);
|
|
944
|
-
// TokenId (u8) based variants on bifrost-polkadot
|
|
945
|
-
const BIFROST_TOKEN2_SYMBOLS = { 0: 'DOT', 1: 'GLMR', 2: 'PARA', 3: 'ASTR', 4: 'FIL', 8: 'MANTA', 15: 'ETH' };
|
|
946
|
-
function bifrostEncode(variant, payload) {
|
|
947
|
-
const index = BIFROST_CURRENCY[variant];
|
|
948
|
-
if (index === undefined)
|
|
949
|
-
throw new Error(`Unknown bifrost CurrencyId variant ${variant}`);
|
|
950
|
-
if (payload === undefined || Number.isNaN(payload))
|
|
951
|
-
throw new Error(`bifrost ${variant}: missing payload`);
|
|
952
|
-
return Buffer.from([index, payload]);
|
|
953
|
-
}
|
|
954
|
-
function bifrostTokenId(symbol) {
|
|
955
|
-
const id = BIFROST_TOKEN_IDS[symbol];
|
|
956
|
-
if (id === undefined)
|
|
957
|
-
throw new Error(`Unknown bifrost token symbol ${symbol}`);
|
|
958
|
-
return id;
|
|
959
|
-
}
|
|
960
|
-
/** reads one CurrencyId from a ScaleReader */
|
|
961
|
-
function bifrostReadCurrencyId(r) {
|
|
962
|
-
const start = r.offset;
|
|
963
|
-
const variant = BIFROST_VARIANT_NAMES[r.u8()];
|
|
964
|
-
let out = { variant, raw: Buffer.alloc(0) };
|
|
965
|
-
switch (variant) {
|
|
966
|
-
case 'Native':
|
|
967
|
-
case 'VToken':
|
|
968
|
-
case 'Token':
|
|
969
|
-
case 'Stable':
|
|
970
|
-
case 'VSToken': {
|
|
971
|
-
const id = r.u8();
|
|
972
|
-
const symbol = BIFROST_TOKEN_SYMBOLS[id];
|
|
973
|
-
out = { variant, raw: out.raw, id, symbol, human: { [variant]: symbol !== null && symbol !== void 0 ? symbol : String(id) } };
|
|
974
|
-
break;
|
|
975
|
-
}
|
|
976
|
-
case 'Token2':
|
|
977
|
-
case 'VToken2':
|
|
978
|
-
case 'VSToken2': {
|
|
979
|
-
const id = r.u8();
|
|
980
|
-
out = { variant, raw: out.raw, id, symbol: BIFROST_TOKEN2_SYMBOLS[id], human: { [variant]: String(id) } };
|
|
981
|
-
break;
|
|
982
|
-
}
|
|
983
|
-
case 'VSBond':
|
|
984
|
-
r.u8();
|
|
985
|
-
r.u32();
|
|
986
|
-
r.u32();
|
|
987
|
-
r.u32();
|
|
988
|
-
break; // (TokenSymbol, ParaId, LeasePeriod, LeasePeriod)
|
|
989
|
-
case 'VSBond2':
|
|
990
|
-
r.u8();
|
|
991
|
-
r.u32();
|
|
992
|
-
r.u32();
|
|
993
|
-
r.u32();
|
|
994
|
-
break; // (TokenId, ParaId, LeasePeriod, LeasePeriod)
|
|
995
|
-
case 'LPToken':
|
|
996
|
-
r.u8();
|
|
997
|
-
r.u8();
|
|
998
|
-
r.u8();
|
|
999
|
-
r.u8();
|
|
1000
|
-
break; // (TokenSymbol, u8, TokenSymbol, u8)
|
|
1001
|
-
case 'ForeignAsset':
|
|
1002
|
-
case 'StableLpToken':
|
|
1003
|
-
case 'BLP': {
|
|
1004
|
-
const id = r.u32();
|
|
1005
|
-
out = { variant, raw: out.raw, id, human: { [variant]: String(id) } };
|
|
1006
|
-
break;
|
|
1007
|
-
}
|
|
1008
|
-
case 'Lend': {
|
|
1009
|
-
const id = r.u8();
|
|
1010
|
-
out = { variant, raw: out.raw, id, human: { [variant]: String(id) } };
|
|
1011
|
-
break;
|
|
1012
|
-
}
|
|
1013
|
-
default: throw new Error(`Unknown bifrost CurrencyId variant ${variant}`);
|
|
1014
|
-
}
|
|
1015
|
-
out.raw = Buffer.from(r.buf.subarray(start, r.offset));
|
|
1016
|
-
return out;
|
|
1017
|
-
}
|
|
1018
|
-
/** Bifrost CurrencyId SCALE codec (bifrost-primitives) */
|
|
1019
|
-
exports.bifrost = {
|
|
1020
|
-
CURRENCY: BIFROST_CURRENCY,
|
|
1021
|
-
VARIANT_NAMES: BIFROST_VARIANT_NAMES,
|
|
1022
|
-
TOKEN_SYMBOLS: BIFROST_TOKEN_SYMBOLS,
|
|
1023
|
-
TOKEN_IDS: BIFROST_TOKEN_IDS,
|
|
1024
|
-
TOKEN2_SYMBOLS: BIFROST_TOKEN2_SYMBOLS,
|
|
1025
|
-
/** `encodeCurrencyId('Token', 'KSM')` / `encodeCurrencyId('VToken2', 0)` -> 2 byte SCALE CurrencyId */
|
|
1026
|
-
encodeCurrencyId(variant, payload) {
|
|
1027
|
-
const p = typeof payload === 'string' && Number.isNaN(Number(payload)) ? bifrostTokenId(payload) : Number(payload);
|
|
1028
|
-
return bifrostEncode(variant, p);
|
|
1029
|
-
},
|
|
1030
|
-
// explicit `Buffer` return types: newer @types/node infers `Buffer<ArrayBufferLike>`, which breaks
|
|
1031
|
-
// consumers compiling against an older @types/node
|
|
1032
|
-
token: (symbol) => bifrostEncode('Token', bifrostTokenId(symbol)),
|
|
1033
|
-
vToken: (symbol) => bifrostEncode('VToken', bifrostTokenId(symbol)),
|
|
1034
|
-
vsToken: (symbol) => bifrostEncode('VSToken', bifrostTokenId(symbol)),
|
|
1035
|
-
native: (symbol) => bifrostEncode('Native', bifrostTokenId(symbol)),
|
|
1036
|
-
stable: (symbol) => bifrostEncode('Stable', bifrostTokenId(symbol)),
|
|
1037
|
-
token2: (id) => bifrostEncode('Token2', id),
|
|
1038
|
-
vToken2: (id) => bifrostEncode('VToken2', id),
|
|
1039
|
-
vsToken2: (id) => bifrostEncode('VSToken2', id),
|
|
1040
|
-
readCurrencyId: bifrostReadCurrencyId,
|
|
1041
|
-
decodeCurrencyId: (value) => bifrostReadCurrencyId(new ScaleReader(value)),
|
|
1042
|
-
};
|