@defillama/sdk 5.0.240 → 5.0.244
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/build/Balances.d.ts +139 -0
- package/build/Balances.js +363 -0
- package/build/ChainApi.d.ts +142 -0
- package/build/ChainApi.js +310 -0
- package/build/abi/abi2.d.ts +5 -0
- package/build/abi/abi2.js +215 -0
- package/build/abi/cachedABIs.d.ts +4 -0
- package/build/abi/cachedABIs.js +8 -0
- package/build/abi/convertResults.d.ts +5 -0
- package/build/abi/convertResults.js +60 -0
- package/build/abi/index.d.ts +31 -0
- package/build/abi/index.js +327 -0
- package/build/abi/multicall.d.ts +23 -0
- package/build/abi/multicall.js +383 -0
- package/build/abi/multicall3.d.ts +7 -0
- package/build/abi/multicall3.js +405 -0
- package/build/abi/rpcCall.d.ts +4 -0
- package/build/abi/rpcCall.js +62 -0
- package/build/abi/tron.d.ts +33 -0
- package/build/abi/tron.js +118 -0
- package/build/api.d.ts +10 -0
- package/build/api.js +45 -0
- package/build/api2.d.ts +5 -0
- package/build/api2.js +41 -0
- package/build/chains/algorand.d.ts +277 -0
- package/build/chains/algorand.js +618 -0
- package/build/chains/aptos.d.ts +269 -0
- package/build/chains/aptos.js +700 -0
- package/build/chains/cardano.d.ts +242 -0
- package/build/chains/cardano.js +407 -0
- package/build/chains/cosmos.d.ts +252 -0
- package/build/chains/cosmos.js +623 -0
- package/build/chains/icp.d.ts +235 -0
- package/build/chains/icp.js +1040 -0
- package/build/chains/index.d.ts +23 -0
- package/build/chains/index.js +59 -0
- package/build/chains/near.d.ts +192 -0
- package/build/chains/near.js +446 -0
- package/build/chains/rpc.d.ts +125 -0
- package/build/chains/rpc.js +332 -0
- package/build/chains/starknet.d.ts +205 -0
- package/build/chains/starknet.js +886 -0
- package/build/chains/stellar.d.ts +410 -0
- package/build/chains/stellar.js +1082 -0
- package/build/chains/substrate.d.ts +333 -0
- package/build/chains/substrate.js +1042 -0
- package/build/chains/sui.d.ts +392 -0
- package/build/chains/sui.js +1213 -0
- package/build/chains/svm.d.ts +340 -0
- package/build/chains/svm.js +764 -0
- package/build/chains/tezos.d.ts +225 -0
- package/build/chains/tezos.js +412 -0
- package/build/chains/ton.d.ts +353 -0
- package/build/chains/ton.js +788 -0
- package/build/chains/tron.d.ts +45 -0
- package/build/chains/tron.js +110 -0
- package/build/chains/utxo.d.ts +210 -0
- package/build/chains/utxo.js +678 -0
- package/build/chains/xrpl.d.ts +179 -0
- package/build/chains/xrpl.js +467 -0
- package/build/computeTVL/blocks.d.ts +1 -0
- package/build/computeTVL/blocks.js +12 -0
- package/build/computeTVL/humanizeNumber.d.ts +1 -0
- package/build/computeTVL/humanizeNumber.js +19 -0
- package/build/erc20/index.d.ts +31 -0
- package/build/erc20/index.js +56 -0
- package/build/eth/index.d.ts +22 -0
- package/build/eth/index.js +118 -0
- package/build/general.d.ts +5 -0
- package/build/general.js +20 -0
- package/build/generalUtil.d.ts +8 -0
- package/build/generalUtil.js +73 -0
- package/build/index.d.ts +33 -0
- package/build/index.js +75 -0
- package/build/providers.json +1 -0
- package/build/types.d.ts +76 -0
- package/build/types.js +2 -0
- package/build/util/LlamaProvider.d.ts +46 -0
- package/build/util/LlamaProvider.js +343 -0
- package/build/util/blocks.d.ts +36 -0
- package/build/util/blocks.js +500 -0
- package/build/util/cache.d.ts +45 -0
- package/build/util/cache.js +309 -0
- package/build/util/callStats.d.ts +74 -0
- package/build/util/callStats.js +385 -0
- package/build/util/chainUtils/data.json +1459 -0
- package/build/util/chainUtils/index.d.ts +11 -0
- package/build/util/chainUtils/index.js +136 -0
- package/build/util/coins.d.ts +19 -0
- package/build/util/coins.js +124 -0
- package/build/util/common.d.ts +34 -0
- package/build/util/common.js +376 -0
- package/build/util/computeTVL.d.ts +19 -0
- package/build/util/computeTVL.js +102 -0
- package/build/util/cosmos.d.ts +1 -0
- package/build/util/cosmos.js +8 -0
- package/build/util/debugLog.d.ts +4 -0
- package/build/util/debugLog.js +18 -0
- package/build/util/discord.d.ts +1 -0
- package/build/util/discord.js +33 -0
- package/build/util/elastic.d.ts +43 -0
- package/build/util/elastic.js +113 -0
- package/build/util/env.d.ts +20 -0
- package/build/util/env.js +176 -0
- package/build/util/graph.d.ts +8 -0
- package/build/util/graph.js +50 -0
- package/build/util/index.d.ts +32 -0
- package/build/util/index.js +227 -0
- package/build/util/indexer.compatibility.d.ts +6 -0
- package/build/util/indexer.compatibility.js +64 -0
- package/build/util/indexer.d.ts +92 -0
- package/build/util/indexer.js +854 -0
- package/build/util/indexerSql.d.ts +9 -0
- package/build/util/indexerSql.js +102 -0
- package/build/util/internal-cache.d.ts +11 -0
- package/build/util/internal-cache.js +77 -0
- package/build/util/logs.d.ts +58 -0
- package/build/util/logs.decode.shared.d.ts +8 -0
- package/build/util/logs.decode.shared.js +289 -0
- package/build/util/logs.js +432 -0
- package/build/util/promisePool.d.ts +8 -0
- package/build/util/promisePool.js +31 -0
- package/build/util/r2.d.ts +4 -0
- package/build/util/r2.js +52 -0
- package/build/util/removeRedundantRPCs.d.ts +1 -0
- package/build/util/removeRedundantRPCs.js +49 -0
- package/build/util/transactions.d.ts +35 -0
- package/build/util/transactions.js +22 -0
- package/build/util/updateChainLabels.d.ts +1 -0
- package/build/util/updateChainLabels.js +5 -0
- package/build/util/updateProviderList.d.ts +1 -0
- package/build/util/updateProviderList.js +275 -0
- package/package.json +3 -2
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.viewFunction = exports.NearRpcError = exports.DEFAULT_ENDPOINTS = exports.CHAIN = void 0;
|
|
7
|
+
exports.encodeArgs = encodeArgs;
|
|
8
|
+
exports.decodeResult = decodeResult;
|
|
9
|
+
exports.isNearAccountId = isNearAccountId;
|
|
10
|
+
exports.isImplicitAccountId = isImplicitAccountId;
|
|
11
|
+
exports.yoctoToNear = yoctoToNear;
|
|
12
|
+
exports.getEndpoints = getEndpoints;
|
|
13
|
+
exports.shouldRetry = shouldRetry;
|
|
14
|
+
exports.rpc = rpc;
|
|
15
|
+
exports.query = query;
|
|
16
|
+
exports.viewAccount = viewAccount;
|
|
17
|
+
exports.getBalance = getBalance;
|
|
18
|
+
exports.call = call;
|
|
19
|
+
exports.getTokenBalance = getTokenBalance;
|
|
20
|
+
exports.getTokenMetadata = getTokenMetadata;
|
|
21
|
+
exports.getTokenTotalSupply = getTokenTotalSupply;
|
|
22
|
+
exports.getBlock = getBlock;
|
|
23
|
+
exports.getLatestBlock = getLatestBlock;
|
|
24
|
+
exports.getBlockAtTimestamp = getBlockAtTimestamp;
|
|
25
|
+
exports.getAccessKeys = getAccessKeys;
|
|
26
|
+
exports.viewState = viewState;
|
|
27
|
+
/**
|
|
28
|
+
* NEAR JSON-RPC client.
|
|
29
|
+
*
|
|
30
|
+
* Replaces (and unifies) the ad-hoc NEAR helpers spread across the llama repos:
|
|
31
|
+
* - DefiLlama-Adapters `projects/helper/chain/near.js` (endpoints, failover, view_account, call, getTokenBalance)
|
|
32
|
+
* - dimension-adapters `helpers/near.ts` (nearView: 8 attempts, exponential backoff + jitter, round-robin cursor, p-limit(3))
|
|
33
|
+
* - peggedassets-server `src/adapters/peggedAssets/helper/near.js` (call)
|
|
34
|
+
* - server/coins `src/adapters/yield/apiDerivs.ts` (inline `ft_price` call_function)
|
|
35
|
+
*
|
|
36
|
+
* TVL specific pieces of the adapters helper (coingecko `tokenMapping`, `transformAddress`,
|
|
37
|
+
* `sumSingleBalance`, `sumTokens`, `addTokenBalances`) are intentionally NOT ported: this module
|
|
38
|
+
* only talks to the chain and returns raw chain data.
|
|
39
|
+
*
|
|
40
|
+
* Transport: every request goes through a shared p-limit(3) limiter (`NEAR_RPC_CONCURRENCY`
|
|
41
|
+
* overrides it), rotates over the endpoint list with a module level round-robin cursor and
|
|
42
|
+
* retries transient failures up to 8 times with exponential backoff (400ms * 2^attempt + jitter).
|
|
43
|
+
* `NEAR_RPC` (comma separated) overrides the default endpoint list.
|
|
44
|
+
*
|
|
45
|
+
* Usage: `sdk.chains.near.call({ contract: 'wrap.near', method: 'ft_metadata' })`
|
|
46
|
+
*/
|
|
47
|
+
const axios_1 = __importDefault(require("axios"));
|
|
48
|
+
const debugLog_1 = require("../util/debugLog");
|
|
49
|
+
const rpc_1 = require("./rpc");
|
|
50
|
+
exports.CHAIN = 'near';
|
|
51
|
+
// rpc.mainnet.near.org is deprecated (429 heavy) and near.lava.build answers 410 (discontinued);
|
|
52
|
+
// both are kept last as a fallback only, the transport rotates past them on failure.
|
|
53
|
+
exports.DEFAULT_ENDPOINTS = [
|
|
54
|
+
'https://free.rpc.fastnear.com',
|
|
55
|
+
'https://near.drpc.org',
|
|
56
|
+
'https://rpc.mainnet.near.org',
|
|
57
|
+
'https://near.lava.build',
|
|
58
|
+
];
|
|
59
|
+
const MAX_ATTEMPTS = 8;
|
|
60
|
+
const BASE_DELAY = 400;
|
|
61
|
+
const CONCURRENCY = 3;
|
|
62
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
63
|
+
const YOCTO_PER_NEAR = BigInt('1000000000000000000000000');
|
|
64
|
+
/**
|
|
65
|
+
* Error returned by a NEAR node (`error` member of the JSON-RPC response, or the
|
|
66
|
+
* `result.error` string of a failed `call_function`). Extends `JsonRpcError` so the
|
|
67
|
+
* shared retry helper keeps it intact. `nodeError` is the raw error object, `cause`
|
|
68
|
+
* mirrors NEAR's structured `error.cause.name` (e.g. `UNKNOWN_ACCOUNT`, `CONTRACT_EXECUTION_ERROR`).
|
|
69
|
+
*/
|
|
70
|
+
class NearRpcError extends rpc_1.JsonRpcError {
|
|
71
|
+
constructor(method, error, endpoint, label) {
|
|
72
|
+
var _a;
|
|
73
|
+
super(method, error);
|
|
74
|
+
this.name = 'NearRpcError';
|
|
75
|
+
this.nodeError = error;
|
|
76
|
+
this.errorName = error === null || error === void 0 ? void 0 : error.name;
|
|
77
|
+
this.cause = (_a = error === null || error === void 0 ? void 0 : error.cause) === null || _a === void 0 ? void 0 : _a.name;
|
|
78
|
+
this.endpoint = endpoint;
|
|
79
|
+
this.message = `NEAR ${label !== null && label !== void 0 ? label : method} failed: ${formatNodeError(error)}`;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.NearRpcError = NearRpcError;
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
// pure helpers
|
|
85
|
+
// ---------------------------------------------------------------------------
|
|
86
|
+
/**
|
|
87
|
+
* Encode `call_function` arguments to base64. Objects are JSON serialised, a
|
|
88
|
+
* `Buffer`/`Uint8Array` is taken as raw bytes, a string is assumed to be base64 already
|
|
89
|
+
* (pass `''` for methods without arguments), `undefined`/`null` become `{}`.
|
|
90
|
+
*/
|
|
91
|
+
function encodeArgs(args) {
|
|
92
|
+
if (args === undefined || args === null)
|
|
93
|
+
args = {};
|
|
94
|
+
if (typeof args === 'string')
|
|
95
|
+
return args;
|
|
96
|
+
if (Buffer.isBuffer(args) || args instanceof Uint8Array)
|
|
97
|
+
return Buffer.from(args).toString('base64');
|
|
98
|
+
return Buffer.from(JSON.stringify(args)).toString('base64');
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Decode the `result` byte array of a `call_function` response. Returns the parsed JSON
|
|
102
|
+
* when the payload is JSON, otherwise the utf8 string (empty payload -> `''`).
|
|
103
|
+
*/
|
|
104
|
+
function decodeResult(bytes) {
|
|
105
|
+
if (!bytes)
|
|
106
|
+
return '';
|
|
107
|
+
const text = Buffer.from(bytes).toString('utf8');
|
|
108
|
+
if (!text.length)
|
|
109
|
+
return '';
|
|
110
|
+
try {
|
|
111
|
+
return JSON.parse(text);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return text;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// https://nomicon.io/DataStructures/Account#account-id-rules
|
|
118
|
+
const ACCOUNT_ID_REGEX = /^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/;
|
|
119
|
+
/** True for a syntactically valid NEAR account id (named accounts and 64-hex implicit accounts) */
|
|
120
|
+
function isNearAccountId(str) {
|
|
121
|
+
if (typeof str !== 'string')
|
|
122
|
+
return false;
|
|
123
|
+
if (str.length < 2 || str.length > 64)
|
|
124
|
+
return false;
|
|
125
|
+
return ACCOUNT_ID_REGEX.test(str);
|
|
126
|
+
}
|
|
127
|
+
/** True for a 64 char hex implicit account id */
|
|
128
|
+
function isImplicitAccountId(str) {
|
|
129
|
+
return typeof str === 'string' && /^[0-9a-f]{64}$/.test(str);
|
|
130
|
+
}
|
|
131
|
+
/** yoctoNEAR (string/bigint) -> NEAR as a number (loses precision below 1e-15 NEAR, fine for reporting) */
|
|
132
|
+
function yoctoToNear(amount) {
|
|
133
|
+
const value = typeof amount === 'bigint' ? amount : BigInt(String(amount).split('.')[0] || '0');
|
|
134
|
+
const whole = value / YOCTO_PER_NEAR;
|
|
135
|
+
const frac = value % YOCTO_PER_NEAR;
|
|
136
|
+
return Number(whole) + Number(frac) / 1e24;
|
|
137
|
+
}
|
|
138
|
+
function formatNodeError(error) {
|
|
139
|
+
var _a, _b;
|
|
140
|
+
if (!error)
|
|
141
|
+
return 'unknown error';
|
|
142
|
+
if (typeof error === 'string')
|
|
143
|
+
return error;
|
|
144
|
+
const parts = [];
|
|
145
|
+
if (error.message)
|
|
146
|
+
parts.push(String(error.message));
|
|
147
|
+
if (error.name && error.name !== error.message)
|
|
148
|
+
parts.push(String(error.name));
|
|
149
|
+
if ((_a = error.cause) === null || _a === void 0 ? void 0 : _a.name)
|
|
150
|
+
parts.push(String(error.cause.name));
|
|
151
|
+
if (((_b = error.cause) === null || _b === void 0 ? void 0 : _b.info) && Object.keys(error.cause.info).length)
|
|
152
|
+
parts.push(JSON.stringify(error.cause.info));
|
|
153
|
+
if (error.data !== undefined && error.data !== null)
|
|
154
|
+
parts.push(typeof error.data === 'string' ? error.data : JSON.stringify(error.data));
|
|
155
|
+
return parts.join(' | ').slice(0, 1000);
|
|
156
|
+
}
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// transport
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
/** Endpoint list: `NEAR_RPC` env (comma separated) or `DEFAULT_ENDPOINTS` */
|
|
161
|
+
function getEndpoints() {
|
|
162
|
+
return (0, rpc_1.getEndpoints)(exports.CHAIN, exports.DEFAULT_ENDPOINTS);
|
|
163
|
+
}
|
|
164
|
+
let rpcCursor = 0;
|
|
165
|
+
let requestId = 0;
|
|
166
|
+
// node side errors that another endpoint / a later attempt may resolve
|
|
167
|
+
const RETRYABLE_CAUSES = new Set(['INTERNAL_ERROR', 'TIMEOUT_ERROR', 'NO_SYNCED_BLOCKS', 'UNAVAILABLE_SHARD', 'UNKNOWN_BLOCK', 'GARBAGE_COLLECTED_BLOCK', 'NOT_SYNCED_YET']);
|
|
168
|
+
/**
|
|
169
|
+
* Decide whether a failed attempt should be retried. Transport/HTTP level failures
|
|
170
|
+
* (network errors, timeouts, 4xx/5xx from a gateway - e.g. the 410 of a discontinued
|
|
171
|
+
* provider, 429 rate limits) always rotate to the next endpoint; node errors only when
|
|
172
|
+
* another node might have the data (missing/garbage collected block, node not synced,
|
|
173
|
+
* internal error). Contract level errors (unknown account, method not found, execution
|
|
174
|
+
* failure) are deterministic and fail fast.
|
|
175
|
+
*/
|
|
176
|
+
function shouldRetry(e) {
|
|
177
|
+
var _a;
|
|
178
|
+
if ((0, rpc_1.isRateLimitError)(e))
|
|
179
|
+
return true;
|
|
180
|
+
if (e instanceof NearRpcError) {
|
|
181
|
+
if (e.cause && RETRYABLE_CAUSES.has(e.cause))
|
|
182
|
+
return true;
|
|
183
|
+
if (e.errorName === 'INTERNAL_ERROR')
|
|
184
|
+
return true;
|
|
185
|
+
// legacy (unstructured) error format: `Server error` + data string
|
|
186
|
+
const data = typeof ((_a = e.nodeError) === null || _a === void 0 ? void 0 : _a.data) === 'string' ? e.nodeError.data : '';
|
|
187
|
+
if (/not synced|unavailable|timeout|internal error|garbage collected|unknown block|DB Not Found/i.test(data))
|
|
188
|
+
return true;
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
if (e instanceof rpc_1.JsonRpcError)
|
|
192
|
+
return false;
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Raw NEAR JSON-RPC call. Returns `result`, throws `NearRpcError` when the node answers with
|
|
197
|
+
* an `error`. Rotates endpoints (round-robin), retries with exponential backoff and runs
|
|
198
|
+
* under the shared concurrency limiter.
|
|
199
|
+
*/
|
|
200
|
+
async function rpc(method, params = {}, options = {}) {
|
|
201
|
+
var _a, _b;
|
|
202
|
+
const explicit = (0, rpc_1.toEndpointList)(options.endpoints);
|
|
203
|
+
const endpoints = explicit.length ? explicit : getEndpoints();
|
|
204
|
+
const start = rpcCursor++;
|
|
205
|
+
const body = { jsonrpc: '2.0', id: `llama-sdk-${++requestId}`, method, params };
|
|
206
|
+
const timeout = (_a = options.timeout) !== null && _a !== void 0 ? _a : DEFAULT_TIMEOUT;
|
|
207
|
+
const label = (_b = options.label) !== null && _b !== void 0 ? _b : `${exports.CHAIN} ${method}${(params === null || params === void 0 ? void 0 : params.request_type) ? `/${params.request_type}` : ''}`;
|
|
208
|
+
const run = () => {
|
|
209
|
+
var _a, _b, _c, _d, _e;
|
|
210
|
+
return (0, rpc_1.withRetry)(async (attempt) => {
|
|
211
|
+
const endpoint = endpoints[(start + attempt) % endpoints.length];
|
|
212
|
+
const { data } = await axios_1.default.post(endpoint, body, { timeout });
|
|
213
|
+
if (data === undefined || data === null || typeof data !== 'object')
|
|
214
|
+
throw new Error(`${label}: unexpected response from ${(0, rpc_1.shortUrl)(endpoint)}`);
|
|
215
|
+
if (data.error) {
|
|
216
|
+
const err = new NearRpcError(method, data.error, endpoint, label);
|
|
217
|
+
(0, debugLog_1.debugLog)(`[chains.near] ${label} node error from ${(0, rpc_1.shortUrl)(endpoint)}: ${err.message}`);
|
|
218
|
+
throw err;
|
|
219
|
+
}
|
|
220
|
+
return data.result;
|
|
221
|
+
}, {
|
|
222
|
+
retries: (_a = options.retries) !== null && _a !== void 0 ? _a : MAX_ATTEMPTS,
|
|
223
|
+
delay: (_b = options.delay) !== null && _b !== void 0 ? _b : BASE_DELAY,
|
|
224
|
+
backoff: (_c = options.backoff) !== null && _c !== void 0 ? _c : 2,
|
|
225
|
+
maxDelay: (_d = options.maxDelay) !== null && _d !== void 0 ? _d : 10000,
|
|
226
|
+
shouldRetry: (_e = options.shouldRetry) !== null && _e !== void 0 ? _e : shouldRetry,
|
|
227
|
+
label,
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
if (options.skipLimiter)
|
|
231
|
+
return run();
|
|
232
|
+
return (0, rpc_1.getLimiter)(exports.CHAIN.toUpperCase(), CONCURRENCY)(run);
|
|
233
|
+
}
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// query helpers
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
function blockParams(blockId, finality) {
|
|
238
|
+
if (blockId !== undefined && blockId !== null && blockId !== '')
|
|
239
|
+
return { block_id: normaliseBlockId(blockId) };
|
|
240
|
+
return { finality: finality !== null && finality !== void 0 ? finality : 'final' };
|
|
241
|
+
}
|
|
242
|
+
function normaliseBlockId(blockId) {
|
|
243
|
+
if (typeof blockId === 'string' && /^\d+$/.test(blockId))
|
|
244
|
+
return +blockId;
|
|
245
|
+
return blockId;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* The `query` RPC method. Defaults to `finality: 'final'`; when `block_id`/`blockId` is
|
|
249
|
+
* given the finality is omitted (the node rejects requests carrying both).
|
|
250
|
+
*/
|
|
251
|
+
async function query(params, options) {
|
|
252
|
+
const { blockId, block_id, finality, ...rest } = params;
|
|
253
|
+
const target = blockParams(block_id !== null && block_id !== void 0 ? block_id : blockId, finality);
|
|
254
|
+
return rpc('query', { ...rest, ...target }, options);
|
|
255
|
+
}
|
|
256
|
+
/** `view_account`: raw account view (`amount` and `locked` are yoctoNEAR strings) */
|
|
257
|
+
async function viewAccount({ account, blockId }, options) {
|
|
258
|
+
return query({ request_type: 'view_account', account_id: account, blockId }, options);
|
|
259
|
+
}
|
|
260
|
+
/** Native balance (`amount`, yoctoNEAR string, excludes `locked` stake) */
|
|
261
|
+
async function getBalance({ account, blockId }, options) {
|
|
262
|
+
const { amount } = await viewAccount({ account, blockId }, options);
|
|
263
|
+
return amount;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* View call (`call_function`). `args` are JSON serialised and base64 encoded, the returned
|
|
267
|
+
* byte array is decoded to JSON (or a string). Throws `NearRpcError` carrying the node
|
|
268
|
+
* error message on failure (unknown account/method, execution error, ...).
|
|
269
|
+
*/
|
|
270
|
+
async function call({ contract, method, args, blockId }, options) {
|
|
271
|
+
const label = `${contract}.${method}`;
|
|
272
|
+
const res = await query({
|
|
273
|
+
request_type: 'call_function',
|
|
274
|
+
account_id: contract,
|
|
275
|
+
method_name: method,
|
|
276
|
+
args_base64: encodeArgs(args),
|
|
277
|
+
blockId,
|
|
278
|
+
}, { label: `${exports.CHAIN} ${label}`, ...options });
|
|
279
|
+
// older nodes report contract execution failures inside `result` with a 200 status
|
|
280
|
+
if (res === null || res === void 0 ? void 0 : res.error)
|
|
281
|
+
throw new NearRpcError('query', { message: 'Contract execution error', cause: { name: 'CONTRACT_EXECUTION_ERROR' }, data: res.error }, undefined, label);
|
|
282
|
+
if (!Array.isArray(res === null || res === void 0 ? void 0 : res.result))
|
|
283
|
+
throw new Error(`NEAR ${label}: unexpected response shape`);
|
|
284
|
+
return decodeResult(res.result);
|
|
285
|
+
}
|
|
286
|
+
/** Alias of `call` */
|
|
287
|
+
exports.viewFunction = call;
|
|
288
|
+
/**
|
|
289
|
+
* `ft_balance_of` raw balance string. Mirrors the adapters helper: when the token
|
|
290
|
+
* contract does not exist the balance is `'0'` instead of an error.
|
|
291
|
+
*/
|
|
292
|
+
async function getTokenBalance({ token, account, blockId }, options) {
|
|
293
|
+
try {
|
|
294
|
+
const res = await call({ contract: token, method: 'ft_balance_of', args: { account_id: account }, blockId }, options);
|
|
295
|
+
return String(res !== null && res !== void 0 ? res : '0');
|
|
296
|
+
}
|
|
297
|
+
catch (e) {
|
|
298
|
+
if (isMissingAccountError(e)) {
|
|
299
|
+
(0, debugLog_1.debugLog)(`[chains.near] ${token}.ft_balance_of(${account}): token contract does not exist, returning 0`);
|
|
300
|
+
return '0';
|
|
301
|
+
}
|
|
302
|
+
throw e;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/** `ft_metadata` (NEP-148) */
|
|
306
|
+
async function getTokenMetadata({ token, blockId }, options) {
|
|
307
|
+
return call({ contract: token, method: 'ft_metadata', blockId }, options);
|
|
308
|
+
}
|
|
309
|
+
/** `ft_total_supply` raw string */
|
|
310
|
+
async function getTokenTotalSupply({ token, blockId }, options) {
|
|
311
|
+
const res = await call({ contract: token, method: 'ft_total_supply', blockId }, options);
|
|
312
|
+
return String(res);
|
|
313
|
+
}
|
|
314
|
+
function isMissingAccountError(e) {
|
|
315
|
+
var _a;
|
|
316
|
+
if (e instanceof NearRpcError) {
|
|
317
|
+
if (e.cause === 'UNKNOWN_ACCOUNT' || e.cause === 'NO_CONTRACT_CODE')
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
return /does not exist while viewing/i.test(String((_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : ''));
|
|
321
|
+
}
|
|
322
|
+
// ---------------------------------------------------------------------------
|
|
323
|
+
// blocks
|
|
324
|
+
// ---------------------------------------------------------------------------
|
|
325
|
+
function toBlock(raw) {
|
|
326
|
+
var _a, _b;
|
|
327
|
+
const header = raw === null || raw === void 0 ? void 0 : raw.header;
|
|
328
|
+
if (!header)
|
|
329
|
+
throw new Error('NEAR block: unexpected response shape');
|
|
330
|
+
const ns = String((_a = header.timestamp_nanosec) !== null && _a !== void 0 ? _a : header.timestamp);
|
|
331
|
+
return {
|
|
332
|
+
number: header.height,
|
|
333
|
+
timestamp: Math.floor(Number(BigInt(ns) / BigInt(1000000000))),
|
|
334
|
+
timestampNs: ns,
|
|
335
|
+
hash: header.hash,
|
|
336
|
+
prevHash: header.prev_hash,
|
|
337
|
+
header,
|
|
338
|
+
chunks: (_b = raw.chunks) !== null && _b !== void 0 ? _b : [],
|
|
339
|
+
author: raw.author,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/** `block` RPC: by height/hash (`blockId`) or by finality (default `final`) */
|
|
343
|
+
async function getBlock({ blockId, finality } = {}, options) {
|
|
344
|
+
const raw = await rpc('block', blockParams(blockId, finality), options);
|
|
345
|
+
return toBlock(raw);
|
|
346
|
+
}
|
|
347
|
+
async function getLatestBlock(options) {
|
|
348
|
+
return getBlock({}, options);
|
|
349
|
+
}
|
|
350
|
+
function isUnknownBlockError(e) {
|
|
351
|
+
var _a;
|
|
352
|
+
if (e instanceof NearRpcError) {
|
|
353
|
+
if (e.cause === 'UNKNOWN_BLOCK' || e.cause === 'GARBAGE_COLLECTED_BLOCK')
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
return /unknown block|DB Not Found|garbage collected/i.test(String((_a = e === null || e === void 0 ? void 0 : e.message) !== null && _a !== void 0 ? _a : ''));
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Fetch the block at `height`, or the next existing one (NEAR skips heights when a block
|
|
360
|
+
* producer misses its slot). Returns `undefined` when nothing exists up to `maxHeight`.
|
|
361
|
+
*/
|
|
362
|
+
async function getBlockAtOrAfter(height, maxHeight, options) {
|
|
363
|
+
const maxSteps = 200;
|
|
364
|
+
for (let h = height, i = 0; h <= maxHeight && i < maxSteps; h++, i++) {
|
|
365
|
+
try {
|
|
366
|
+
return await getBlock({ blockId: h }, { ...options, retries: 2, shouldRetry: (e) => !isUnknownBlockError(e) && shouldRetry(e) });
|
|
367
|
+
}
|
|
368
|
+
catch (e) {
|
|
369
|
+
if (!isUnknownBlockError(e))
|
|
370
|
+
throw e;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Last block produced at or before `timestamp` (unix seconds). Binary search on heights;
|
|
377
|
+
* missing heights are skipped by stepping forward. Non archival nodes only keep ~5 epochs
|
|
378
|
+
* (a few days) of history, older timestamps need an archival `NEAR_RPC`.
|
|
379
|
+
*/
|
|
380
|
+
async function getBlockAtTimestamp({ timestamp }, options) {
|
|
381
|
+
if (!timestamp || !Number.isFinite(timestamp))
|
|
382
|
+
throw new Error('NEAR getBlockAtTimestamp: invalid timestamp');
|
|
383
|
+
if (timestamp > 1e12)
|
|
384
|
+
timestamp = Math.floor(timestamp / 1000); // ms -> s
|
|
385
|
+
const latest = await getLatestBlock(options);
|
|
386
|
+
if (latest.timestamp <= timestamp)
|
|
387
|
+
return latest;
|
|
388
|
+
// bracket: guess a lower bound assuming >= 0.5s per block, widen until it precedes the target
|
|
389
|
+
let hi = latest;
|
|
390
|
+
let span = Math.max(100, Math.ceil((latest.timestamp - timestamp) * 2));
|
|
391
|
+
let lo;
|
|
392
|
+
while (true) {
|
|
393
|
+
const loHeight = Math.max(1, hi.number - span);
|
|
394
|
+
const candidate = await getBlockAtOrAfter(loHeight, hi.number, options);
|
|
395
|
+
if (!candidate)
|
|
396
|
+
throw new Error(`NEAR getBlockAtTimestamp: no block found around height ${loHeight}, node may not be archival`);
|
|
397
|
+
if (candidate.timestamp <= timestamp) {
|
|
398
|
+
lo = candidate;
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
if (loHeight <= 1)
|
|
402
|
+
throw new Error(`NEAR getBlockAtTimestamp: timestamp ${timestamp} predates the chain`);
|
|
403
|
+
hi = candidate;
|
|
404
|
+
span *= 2;
|
|
405
|
+
}
|
|
406
|
+
// binary search between lo (<= target) and hi (> target)
|
|
407
|
+
while (hi.number - lo.number > 1) {
|
|
408
|
+
const mid = lo.number + Math.floor((hi.number - lo.number) / 2);
|
|
409
|
+
const block = await getBlockAtOrAfter(mid, hi.number - 1, options);
|
|
410
|
+
if (!block) {
|
|
411
|
+
hi = { ...hi, number: mid };
|
|
412
|
+
continue;
|
|
413
|
+
} // heights (mid, hi) are all missing; shrink from the top
|
|
414
|
+
if (block.timestamp <= timestamp)
|
|
415
|
+
lo = block;
|
|
416
|
+
else
|
|
417
|
+
hi = block;
|
|
418
|
+
}
|
|
419
|
+
(0, debugLog_1.debugLog)(`[chains.near] getBlockAtTimestamp(${timestamp}) -> height ${lo.number} @ ${lo.timestamp}`);
|
|
420
|
+
return lo;
|
|
421
|
+
}
|
|
422
|
+
// ---------------------------------------------------------------------------
|
|
423
|
+
// keys / state
|
|
424
|
+
// ---------------------------------------------------------------------------
|
|
425
|
+
/** `view_access_key_list`: all access keys of an account */
|
|
426
|
+
async function getAccessKeys({ account, blockId }, options) {
|
|
427
|
+
var _a;
|
|
428
|
+
const res = await query({ request_type: 'view_access_key_list', account_id: account, blockId }, options);
|
|
429
|
+
return (_a = res === null || res === void 0 ? void 0 : res.keys) !== null && _a !== void 0 ? _a : [];
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* `view_state`: contract storage entries whose key starts with `prefix` (utf8 string, or
|
|
433
|
+
* raw bytes / base64 via `prefixBase64`). Keys and values are returned base64 and utf8 decoded.
|
|
434
|
+
*/
|
|
435
|
+
async function viewState({ contract, prefix = '', prefixBase64, blockId }, options) {
|
|
436
|
+
var _a;
|
|
437
|
+
const prefix_base64 = prefixBase64 !== null && prefixBase64 !== void 0 ? prefixBase64 : Buffer.from(prefix, 'utf8').toString('base64');
|
|
438
|
+
const res = await query({ request_type: 'view_state', account_id: contract, prefix_base64, blockId }, options);
|
|
439
|
+
const values = (_a = res === null || res === void 0 ? void 0 : res.values) !== null && _a !== void 0 ? _a : [];
|
|
440
|
+
return values.map((entry) => ({
|
|
441
|
+
key: Buffer.from(entry.key, 'base64').toString('utf8'),
|
|
442
|
+
value: Buffer.from(entry.value, 'base64').toString('utf8'),
|
|
443
|
+
keyBase64: entry.key,
|
|
444
|
+
valueBase64: entry.value,
|
|
445
|
+
}));
|
|
446
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared transport for the non-EVM chain modules under `sdk.chains.*`.
|
|
3
|
+
*
|
|
4
|
+
* Every chain module resolves its endpoints through `getEndpoints`. When
|
|
5
|
+
* `<CHAIN>_WHITELISTED_RPC` is set only those endpoints are used; otherwise the
|
|
6
|
+
* `<CHAIN>_RPC` env var (and the `SDK_` / `LLAMA_SDK_` prefixed variants read by
|
|
7
|
+
* `getEnvValue`) is tried first, followed by the module's built-in defaults.
|
|
8
|
+
* Comma separated values give a list; `jsonRpc` / `httpGet` / `httpPost` start
|
|
9
|
+
* at the first entry, rotate to the next on failure and retry with backoff.
|
|
10
|
+
*/
|
|
11
|
+
import { AxiosRequestConfig } from "axios";
|
|
12
|
+
import pLimit from "p-limit";
|
|
13
|
+
import { sleep } from "../util/common";
|
|
14
|
+
export type Endpoints = string | string[] | undefined;
|
|
15
|
+
export interface RetryOptions {
|
|
16
|
+
/** total attempts across all endpoints, default 3 */
|
|
17
|
+
retries?: number;
|
|
18
|
+
/** base delay in ms between attempts, default 500 */
|
|
19
|
+
delay?: number;
|
|
20
|
+
/** multiplier applied to delay after every failed attempt, default 2 */
|
|
21
|
+
backoff?: number;
|
|
22
|
+
/** max delay in ms, default 10_000 */
|
|
23
|
+
maxDelay?: number;
|
|
24
|
+
/** return false to abort retrying for a given error */
|
|
25
|
+
shouldRetry?: (error: any, attempt: number) => boolean;
|
|
26
|
+
/** label used in error messages */
|
|
27
|
+
label?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface HttpOptions extends RetryOptions {
|
|
30
|
+
timeout?: number;
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
/** axios `params` (query string) */
|
|
33
|
+
params?: Record<string, any>;
|
|
34
|
+
/** extra axios config merged last */
|
|
35
|
+
axiosConfig?: AxiosRequestConfig;
|
|
36
|
+
/** return the full axios response (data, headers, status) instead of only `data` */
|
|
37
|
+
withMetadata?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface JsonRpcOptions extends HttpOptions {
|
|
40
|
+
/** chain key, used to look up `<CHAIN>_RPC` and passed to `getEndpoints` */
|
|
41
|
+
chain?: string;
|
|
42
|
+
/** explicit endpoint(s); overrides `chain` */
|
|
43
|
+
endpoints?: Endpoints;
|
|
44
|
+
/** module defaults used when neither env nor `endpoints` is set */
|
|
45
|
+
defaultEndpoints?: Endpoints;
|
|
46
|
+
id?: number | string;
|
|
47
|
+
}
|
|
48
|
+
export interface JsonRpcCall {
|
|
49
|
+
method: string;
|
|
50
|
+
params?: any;
|
|
51
|
+
id?: number | string;
|
|
52
|
+
}
|
|
53
|
+
export declare function toEndpointList(value: Endpoints): string[];
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the endpoint list for a chain. `<CHAIN>_WHITELISTED_RPC` wins outright
|
|
56
|
+
* when set. Otherwise env (`<CHAIN>_RPC` or `envKey`, comma separated) comes
|
|
57
|
+
* first followed by the module defaults, then the generic fallback.
|
|
58
|
+
* Throws when nothing is configured so a misconfigured chain fails loudly.
|
|
59
|
+
*/
|
|
60
|
+
export declare function getEndpoints(chain: string | undefined, defaults?: Endpoints, { envKey, fallback, }?: {
|
|
61
|
+
envKey?: string;
|
|
62
|
+
fallback?: Endpoints;
|
|
63
|
+
}): string[];
|
|
64
|
+
/** First endpoint of `getEndpoints` */
|
|
65
|
+
export declare function getEndpoint(chain: string | undefined, defaults?: Endpoints, options?: {
|
|
66
|
+
envKey?: string;
|
|
67
|
+
fallback?: Endpoints;
|
|
68
|
+
}): string;
|
|
69
|
+
export declare function stripTrailingSlash(url: string): string;
|
|
70
|
+
export declare function joinUrl(base: string, path: string): string;
|
|
71
|
+
export declare function isRateLimitError(e: any): boolean;
|
|
72
|
+
export declare function isRetryableError(e: any): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Run `fn` with retries and exponential backoff. `fn` receives the attempt index.
|
|
75
|
+
*/
|
|
76
|
+
export declare function withRetry<T>(fn: (attempt: number) => Promise<T>, options?: RetryOptions): Promise<T>;
|
|
77
|
+
/**
|
|
78
|
+
* Lazily created per-key concurrency limiter. Concurrency can be overridden with
|
|
79
|
+
* the `<KEY>_RPC_CONCURRENCY` env var.
|
|
80
|
+
*/
|
|
81
|
+
export declare function getLimiter(key: string, concurrency?: number): pLimit.Limit;
|
|
82
|
+
export declare function sliceIntoChunks<T>(arr: T[], chunkSize?: number): T[][];
|
|
83
|
+
/**
|
|
84
|
+
* Process `items` in chunks, sequentially or with limited concurrency, keeping
|
|
85
|
+
* result order. `fn` receives one chunk and returns an array (flattened) or any value.
|
|
86
|
+
*/
|
|
87
|
+
export declare function runInChunks<T, R>(items: T[], fn: (chunk: T[], index: number) => Promise<R[] | R>, { chunkSize, concurrency, sleepTime }?: {
|
|
88
|
+
chunkSize?: number;
|
|
89
|
+
concurrency?: number;
|
|
90
|
+
sleepTime?: number;
|
|
91
|
+
}): Promise<R[]>;
|
|
92
|
+
/**
|
|
93
|
+
* GET `url` (or rotate over several base urls when `url` is an array; `path` is
|
|
94
|
+
* appended to each). Retries transient failures.
|
|
95
|
+
*/
|
|
96
|
+
export declare function httpGet(url: string | string[], options?: HttpOptions & {
|
|
97
|
+
path?: string;
|
|
98
|
+
}): Promise<any>;
|
|
99
|
+
/**
|
|
100
|
+
* POST `body` to `url` (or rotate over several urls). Retries transient failures.
|
|
101
|
+
*/
|
|
102
|
+
export declare function httpPost(url: string | string[], body: any, options?: HttpOptions & {
|
|
103
|
+
path?: string;
|
|
104
|
+
}): Promise<any>;
|
|
105
|
+
export declare class JsonRpcError extends Error {
|
|
106
|
+
code?: number;
|
|
107
|
+
data?: any;
|
|
108
|
+
method: string;
|
|
109
|
+
constructor(method: string, error: any);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Single JSON-RPC 2.0 call. Returns `result`; throws `JsonRpcError` when the node
|
|
113
|
+
* returns an `error` object. Rotates endpoints and retries on transport errors.
|
|
114
|
+
*/
|
|
115
|
+
export declare function jsonRpc(method: string, params?: any, options?: JsonRpcOptions): Promise<any>;
|
|
116
|
+
/**
|
|
117
|
+
* JSON-RPC 2.0 batch call. Returns results in call order. Individual `error`
|
|
118
|
+
* entries throw unless `permitFailure` is set, in which case they resolve to `undefined`.
|
|
119
|
+
*/
|
|
120
|
+
export declare function jsonRpcBatch(calls: JsonRpcCall[], options?: JsonRpcOptions & {
|
|
121
|
+
permitFailure?: boolean;
|
|
122
|
+
chunkSize?: number;
|
|
123
|
+
}): Promise<any[]>;
|
|
124
|
+
export declare function shortUrl(url: string): string;
|
|
125
|
+
export { sleep };
|