@anywalletkit/wallet-near 0.0.0-stage → 0.1.3
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/LICENSE +202 -0
- package/README.md +104 -2
- package/dist/chunk-2GH6U3LB.js +693 -0
- package/dist/chunk-2GH6U3LB.js.map +1 -0
- package/dist/history.cjs +538 -0
- package/dist/history.cjs.map +1 -0
- package/dist/history.d.cts +216 -0
- package/dist/history.d.ts +216 -0
- package/dist/history.js +25 -0
- package/dist/history.js.map +1 -0
- package/dist/index.cjs +1749 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +677 -0
- package/dist/index.d.ts +677 -0
- package/dist/index.js +1097 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -3
|
@@ -0,0 +1,693 @@
|
|
|
1
|
+
// src/rpc.ts
|
|
2
|
+
import { NetworkError } from "@anywalletkit/core";
|
|
3
|
+
|
|
4
|
+
// src/errors.ts
|
|
5
|
+
var UnsafeTransactionError = class extends Error {
|
|
6
|
+
code;
|
|
7
|
+
constructor(code, message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "UnsafeTransactionError";
|
|
10
|
+
this.code = code;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
var SimulationError = class extends Error {
|
|
14
|
+
reason;
|
|
15
|
+
constructor(reason) {
|
|
16
|
+
super(`Transaction preflight failed: ${reason}`);
|
|
17
|
+
this.name = "SimulationError";
|
|
18
|
+
this.reason = reason;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var NearRpcError = class extends Error {
|
|
22
|
+
method;
|
|
23
|
+
errorName;
|
|
24
|
+
cause;
|
|
25
|
+
constructor(method, error) {
|
|
26
|
+
const causeName = error.cause?.name;
|
|
27
|
+
super(`${method}: ${error.name ?? "error"}${causeName ? ` / ${causeName}` : ""}${error.message ? ` \u2014 ${error.message}` : ""}`);
|
|
28
|
+
this.name = "NearRpcError";
|
|
29
|
+
this.method = method;
|
|
30
|
+
this.errorName = causeName ?? error.name;
|
|
31
|
+
this.cause = error;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// src/rpc.ts
|
|
36
|
+
function toBase64(bytes) {
|
|
37
|
+
if (typeof btoa === "function") {
|
|
38
|
+
let s = "";
|
|
39
|
+
for (let i = 0; i < bytes.length; i += 32768) s += String.fromCharCode.apply(null, Array.from(bytes.subarray(i, i + 32768)));
|
|
40
|
+
return btoa(s);
|
|
41
|
+
}
|
|
42
|
+
return globalThis.Buffer.from(bytes).toString("base64");
|
|
43
|
+
}
|
|
44
|
+
function fromBase64(s) {
|
|
45
|
+
if (typeof atob === "function") {
|
|
46
|
+
const bin = atob(s);
|
|
47
|
+
const out = new Uint8Array(bin.length);
|
|
48
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
return new Uint8Array(globalThis.Buffer.from(s, "base64"));
|
|
52
|
+
}
|
|
53
|
+
function httpTransport(url, headers) {
|
|
54
|
+
let id = 0;
|
|
55
|
+
return async (method, params) => {
|
|
56
|
+
const res = await fetch(url, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: { "content-type": "application/json", accept: "application/json", ...headers },
|
|
59
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: String(++id), method, params })
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok) throw new NetworkError(`${method}: HTTP ${res.status}`, { provider: url });
|
|
62
|
+
const json = await res.json();
|
|
63
|
+
if (json.error) throw new NearRpcError(method, json.error);
|
|
64
|
+
return json.result;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
var isDefinitive = (e) => e instanceof NearRpcError && !/TIMEOUT|INTERNAL|UNAVAILABLE|NO_SYNCED/i.test(e.errorName ?? "");
|
|
68
|
+
function createClient(config) {
|
|
69
|
+
if (config.provider === void 0) return void 0;
|
|
70
|
+
const list = (Array.isArray(config.provider) ? config.provider : [config.provider]).map(
|
|
71
|
+
(p) => typeof p === "string" ? httpTransport(p, config.headers) : p
|
|
72
|
+
);
|
|
73
|
+
if (list.length === 0) throw new Error("The 'provider' option cannot be set to an empty list.");
|
|
74
|
+
if (list.length === 1) return list[0];
|
|
75
|
+
const attempts = list.length + (config.retries ?? 3);
|
|
76
|
+
return async (method, params) => {
|
|
77
|
+
let lastError;
|
|
78
|
+
for (let i = 0; i < attempts; i++) {
|
|
79
|
+
try {
|
|
80
|
+
return await list[i % list.length](method, params);
|
|
81
|
+
} catch (e) {
|
|
82
|
+
if (isDefinitive(e)) throw e;
|
|
83
|
+
lastError = e;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
throw new NetworkError(`All NEAR providers failed for ${method}`, { cause: lastError });
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
var UNKNOWN = /UNKNOWN_ACCOUNT|UNKNOWN_ACCESS_KEY|UNKNOWN_TRANSACTION|does not exist/i;
|
|
90
|
+
var NearRpc = class {
|
|
91
|
+
constructor(fetch2) {
|
|
92
|
+
this.fetch = fetch2;
|
|
93
|
+
}
|
|
94
|
+
fetch;
|
|
95
|
+
/** `undefined` when the account does not exist. */
|
|
96
|
+
async viewAccount(accountId) {
|
|
97
|
+
try {
|
|
98
|
+
return await this.fetch("query", { request_type: "view_account", finality: "final", account_id: accountId });
|
|
99
|
+
} catch (e) {
|
|
100
|
+
if (e instanceof NearRpcError && UNKNOWN.test(e.errorName ?? e.message)) return void 0;
|
|
101
|
+
throw e;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/** `undefined` when the key is not on the account. */
|
|
105
|
+
async viewAccessKey(accountId, publicKey) {
|
|
106
|
+
try {
|
|
107
|
+
return await this.fetch("query", { request_type: "view_access_key", finality: "final", account_id: accountId, public_key: publicKey });
|
|
108
|
+
} catch (e) {
|
|
109
|
+
if (e instanceof NearRpcError && UNKNOWN.test(e.errorName ?? e.message)) return void 0;
|
|
110
|
+
throw e;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** View call; the JSON-decoded return value (`null` for an empty result). */
|
|
114
|
+
async callFunction(contract, method, args = {}) {
|
|
115
|
+
const r = await this.fetch("query", {
|
|
116
|
+
request_type: "call_function",
|
|
117
|
+
finality: "final",
|
|
118
|
+
account_id: contract,
|
|
119
|
+
method_name: method,
|
|
120
|
+
args_base64: toBase64(new TextEncoder().encode(JSON.stringify(args)))
|
|
121
|
+
});
|
|
122
|
+
if (r.error) throw new NearRpcError("query", { name: "HANDLER_ERROR", message: r.error, cause: { name: "CONTRACT_EXECUTION_ERROR" } });
|
|
123
|
+
const text = new TextDecoder().decode(Uint8Array.from(r.result ?? []));
|
|
124
|
+
if (!text.length) return null;
|
|
125
|
+
return JSON.parse(text);
|
|
126
|
+
}
|
|
127
|
+
async latestBlockHash() {
|
|
128
|
+
const b = await this.fetch("block", { finality: "final" });
|
|
129
|
+
if (!b.header?.hash) throw new NetworkError("block: no header hash in the response");
|
|
130
|
+
return b.header.hash;
|
|
131
|
+
}
|
|
132
|
+
async gasPrice() {
|
|
133
|
+
const r = await this.fetch("gas_price", [null]);
|
|
134
|
+
if (!r.gas_price) throw new NetworkError("gas_price: no price in the response");
|
|
135
|
+
return BigInt(r.gas_price);
|
|
136
|
+
}
|
|
137
|
+
async sendTx(signedTxBase64, waitUntil = "EXECUTED_OPTIMISTIC") {
|
|
138
|
+
return await this.fetch("send_tx", { signed_tx_base64: signedTxBase64, wait_until: waitUntil });
|
|
139
|
+
}
|
|
140
|
+
/** `undefined` when the node does not know the transaction. */
|
|
141
|
+
async txStatus(hash, senderId) {
|
|
142
|
+
try {
|
|
143
|
+
return await this.fetch("tx", { tx_hash: hash, sender_account_id: senderId, wait_until: "NONE" });
|
|
144
|
+
} catch (e) {
|
|
145
|
+
if (e instanceof NearRpcError && UNKNOWN.test(e.errorName ?? e.message)) return void 0;
|
|
146
|
+
throw e;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
function failureOf(status) {
|
|
151
|
+
if (!status || !("Failure" in status)) return void 0;
|
|
152
|
+
const f = status.Failure;
|
|
153
|
+
try {
|
|
154
|
+
const json = JSON.stringify(f);
|
|
155
|
+
const m = /"ExecutionError":"([^"]+)"/.exec(json) ?? /"error_message":"([^"]+)"/.exec(json) ?? /"kind":(\{[^}]*\})/.exec(json);
|
|
156
|
+
return m?.[1] ?? json.slice(0, 300);
|
|
157
|
+
} catch {
|
|
158
|
+
return String(f);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function outcomeFailed(o) {
|
|
162
|
+
const top = failureOf(o.status);
|
|
163
|
+
if (top) return top;
|
|
164
|
+
for (const r of o.receipts_outcome ?? []) {
|
|
165
|
+
const f = failureOf(r.outcome?.status);
|
|
166
|
+
if (f) return f;
|
|
167
|
+
}
|
|
168
|
+
return void 0;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// src/types.ts
|
|
172
|
+
var CAIP2 = { mainnet: "near:mainnet", testnet: "near:testnet" };
|
|
173
|
+
var YOCTO = 10n ** 24n;
|
|
174
|
+
var TGAS = 10n ** 12n;
|
|
175
|
+
var MAX_GAS = 300n * TGAS;
|
|
176
|
+
var STORAGE_PRICE_PER_BYTE = 10n ** 19n;
|
|
177
|
+
var ONE_YOCTO = 1n;
|
|
178
|
+
var FT_TRANSFER_GAS = 30n * TGAS;
|
|
179
|
+
var STORAGE_DEPOSIT_GAS = 10n * TGAS;
|
|
180
|
+
var IMPLICIT_ACCOUNT_MIN_DEPOSIT = 2n * 10n ** 21n;
|
|
181
|
+
|
|
182
|
+
// src/history.ts
|
|
183
|
+
var HistoryUnavailableError = class extends Error {
|
|
184
|
+
chain;
|
|
185
|
+
reason;
|
|
186
|
+
attempts;
|
|
187
|
+
constructor(chain, reason, attempts = []) {
|
|
188
|
+
super(`History unavailable for ${chain}: ${reason}`);
|
|
189
|
+
this.name = "HistoryUnavailableError";
|
|
190
|
+
this.chain = chain;
|
|
191
|
+
this.reason = reason;
|
|
192
|
+
this.attempts = attempts;
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
var DEFAULT_LIMIT = 25;
|
|
196
|
+
var MAX_LIMIT = 25;
|
|
197
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
198
|
+
var ONE_YOCTO2 = 1n;
|
|
199
|
+
var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
200
|
+
function b64encode(s) {
|
|
201
|
+
let out = "";
|
|
202
|
+
for (let i = 0; i < s.length; i += 3) {
|
|
203
|
+
const c = [s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)];
|
|
204
|
+
for (const x of c) if (x > 255) throw new Error("cursor must be ASCII");
|
|
205
|
+
const n = c[0] << 16 | (c[1] || 0) << 8 | (c[2] || 0);
|
|
206
|
+
out += B64[n >> 18 & 63] + B64[n >> 12 & 63] + (Number.isNaN(c[1]) ? "=" : B64[n >> 6 & 63]) + (Number.isNaN(c[2]) ? "=" : B64[n & 63]);
|
|
207
|
+
}
|
|
208
|
+
return out;
|
|
209
|
+
}
|
|
210
|
+
function b64decode(s) {
|
|
211
|
+
const clean = s.replace(/[^A-Za-z0-9+/]/g, "");
|
|
212
|
+
let out = "";
|
|
213
|
+
for (let i = 0; i < clean.length; i += 4) {
|
|
214
|
+
const c = [0, 1, 2, 3].map((k) => i + k < clean.length ? B64.indexOf(clean[i + k]) : -1);
|
|
215
|
+
if (c[0] < 0 || c[1] < 0) throw new Error("bad base64");
|
|
216
|
+
const n = c[0] << 18 | c[1] << 12 | (c[2] < 0 ? 0 : c[2]) << 6 | (c[3] < 0 ? 0 : c[3]);
|
|
217
|
+
out += String.fromCharCode(n >> 16 & 255);
|
|
218
|
+
if (c[2] >= 0) out += String.fromCharCode(n >> 8 & 255);
|
|
219
|
+
if (c[3] >= 0) out += String.fromCharCode(n & 255);
|
|
220
|
+
}
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
function encodeCursor(c) {
|
|
224
|
+
return b64encode(JSON.stringify(c));
|
|
225
|
+
}
|
|
226
|
+
function decodeCursor(s) {
|
|
227
|
+
let parsed;
|
|
228
|
+
try {
|
|
229
|
+
parsed = JSON.parse(b64decode(s));
|
|
230
|
+
} catch {
|
|
231
|
+
throw new Error("@anywalletkit/wallet-near: malformed history cursor");
|
|
232
|
+
}
|
|
233
|
+
const c = parsed;
|
|
234
|
+
const ok = (v) => v === null || typeof v === "string";
|
|
235
|
+
if (!c || c.v !== 1 || !ok(c.tx) || !ok(c.ft)) throw new Error("@anywalletkit/wallet-near: malformed history cursor");
|
|
236
|
+
return { v: 1, tx: c.tx, ft: c.ft };
|
|
237
|
+
}
|
|
238
|
+
var TokenBucket = class {
|
|
239
|
+
constructor(rate, burst = Math.max(2, Math.ceil(rate))) {
|
|
240
|
+
this.rate = rate;
|
|
241
|
+
this.burst = burst;
|
|
242
|
+
this.tokens = burst;
|
|
243
|
+
}
|
|
244
|
+
rate;
|
|
245
|
+
burst;
|
|
246
|
+
tokens;
|
|
247
|
+
last = Date.now();
|
|
248
|
+
chain = Promise.resolve();
|
|
249
|
+
acquire() {
|
|
250
|
+
const next = this.chain.then(() => this.take());
|
|
251
|
+
this.chain = next.catch(() => void 0);
|
|
252
|
+
return next;
|
|
253
|
+
}
|
|
254
|
+
refill() {
|
|
255
|
+
const now = Date.now();
|
|
256
|
+
this.tokens = Math.min(this.burst, this.tokens + (now - this.last) / 1e3 * this.rate);
|
|
257
|
+
this.last = now;
|
|
258
|
+
}
|
|
259
|
+
async take() {
|
|
260
|
+
this.refill();
|
|
261
|
+
if (this.tokens >= 1) {
|
|
262
|
+
this.tokens -= 1;
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
await new Promise((r) => setTimeout(r, Math.ceil((1 - this.tokens) / this.rate * 1e3)));
|
|
266
|
+
this.refill();
|
|
267
|
+
this.tokens = Math.max(0, this.tokens - 1);
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
function timeoutSignal(ms) {
|
|
271
|
+
const ctor = globalThis.AbortSignal;
|
|
272
|
+
return typeof ctor?.timeout === "function" ? ctor.timeout(ms) : void 0;
|
|
273
|
+
}
|
|
274
|
+
function parseJsonPreservingBigInts(text) {
|
|
275
|
+
let out = "";
|
|
276
|
+
let i = 0;
|
|
277
|
+
let inString = false;
|
|
278
|
+
while (i < text.length) {
|
|
279
|
+
const ch = text[i];
|
|
280
|
+
if (inString) {
|
|
281
|
+
out += ch;
|
|
282
|
+
if (ch === "\\") {
|
|
283
|
+
out += text[i + 1] ?? "";
|
|
284
|
+
i += 2;
|
|
285
|
+
continue;
|
|
286
|
+
}
|
|
287
|
+
if (ch === '"') inString = false;
|
|
288
|
+
i++;
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
if (ch === '"') {
|
|
292
|
+
inString = true;
|
|
293
|
+
out += ch;
|
|
294
|
+
i++;
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (ch === "-" || ch >= "0" && ch <= "9") {
|
|
298
|
+
let j = i;
|
|
299
|
+
if (text[j] === "-") j++;
|
|
300
|
+
while (j < text.length && text[j] >= "0" && text[j] <= "9") j++;
|
|
301
|
+
const next = text[j];
|
|
302
|
+
const isInteger = next !== "." && next !== "e" && next !== "E";
|
|
303
|
+
if (isInteger) {
|
|
304
|
+
const tok = text.slice(i, j);
|
|
305
|
+
out += tok.replace("-", "").length >= 16 ? `"${tok}"` : tok;
|
|
306
|
+
i = j;
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
while (j < text.length && /[0-9.eE+-]/.test(text[j])) j++;
|
|
310
|
+
out += text.slice(i, j);
|
|
311
|
+
i = j;
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
out += ch;
|
|
315
|
+
i++;
|
|
316
|
+
}
|
|
317
|
+
return JSON.parse(out);
|
|
318
|
+
}
|
|
319
|
+
function big(v, approx) {
|
|
320
|
+
if (typeof v === "bigint") return v;
|
|
321
|
+
if (typeof v === "string" && /^-?\d+$/.test(v)) return BigInt(v);
|
|
322
|
+
if (typeof v === "number" && Number.isFinite(v)) {
|
|
323
|
+
if (!Number.isSafeInteger(v)) approx.value = true;
|
|
324
|
+
return BigInt(Math.trunc(v));
|
|
325
|
+
}
|
|
326
|
+
return void 0;
|
|
327
|
+
}
|
|
328
|
+
var nsToSeconds = (ts) => {
|
|
329
|
+
if (typeof ts === "string" && /^\d+$/.test(ts)) return Number(BigInt(ts) / 1000000000n);
|
|
330
|
+
if (typeof ts === "number") return Math.floor(ts / 1e9);
|
|
331
|
+
return 0;
|
|
332
|
+
};
|
|
333
|
+
function ftTransfer(row, approx) {
|
|
334
|
+
const meta = row.ft ?? row.ft_meta;
|
|
335
|
+
if (!meta?.contract) return void 0;
|
|
336
|
+
const delta = big(row.delta_amount, approx);
|
|
337
|
+
if (delta === void 0 || delta === 0n) return void 0;
|
|
338
|
+
const other = row.involved_account_id ?? meta.contract;
|
|
339
|
+
const t = { token: meta.contract, from: delta < 0n ? row.affected_account_id : other, to: delta < 0n ? other : row.affected_account_id, amount: delta < 0n ? -delta : delta, standard: "nep141" };
|
|
340
|
+
if (typeof meta.symbol === "string") t.symbol = meta.symbol;
|
|
341
|
+
if (typeof meta.decimals === "number") t.decimals = meta.decimals;
|
|
342
|
+
return t;
|
|
343
|
+
}
|
|
344
|
+
function foldActions(actions, from, to, fold, approx) {
|
|
345
|
+
for (const a of actions ?? []) {
|
|
346
|
+
const deposit = big(a.deposit, approx) ?? 0n;
|
|
347
|
+
if (a.action === "TRANSFER") {
|
|
348
|
+
if (deposit > 0n) fold.transfers.push({ token: null, from, to, amount: deposit });
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (a.action === "DELEGATE_ACTION") continue;
|
|
352
|
+
const method = a.action === "FUNCTION_CALL" ? a.method ?? "function_call" : a.action.toLowerCase();
|
|
353
|
+
fold.programs.push(method);
|
|
354
|
+
if (a.action === "FUNCTION_CALL" && deposit > 0n && deposit !== ONE_YOCTO2) fold.transfers.push({ token: null, from, to, amount: deposit });
|
|
355
|
+
fold.call ??= { to, method, programs: fold.programs };
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function mapNearblocksGroup(chain, address, receipts, ft) {
|
|
359
|
+
const approx = { value: false };
|
|
360
|
+
const rows = [...receipts].sort((a, b) => BigInt(a.id) < BigInt(b.id) ? -1 : BigInt(a.id) > BigInt(b.id) ? 1 : 0);
|
|
361
|
+
const real = rows.filter((r) => r.predecessor_account_id !== "system" && (r.receipt_kind ?? "ACTION") === "ACTION");
|
|
362
|
+
const fold = { transfers: [], programs: [] };
|
|
363
|
+
const ordered = [...real.filter((r) => r.receiver_account_id !== address), ...real.filter((r) => r.receiver_account_id === address)];
|
|
364
|
+
for (const r of ordered) foldActions(r.actions, r.predecessor_account_id, r.receiver_account_id, fold, approx);
|
|
365
|
+
for (const f of ft) {
|
|
366
|
+
const t = ftTransfer(f, approx);
|
|
367
|
+
if (t) fold.transfers.push(t);
|
|
368
|
+
}
|
|
369
|
+
const head = ordered[0] ?? rows[0] ?? ft[0];
|
|
370
|
+
const hash = head?.transaction_hash ?? "";
|
|
371
|
+
const from = ordered[0]?.predecessor_account_id ?? (ft.length ? ftTransfer(ft[0], approx)?.from ?? address : address);
|
|
372
|
+
const involves = (t) => t.from === address || t.to === address;
|
|
373
|
+
const primary = fold.transfers.find((t) => t.token !== null && involves(t)) ?? fold.transfers.find(involves) ?? fold.transfers[0];
|
|
374
|
+
const to = fold.call?.to ?? primary?.to ?? ordered[0]?.receiver_account_id ?? null;
|
|
375
|
+
let nativeValue = 0n;
|
|
376
|
+
for (const t of fold.transfers) if (t.token === null && t.from === from) nativeValue += t.amount;
|
|
377
|
+
const statuses = [...rows.map((r) => r.outcomes?.status), ...ft.map((r) => r.outcomes?.status)].filter((s) => typeof s === "boolean");
|
|
378
|
+
const status = statuses.length === 0 ? "confirmed" : statuses.every(Boolean) ? "confirmed" : "failed";
|
|
379
|
+
const feeSrc = rows.find((r) => r.outcomes_agg?.transaction_fee != null)?.outcomes_agg?.transaction_fee;
|
|
380
|
+
const fee = big(feeSrc, approx);
|
|
381
|
+
const heights = [...rows, ...ft].map((r) => r.block?.block_height).filter((h) => typeof h === "number");
|
|
382
|
+
const raw = { receipts: rows, ft };
|
|
383
|
+
if (approx.value) raw.approximate = true;
|
|
384
|
+
const out = {
|
|
385
|
+
chain,
|
|
386
|
+
hash,
|
|
387
|
+
time: nsToSeconds(head?.block_timestamp),
|
|
388
|
+
status,
|
|
389
|
+
address,
|
|
390
|
+
from,
|
|
391
|
+
to,
|
|
392
|
+
nativeValue,
|
|
393
|
+
transfers: fold.transfers,
|
|
394
|
+
raw
|
|
395
|
+
};
|
|
396
|
+
if (fee !== void 0) out.fee = fee;
|
|
397
|
+
if (fold.call) out.call = fold.call;
|
|
398
|
+
if (heights.length) out.block = BigInt(Math.min(...heights));
|
|
399
|
+
return out;
|
|
400
|
+
}
|
|
401
|
+
function mapNearblocksTxn(chain, address, txn) {
|
|
402
|
+
const approx = { value: false };
|
|
403
|
+
const fold = { transfers: [], programs: [] };
|
|
404
|
+
foldActions(txn.actions, txn.signer_account_id, txn.receiver_account_id, fold, approx);
|
|
405
|
+
for (const r of txn.receipts ?? []) {
|
|
406
|
+
for (const f of r.fts ?? []) {
|
|
407
|
+
const delta = big(f.delta_amount, approx);
|
|
408
|
+
if (delta === void 0 || delta >= 0n) continue;
|
|
409
|
+
const t = ftTransfer(f, approx);
|
|
410
|
+
if (t) fold.transfers.push(t);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
const from = txn.signer_account_id;
|
|
414
|
+
const involves = (t) => t.from === address || t.to === address;
|
|
415
|
+
const primary = fold.transfers.find((t) => t.token !== null && involves(t)) ?? fold.transfers.find(involves) ?? fold.transfers[0];
|
|
416
|
+
let nativeValue = 0n;
|
|
417
|
+
for (const t of fold.transfers) if (t.token === null && t.from === from) nativeValue += t.amount;
|
|
418
|
+
const fee = big(txn.outcomes_agg?.transaction_fee, approx);
|
|
419
|
+
const raw = { receipts: [], ft: [], txn };
|
|
420
|
+
if (approx.value) raw.approximate = true;
|
|
421
|
+
const out = {
|
|
422
|
+
chain,
|
|
423
|
+
hash: txn.transaction_hash,
|
|
424
|
+
time: nsToSeconds(txn.block_timestamp),
|
|
425
|
+
status: txn.outcomes?.status === false ? "failed" : "confirmed",
|
|
426
|
+
address,
|
|
427
|
+
from,
|
|
428
|
+
to: fold.call?.to ?? primary?.to ?? txn.receiver_account_id,
|
|
429
|
+
nativeValue,
|
|
430
|
+
transfers: fold.transfers,
|
|
431
|
+
raw
|
|
432
|
+
};
|
|
433
|
+
if (fee !== void 0) out.fee = fee;
|
|
434
|
+
if (fold.call) out.call = fold.call;
|
|
435
|
+
if (typeof txn.block?.block_height === "number") out.block = BigInt(txn.block.block_height);
|
|
436
|
+
return out;
|
|
437
|
+
}
|
|
438
|
+
var utf8 = (bytes) => {
|
|
439
|
+
let s = "";
|
|
440
|
+
for (let i = 0; i < bytes.length; ) {
|
|
441
|
+
const b0 = bytes[i++];
|
|
442
|
+
let cp;
|
|
443
|
+
if (b0 < 128) cp = b0;
|
|
444
|
+
else if (b0 < 224) cp = (b0 & 31) << 6 | bytes[i++] & 63;
|
|
445
|
+
else if (b0 < 240) cp = (b0 & 15) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63;
|
|
446
|
+
else cp = (b0 & 7) << 18 | (bytes[i++] & 63) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63;
|
|
447
|
+
s += String.fromCodePoint(cp);
|
|
448
|
+
}
|
|
449
|
+
return s;
|
|
450
|
+
};
|
|
451
|
+
function mapRpcTxStatus(chain, address, r, base) {
|
|
452
|
+
const tx = r.transaction;
|
|
453
|
+
const transfers = [];
|
|
454
|
+
const programs = [];
|
|
455
|
+
let call;
|
|
456
|
+
const walk = (actions, from2, to) => {
|
|
457
|
+
for (const a of actions ?? []) {
|
|
458
|
+
if (a.Transfer) {
|
|
459
|
+
const d = BigInt(a.Transfer.deposit);
|
|
460
|
+
if (d > 0n) transfers.push({ token: null, from: from2, to, amount: d });
|
|
461
|
+
} else if (a.FunctionCall) {
|
|
462
|
+
const d = BigInt(a.FunctionCall.deposit || "0");
|
|
463
|
+
programs.push(a.FunctionCall.method_name);
|
|
464
|
+
if (d > 0n && d !== ONE_YOCTO2) transfers.push({ token: null, from: from2, to, amount: d });
|
|
465
|
+
call ??= { to, method: a.FunctionCall.method_name, programs };
|
|
466
|
+
} else if (a.Delegate) {
|
|
467
|
+
walk(a.Delegate.delegate_action.actions, a.Delegate.delegate_action.sender_id, a.Delegate.delegate_action.receiver_id);
|
|
468
|
+
} else {
|
|
469
|
+
const name = Object.keys(a)[0];
|
|
470
|
+
if (name) {
|
|
471
|
+
const method = name.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
|
|
472
|
+
programs.push(method);
|
|
473
|
+
call ??= { to, method, programs };
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
if (tx) walk(tx.actions, tx.signer_id, tx.receiver_id);
|
|
479
|
+
let fee = 0n;
|
|
480
|
+
const burnt = r.transaction_outcome?.outcome?.tokens_burnt;
|
|
481
|
+
if (burnt) fee += BigInt(burnt);
|
|
482
|
+
let failed = false;
|
|
483
|
+
for (const ro of r.receipts_outcome ?? []) {
|
|
484
|
+
const o = ro.outcome;
|
|
485
|
+
if (!o) continue;
|
|
486
|
+
if (o.tokens_burnt) fee += BigInt(o.tokens_burnt);
|
|
487
|
+
if (o.status && "Failure" in o.status) failed = true;
|
|
488
|
+
const token = o.executor_id;
|
|
489
|
+
for (const log of o.logs ?? []) {
|
|
490
|
+
if (!token) continue;
|
|
491
|
+
const legacy = /^Transfer (\d+) from (\S+) to (\S+)$/.exec(log);
|
|
492
|
+
if (legacy) {
|
|
493
|
+
transfers.push({ token, from: legacy[2], to: legacy[3], amount: BigInt(legacy[1]), standard: "nep141" });
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
if (!log.startsWith("EVENT_JSON:")) continue;
|
|
497
|
+
let ev;
|
|
498
|
+
try {
|
|
499
|
+
ev = JSON.parse(log.slice("EVENT_JSON:".length));
|
|
500
|
+
} catch {
|
|
501
|
+
continue;
|
|
502
|
+
}
|
|
503
|
+
if (ev.standard !== "nep141") continue;
|
|
504
|
+
for (const d of ev.data ?? []) {
|
|
505
|
+
if (!d.amount || !/^\d+$/.test(d.amount)) continue;
|
|
506
|
+
if (ev.event === "ft_transfer" && d.old_owner_id && d.new_owner_id) transfers.push({ token, from: d.old_owner_id, to: d.new_owner_id, amount: BigInt(d.amount), standard: "nep141" });
|
|
507
|
+
else if (ev.event === "ft_mint" && d.owner_id) transfers.push({ token, from: token, to: d.owner_id, amount: BigInt(d.amount), standard: "nep141" });
|
|
508
|
+
else if (ev.event === "ft_burn" && d.owner_id) transfers.push({ token, from: d.owner_id, to: token, amount: BigInt(d.amount), standard: "nep141" });
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (r.status && "Failure" in r.status) failed = true;
|
|
513
|
+
for (const t of transfers) {
|
|
514
|
+
const known = base?.transfers.find((x) => x.token === t.token && (x.symbol !== void 0 || x.decimals !== void 0));
|
|
515
|
+
if (known?.symbol !== void 0) t.symbol = known.symbol;
|
|
516
|
+
if (known?.decimals !== void 0) t.decimals = known.decimals;
|
|
517
|
+
}
|
|
518
|
+
const from = tx?.signer_id ?? base?.from ?? address;
|
|
519
|
+
const involves = (t) => t.from === address || t.to === address;
|
|
520
|
+
const primary = transfers.find((t) => t.token !== null && involves(t)) ?? transfers.find(involves) ?? transfers[0];
|
|
521
|
+
let nativeValue = 0n;
|
|
522
|
+
for (const t of transfers) if (t.token === null && t.from === from) nativeValue += t.amount;
|
|
523
|
+
const raw = { ...base?.raw ?? { receipts: [], ft: [] }, rpc: r };
|
|
524
|
+
delete raw.approximate;
|
|
525
|
+
const out = {
|
|
526
|
+
chain,
|
|
527
|
+
hash: tx?.hash ?? base?.hash ?? "",
|
|
528
|
+
time: base?.time ?? 0,
|
|
529
|
+
status: failed ? "failed" : "confirmed",
|
|
530
|
+
address,
|
|
531
|
+
from,
|
|
532
|
+
to: call?.to ?? primary?.to ?? tx?.receiver_id ?? base?.to ?? null,
|
|
533
|
+
nativeValue,
|
|
534
|
+
transfers,
|
|
535
|
+
fee,
|
|
536
|
+
raw
|
|
537
|
+
};
|
|
538
|
+
if (call) out.call = call;
|
|
539
|
+
if (base?.block !== void 0) out.block = base.block;
|
|
540
|
+
return out;
|
|
541
|
+
}
|
|
542
|
+
function decodeFunctionCallArgs(args) {
|
|
543
|
+
try {
|
|
544
|
+
return JSON.parse(utf8(fromBase64(args)));
|
|
545
|
+
} catch {
|
|
546
|
+
return void 0;
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
function nearExplorerTxUrl(hash, network = "mainnet") {
|
|
550
|
+
return `https://${network === "testnet" ? "testnet." : ""}nearblocks.io/txns/${hash}`;
|
|
551
|
+
}
|
|
552
|
+
function createNearHistory(options = {}) {
|
|
553
|
+
const network = options.network ?? "mainnet";
|
|
554
|
+
const chain = CAIP2[network] ?? CAIP2.mainnet;
|
|
555
|
+
const base = (options.nearblocksUrl ?? (network === "testnet" ? "https://api-testnet.nearblocks.io" : "https://api.nearblocks.io")).replace(/\/+$/, "");
|
|
556
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
557
|
+
if (typeof fetchFn !== "function") throw new Error("@anywalletkit/wallet-near: no global fetch; pass `fetch` in the options");
|
|
558
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
559
|
+
const bucket = new TokenBucket(options.rateLimit ?? (options.apiKey ? 5 : 0.1));
|
|
560
|
+
async function get(path) {
|
|
561
|
+
await bucket.acquire();
|
|
562
|
+
const url = `${base}${path}`;
|
|
563
|
+
let res;
|
|
564
|
+
try {
|
|
565
|
+
const signal = timeoutSignal(timeoutMs);
|
|
566
|
+
res = await fetchFn(url, { headers: { accept: "application/json", ...options.apiKey ? { authorization: `Bearer ${options.apiKey}` } : {} }, ...signal ? { signal } : {} });
|
|
567
|
+
} catch (e) {
|
|
568
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
569
|
+
throw new HistoryUnavailableError(chain, `${path}: ${msg}`, [`nearblocks: ${msg}`]);
|
|
570
|
+
}
|
|
571
|
+
const text = await res.text();
|
|
572
|
+
let body;
|
|
573
|
+
try {
|
|
574
|
+
body = parseJsonPreservingBigInts(text);
|
|
575
|
+
} catch {
|
|
576
|
+
body = void 0;
|
|
577
|
+
}
|
|
578
|
+
if (!res.ok) {
|
|
579
|
+
const msg = body?.message ?? `HTTP ${res.status}`;
|
|
580
|
+
throw new HistoryUnavailableError(chain, `${path}: ${msg}`, [`nearblocks: HTTP ${res.status} ${msg}`]);
|
|
581
|
+
}
|
|
582
|
+
return body;
|
|
583
|
+
}
|
|
584
|
+
async function rpcTxStatus(hash, signer) {
|
|
585
|
+
if (!options.rpcUrl) return void 0;
|
|
586
|
+
const signal = timeoutSignal(timeoutMs);
|
|
587
|
+
const res = await fetchFn(options.rpcUrl, {
|
|
588
|
+
method: "POST",
|
|
589
|
+
headers: { "content-type": "application/json", accept: "application/json" },
|
|
590
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: "1", method: "EXPERIMENTAL_tx_status", params: { tx_hash: hash, sender_account_id: signer, wait_until: "NONE" } }),
|
|
591
|
+
...signal ? { signal } : {}
|
|
592
|
+
});
|
|
593
|
+
const json = JSON.parse(await res.text());
|
|
594
|
+
if (!res.ok || json.error || !json.result) return void 0;
|
|
595
|
+
return json.result;
|
|
596
|
+
}
|
|
597
|
+
return {
|
|
598
|
+
chain,
|
|
599
|
+
async listActivity(address, query = {}) {
|
|
600
|
+
const limit = Math.min(MAX_LIMIT, Math.max(1, Math.floor(query.limit ?? DEFAULT_LIMIT)));
|
|
601
|
+
const cursor = query.cursor ? decodeCursor(query.cursor) : { v: 1, tx: "", ft: "" };
|
|
602
|
+
const acct = encodeURIComponent(address);
|
|
603
|
+
const perPage = Math.min(MAX_LIMIT, limit * 2);
|
|
604
|
+
const txRows = cursor.tx === null ? [] : (await get(`/v1/account/${acct}/txns?per_page=${perPage}&order=desc${cursor.tx ? `&cursor=${encodeURIComponent(cursor.tx)}` : ""}`))?.txns ?? [];
|
|
605
|
+
const ftRows = cursor.ft === null ? [] : (await get(`/v1/account/${acct}/ft-txns?per_page=${limit}&order=desc${cursor.ft ? `&cursor=${encodeURIComponent(cursor.ft)}` : ""}`))?.txns ?? [];
|
|
606
|
+
const key = (r) => BigInt(typeof r.block_timestamp === "string" ? r.block_timestamp : Math.trunc(r.block_timestamp));
|
|
607
|
+
const all = [...txRows.map((r) => ({ k: key(r), h: r.transaction_hash })), ...ftRows.map((r) => ({ k: key(r), h: r.transaction_hash }))];
|
|
608
|
+
all.sort((a, b) => a.k > b.k ? -1 : a.k < b.k ? 1 : 0);
|
|
609
|
+
const chosen = /* @__PURE__ */ new Set();
|
|
610
|
+
let boundary;
|
|
611
|
+
for (const e of all) {
|
|
612
|
+
if (chosen.has(e.h)) continue;
|
|
613
|
+
if (chosen.size >= limit && boundary !== void 0 && e.k < boundary) break;
|
|
614
|
+
chosen.add(e.h);
|
|
615
|
+
if (chosen.size === limit) boundary = e.k;
|
|
616
|
+
}
|
|
617
|
+
const consume = (rows, asked, wasAt, pos) => {
|
|
618
|
+
if (wasAt === null) return { used: [], next: null };
|
|
619
|
+
let n = 0;
|
|
620
|
+
while (n < rows.length && chosen.has(rows[n].transaction_hash)) n++;
|
|
621
|
+
const used = rows.slice(0, n);
|
|
622
|
+
if (rows.length < asked && n === rows.length) return { used, next: null };
|
|
623
|
+
return { used, next: n > 0 ? pos(used[n - 1]) : wasAt };
|
|
624
|
+
};
|
|
625
|
+
const txC = consume(txRows, perPage, cursor.tx, (r) => r.id);
|
|
626
|
+
const ftC = consume(ftRows, limit, cursor.ft, (r) => r.event_index);
|
|
627
|
+
const nextTx = txC.next, nextFt = ftC.next;
|
|
628
|
+
const groups = /* @__PURE__ */ new Map();
|
|
629
|
+
for (const h of chosen) groups.set(h, { receipts: [], ft: [] });
|
|
630
|
+
for (const r of txC.used) groups.get(r.transaction_hash).receipts.push(r);
|
|
631
|
+
for (const r of ftC.used) groups.get(r.transaction_hash).ft.push(r);
|
|
632
|
+
let items = [...groups.entries()].map(([, g]) => mapNearblocksGroup(chain, address, g.receipts, g.ft)).filter((t) => t.hash);
|
|
633
|
+
items.sort((a, b) => b.time - a.time);
|
|
634
|
+
let more = nextTx !== null || nextFt !== null;
|
|
635
|
+
if (query.since !== void 0) {
|
|
636
|
+
const since = query.since;
|
|
637
|
+
if (items.some((t) => t.time < since)) more = false;
|
|
638
|
+
items = items.filter((t) => t.time >= since);
|
|
639
|
+
}
|
|
640
|
+
const page = { items };
|
|
641
|
+
if (more) page.cursor = encodeCursor({ v: 1, tx: nextTx, ft: nextFt });
|
|
642
|
+
return page;
|
|
643
|
+
},
|
|
644
|
+
async getTransaction(hash, address) {
|
|
645
|
+
const body = await get(`/v1/txns/${encodeURIComponent(hash)}`);
|
|
646
|
+
const txn = body?.txns?.[0];
|
|
647
|
+
if (!txn) return void 0;
|
|
648
|
+
const base2 = mapNearblocksTxn(chain, address, txn);
|
|
649
|
+
if (!options.rpcUrl) return base2;
|
|
650
|
+
try {
|
|
651
|
+
const r = await rpcTxStatus(hash, txn.signer_account_id);
|
|
652
|
+
return r ? mapRpcTxStatus(chain, address, r, base2) : base2;
|
|
653
|
+
} catch {
|
|
654
|
+
return base2;
|
|
655
|
+
}
|
|
656
|
+
},
|
|
657
|
+
explorerTxUrl(hash) {
|
|
658
|
+
return nearExplorerTxUrl(hash, network);
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
export {
|
|
664
|
+
CAIP2,
|
|
665
|
+
YOCTO,
|
|
666
|
+
TGAS,
|
|
667
|
+
MAX_GAS,
|
|
668
|
+
STORAGE_PRICE_PER_BYTE,
|
|
669
|
+
ONE_YOCTO,
|
|
670
|
+
FT_TRANSFER_GAS,
|
|
671
|
+
STORAGE_DEPOSIT_GAS,
|
|
672
|
+
IMPLICIT_ACCOUNT_MIN_DEPOSIT,
|
|
673
|
+
UnsafeTransactionError,
|
|
674
|
+
SimulationError,
|
|
675
|
+
NearRpcError,
|
|
676
|
+
toBase64,
|
|
677
|
+
fromBase64,
|
|
678
|
+
createClient,
|
|
679
|
+
NearRpc,
|
|
680
|
+
failureOf,
|
|
681
|
+
outcomeFailed,
|
|
682
|
+
HistoryUnavailableError,
|
|
683
|
+
encodeCursor,
|
|
684
|
+
decodeCursor,
|
|
685
|
+
parseJsonPreservingBigInts,
|
|
686
|
+
mapNearblocksGroup,
|
|
687
|
+
mapNearblocksTxn,
|
|
688
|
+
mapRpcTxStatus,
|
|
689
|
+
decodeFunctionCallArgs,
|
|
690
|
+
nearExplorerTxUrl,
|
|
691
|
+
createNearHistory
|
|
692
|
+
};
|
|
693
|
+
//# sourceMappingURL=chunk-2GH6U3LB.js.map
|