@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
package/dist/history.cjs
ADDED
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/history.ts
|
|
21
|
+
var history_exports = {};
|
|
22
|
+
__export(history_exports, {
|
|
23
|
+
HistoryUnavailableError: () => HistoryUnavailableError,
|
|
24
|
+
createNearHistory: () => createNearHistory,
|
|
25
|
+
decodeCursor: () => decodeCursor,
|
|
26
|
+
decodeFunctionCallArgs: () => decodeFunctionCallArgs,
|
|
27
|
+
encodeCursor: () => encodeCursor,
|
|
28
|
+
mapNearblocksGroup: () => mapNearblocksGroup,
|
|
29
|
+
mapNearblocksTxn: () => mapNearblocksTxn,
|
|
30
|
+
mapRpcTxStatus: () => mapRpcTxStatus,
|
|
31
|
+
nearExplorerTxUrl: () => nearExplorerTxUrl,
|
|
32
|
+
parseJsonPreservingBigInts: () => parseJsonPreservingBigInts
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(history_exports);
|
|
35
|
+
|
|
36
|
+
// src/rpc.ts
|
|
37
|
+
var import_core = require("@anywalletkit/core");
|
|
38
|
+
function fromBase64(s) {
|
|
39
|
+
if (typeof atob === "function") {
|
|
40
|
+
const bin = atob(s);
|
|
41
|
+
const out = new Uint8Array(bin.length);
|
|
42
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
return new Uint8Array(globalThis.Buffer.from(s, "base64"));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/types.ts
|
|
49
|
+
var CAIP2 = { mainnet: "near:mainnet", testnet: "near:testnet" };
|
|
50
|
+
var YOCTO = 10n ** 24n;
|
|
51
|
+
var TGAS = 10n ** 12n;
|
|
52
|
+
var MAX_GAS = 300n * TGAS;
|
|
53
|
+
var STORAGE_PRICE_PER_BYTE = 10n ** 19n;
|
|
54
|
+
var FT_TRANSFER_GAS = 30n * TGAS;
|
|
55
|
+
var STORAGE_DEPOSIT_GAS = 10n * TGAS;
|
|
56
|
+
var IMPLICIT_ACCOUNT_MIN_DEPOSIT = 2n * 10n ** 21n;
|
|
57
|
+
|
|
58
|
+
// src/history.ts
|
|
59
|
+
var HistoryUnavailableError = class extends Error {
|
|
60
|
+
chain;
|
|
61
|
+
reason;
|
|
62
|
+
attempts;
|
|
63
|
+
constructor(chain, reason, attempts = []) {
|
|
64
|
+
super(`History unavailable for ${chain}: ${reason}`);
|
|
65
|
+
this.name = "HistoryUnavailableError";
|
|
66
|
+
this.chain = chain;
|
|
67
|
+
this.reason = reason;
|
|
68
|
+
this.attempts = attempts;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
var DEFAULT_LIMIT = 25;
|
|
72
|
+
var MAX_LIMIT = 25;
|
|
73
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
74
|
+
var ONE_YOCTO = 1n;
|
|
75
|
+
var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
76
|
+
function b64encode(s) {
|
|
77
|
+
let out = "";
|
|
78
|
+
for (let i = 0; i < s.length; i += 3) {
|
|
79
|
+
const c = [s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)];
|
|
80
|
+
for (const x of c) if (x > 255) throw new Error("cursor must be ASCII");
|
|
81
|
+
const n = c[0] << 16 | (c[1] || 0) << 8 | (c[2] || 0);
|
|
82
|
+
out += B64[n >> 18 & 63] + B64[n >> 12 & 63] + (Number.isNaN(c[1]) ? "=" : B64[n >> 6 & 63]) + (Number.isNaN(c[2]) ? "=" : B64[n & 63]);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function b64decode(s) {
|
|
87
|
+
const clean = s.replace(/[^A-Za-z0-9+/]/g, "");
|
|
88
|
+
let out = "";
|
|
89
|
+
for (let i = 0; i < clean.length; i += 4) {
|
|
90
|
+
const c = [0, 1, 2, 3].map((k) => i + k < clean.length ? B64.indexOf(clean[i + k]) : -1);
|
|
91
|
+
if (c[0] < 0 || c[1] < 0) throw new Error("bad base64");
|
|
92
|
+
const n = c[0] << 18 | c[1] << 12 | (c[2] < 0 ? 0 : c[2]) << 6 | (c[3] < 0 ? 0 : c[3]);
|
|
93
|
+
out += String.fromCharCode(n >> 16 & 255);
|
|
94
|
+
if (c[2] >= 0) out += String.fromCharCode(n >> 8 & 255);
|
|
95
|
+
if (c[3] >= 0) out += String.fromCharCode(n & 255);
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
function encodeCursor(c) {
|
|
100
|
+
return b64encode(JSON.stringify(c));
|
|
101
|
+
}
|
|
102
|
+
function decodeCursor(s) {
|
|
103
|
+
let parsed;
|
|
104
|
+
try {
|
|
105
|
+
parsed = JSON.parse(b64decode(s));
|
|
106
|
+
} catch {
|
|
107
|
+
throw new Error("@anywalletkit/wallet-near: malformed history cursor");
|
|
108
|
+
}
|
|
109
|
+
const c = parsed;
|
|
110
|
+
const ok = (v) => v === null || typeof v === "string";
|
|
111
|
+
if (!c || c.v !== 1 || !ok(c.tx) || !ok(c.ft)) throw new Error("@anywalletkit/wallet-near: malformed history cursor");
|
|
112
|
+
return { v: 1, tx: c.tx, ft: c.ft };
|
|
113
|
+
}
|
|
114
|
+
var TokenBucket = class {
|
|
115
|
+
constructor(rate, burst = Math.max(2, Math.ceil(rate))) {
|
|
116
|
+
this.rate = rate;
|
|
117
|
+
this.burst = burst;
|
|
118
|
+
this.tokens = burst;
|
|
119
|
+
}
|
|
120
|
+
rate;
|
|
121
|
+
burst;
|
|
122
|
+
tokens;
|
|
123
|
+
last = Date.now();
|
|
124
|
+
chain = Promise.resolve();
|
|
125
|
+
acquire() {
|
|
126
|
+
const next = this.chain.then(() => this.take());
|
|
127
|
+
this.chain = next.catch(() => void 0);
|
|
128
|
+
return next;
|
|
129
|
+
}
|
|
130
|
+
refill() {
|
|
131
|
+
const now = Date.now();
|
|
132
|
+
this.tokens = Math.min(this.burst, this.tokens + (now - this.last) / 1e3 * this.rate);
|
|
133
|
+
this.last = now;
|
|
134
|
+
}
|
|
135
|
+
async take() {
|
|
136
|
+
this.refill();
|
|
137
|
+
if (this.tokens >= 1) {
|
|
138
|
+
this.tokens -= 1;
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
await new Promise((r) => setTimeout(r, Math.ceil((1 - this.tokens) / this.rate * 1e3)));
|
|
142
|
+
this.refill();
|
|
143
|
+
this.tokens = Math.max(0, this.tokens - 1);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
function timeoutSignal(ms) {
|
|
147
|
+
const ctor = globalThis.AbortSignal;
|
|
148
|
+
return typeof ctor?.timeout === "function" ? ctor.timeout(ms) : void 0;
|
|
149
|
+
}
|
|
150
|
+
function parseJsonPreservingBigInts(text) {
|
|
151
|
+
let out = "";
|
|
152
|
+
let i = 0;
|
|
153
|
+
let inString = false;
|
|
154
|
+
while (i < text.length) {
|
|
155
|
+
const ch = text[i];
|
|
156
|
+
if (inString) {
|
|
157
|
+
out += ch;
|
|
158
|
+
if (ch === "\\") {
|
|
159
|
+
out += text[i + 1] ?? "";
|
|
160
|
+
i += 2;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (ch === '"') inString = false;
|
|
164
|
+
i++;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (ch === '"') {
|
|
168
|
+
inString = true;
|
|
169
|
+
out += ch;
|
|
170
|
+
i++;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (ch === "-" || ch >= "0" && ch <= "9") {
|
|
174
|
+
let j = i;
|
|
175
|
+
if (text[j] === "-") j++;
|
|
176
|
+
while (j < text.length && text[j] >= "0" && text[j] <= "9") j++;
|
|
177
|
+
const next = text[j];
|
|
178
|
+
const isInteger = next !== "." && next !== "e" && next !== "E";
|
|
179
|
+
if (isInteger) {
|
|
180
|
+
const tok = text.slice(i, j);
|
|
181
|
+
out += tok.replace("-", "").length >= 16 ? `"${tok}"` : tok;
|
|
182
|
+
i = j;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
while (j < text.length && /[0-9.eE+-]/.test(text[j])) j++;
|
|
186
|
+
out += text.slice(i, j);
|
|
187
|
+
i = j;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
out += ch;
|
|
191
|
+
i++;
|
|
192
|
+
}
|
|
193
|
+
return JSON.parse(out);
|
|
194
|
+
}
|
|
195
|
+
function big(v, approx) {
|
|
196
|
+
if (typeof v === "bigint") return v;
|
|
197
|
+
if (typeof v === "string" && /^-?\d+$/.test(v)) return BigInt(v);
|
|
198
|
+
if (typeof v === "number" && Number.isFinite(v)) {
|
|
199
|
+
if (!Number.isSafeInteger(v)) approx.value = true;
|
|
200
|
+
return BigInt(Math.trunc(v));
|
|
201
|
+
}
|
|
202
|
+
return void 0;
|
|
203
|
+
}
|
|
204
|
+
var nsToSeconds = (ts) => {
|
|
205
|
+
if (typeof ts === "string" && /^\d+$/.test(ts)) return Number(BigInt(ts) / 1000000000n);
|
|
206
|
+
if (typeof ts === "number") return Math.floor(ts / 1e9);
|
|
207
|
+
return 0;
|
|
208
|
+
};
|
|
209
|
+
function ftTransfer(row, approx) {
|
|
210
|
+
const meta = row.ft ?? row.ft_meta;
|
|
211
|
+
if (!meta?.contract) return void 0;
|
|
212
|
+
const delta = big(row.delta_amount, approx);
|
|
213
|
+
if (delta === void 0 || delta === 0n) return void 0;
|
|
214
|
+
const other = row.involved_account_id ?? meta.contract;
|
|
215
|
+
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" };
|
|
216
|
+
if (typeof meta.symbol === "string") t.symbol = meta.symbol;
|
|
217
|
+
if (typeof meta.decimals === "number") t.decimals = meta.decimals;
|
|
218
|
+
return t;
|
|
219
|
+
}
|
|
220
|
+
function foldActions(actions, from, to, fold, approx) {
|
|
221
|
+
for (const a of actions ?? []) {
|
|
222
|
+
const deposit = big(a.deposit, approx) ?? 0n;
|
|
223
|
+
if (a.action === "TRANSFER") {
|
|
224
|
+
if (deposit > 0n) fold.transfers.push({ token: null, from, to, amount: deposit });
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
if (a.action === "DELEGATE_ACTION") continue;
|
|
228
|
+
const method = a.action === "FUNCTION_CALL" ? a.method ?? "function_call" : a.action.toLowerCase();
|
|
229
|
+
fold.programs.push(method);
|
|
230
|
+
if (a.action === "FUNCTION_CALL" && deposit > 0n && deposit !== ONE_YOCTO) fold.transfers.push({ token: null, from, to, amount: deposit });
|
|
231
|
+
fold.call ??= { to, method, programs: fold.programs };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function mapNearblocksGroup(chain, address, receipts, ft) {
|
|
235
|
+
const approx = { value: false };
|
|
236
|
+
const rows = [...receipts].sort((a, b) => BigInt(a.id) < BigInt(b.id) ? -1 : BigInt(a.id) > BigInt(b.id) ? 1 : 0);
|
|
237
|
+
const real = rows.filter((r) => r.predecessor_account_id !== "system" && (r.receipt_kind ?? "ACTION") === "ACTION");
|
|
238
|
+
const fold = { transfers: [], programs: [] };
|
|
239
|
+
const ordered = [...real.filter((r) => r.receiver_account_id !== address), ...real.filter((r) => r.receiver_account_id === address)];
|
|
240
|
+
for (const r of ordered) foldActions(r.actions, r.predecessor_account_id, r.receiver_account_id, fold, approx);
|
|
241
|
+
for (const f of ft) {
|
|
242
|
+
const t = ftTransfer(f, approx);
|
|
243
|
+
if (t) fold.transfers.push(t);
|
|
244
|
+
}
|
|
245
|
+
const head = ordered[0] ?? rows[0] ?? ft[0];
|
|
246
|
+
const hash = head?.transaction_hash ?? "";
|
|
247
|
+
const from = ordered[0]?.predecessor_account_id ?? (ft.length ? ftTransfer(ft[0], approx)?.from ?? address : address);
|
|
248
|
+
const involves = (t) => t.from === address || t.to === address;
|
|
249
|
+
const primary = fold.transfers.find((t) => t.token !== null && involves(t)) ?? fold.transfers.find(involves) ?? fold.transfers[0];
|
|
250
|
+
const to = fold.call?.to ?? primary?.to ?? ordered[0]?.receiver_account_id ?? null;
|
|
251
|
+
let nativeValue = 0n;
|
|
252
|
+
for (const t of fold.transfers) if (t.token === null && t.from === from) nativeValue += t.amount;
|
|
253
|
+
const statuses = [...rows.map((r) => r.outcomes?.status), ...ft.map((r) => r.outcomes?.status)].filter((s) => typeof s === "boolean");
|
|
254
|
+
const status = statuses.length === 0 ? "confirmed" : statuses.every(Boolean) ? "confirmed" : "failed";
|
|
255
|
+
const feeSrc = rows.find((r) => r.outcomes_agg?.transaction_fee != null)?.outcomes_agg?.transaction_fee;
|
|
256
|
+
const fee = big(feeSrc, approx);
|
|
257
|
+
const heights = [...rows, ...ft].map((r) => r.block?.block_height).filter((h) => typeof h === "number");
|
|
258
|
+
const raw = { receipts: rows, ft };
|
|
259
|
+
if (approx.value) raw.approximate = true;
|
|
260
|
+
const out = {
|
|
261
|
+
chain,
|
|
262
|
+
hash,
|
|
263
|
+
time: nsToSeconds(head?.block_timestamp),
|
|
264
|
+
status,
|
|
265
|
+
address,
|
|
266
|
+
from,
|
|
267
|
+
to,
|
|
268
|
+
nativeValue,
|
|
269
|
+
transfers: fold.transfers,
|
|
270
|
+
raw
|
|
271
|
+
};
|
|
272
|
+
if (fee !== void 0) out.fee = fee;
|
|
273
|
+
if (fold.call) out.call = fold.call;
|
|
274
|
+
if (heights.length) out.block = BigInt(Math.min(...heights));
|
|
275
|
+
return out;
|
|
276
|
+
}
|
|
277
|
+
function mapNearblocksTxn(chain, address, txn) {
|
|
278
|
+
const approx = { value: false };
|
|
279
|
+
const fold = { transfers: [], programs: [] };
|
|
280
|
+
foldActions(txn.actions, txn.signer_account_id, txn.receiver_account_id, fold, approx);
|
|
281
|
+
for (const r of txn.receipts ?? []) {
|
|
282
|
+
for (const f of r.fts ?? []) {
|
|
283
|
+
const delta = big(f.delta_amount, approx);
|
|
284
|
+
if (delta === void 0 || delta >= 0n) continue;
|
|
285
|
+
const t = ftTransfer(f, approx);
|
|
286
|
+
if (t) fold.transfers.push(t);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
const from = txn.signer_account_id;
|
|
290
|
+
const involves = (t) => t.from === address || t.to === address;
|
|
291
|
+
const primary = fold.transfers.find((t) => t.token !== null && involves(t)) ?? fold.transfers.find(involves) ?? fold.transfers[0];
|
|
292
|
+
let nativeValue = 0n;
|
|
293
|
+
for (const t of fold.transfers) if (t.token === null && t.from === from) nativeValue += t.amount;
|
|
294
|
+
const fee = big(txn.outcomes_agg?.transaction_fee, approx);
|
|
295
|
+
const raw = { receipts: [], ft: [], txn };
|
|
296
|
+
if (approx.value) raw.approximate = true;
|
|
297
|
+
const out = {
|
|
298
|
+
chain,
|
|
299
|
+
hash: txn.transaction_hash,
|
|
300
|
+
time: nsToSeconds(txn.block_timestamp),
|
|
301
|
+
status: txn.outcomes?.status === false ? "failed" : "confirmed",
|
|
302
|
+
address,
|
|
303
|
+
from,
|
|
304
|
+
to: fold.call?.to ?? primary?.to ?? txn.receiver_account_id,
|
|
305
|
+
nativeValue,
|
|
306
|
+
transfers: fold.transfers,
|
|
307
|
+
raw
|
|
308
|
+
};
|
|
309
|
+
if (fee !== void 0) out.fee = fee;
|
|
310
|
+
if (fold.call) out.call = fold.call;
|
|
311
|
+
if (typeof txn.block?.block_height === "number") out.block = BigInt(txn.block.block_height);
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
var utf8 = (bytes) => {
|
|
315
|
+
let s = "";
|
|
316
|
+
for (let i = 0; i < bytes.length; ) {
|
|
317
|
+
const b0 = bytes[i++];
|
|
318
|
+
let cp;
|
|
319
|
+
if (b0 < 128) cp = b0;
|
|
320
|
+
else if (b0 < 224) cp = (b0 & 31) << 6 | bytes[i++] & 63;
|
|
321
|
+
else if (b0 < 240) cp = (b0 & 15) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63;
|
|
322
|
+
else cp = (b0 & 7) << 18 | (bytes[i++] & 63) << 12 | (bytes[i++] & 63) << 6 | bytes[i++] & 63;
|
|
323
|
+
s += String.fromCodePoint(cp);
|
|
324
|
+
}
|
|
325
|
+
return s;
|
|
326
|
+
};
|
|
327
|
+
function mapRpcTxStatus(chain, address, r, base) {
|
|
328
|
+
const tx = r.transaction;
|
|
329
|
+
const transfers = [];
|
|
330
|
+
const programs = [];
|
|
331
|
+
let call;
|
|
332
|
+
const walk = (actions, from2, to) => {
|
|
333
|
+
for (const a of actions ?? []) {
|
|
334
|
+
if (a.Transfer) {
|
|
335
|
+
const d = BigInt(a.Transfer.deposit);
|
|
336
|
+
if (d > 0n) transfers.push({ token: null, from: from2, to, amount: d });
|
|
337
|
+
} else if (a.FunctionCall) {
|
|
338
|
+
const d = BigInt(a.FunctionCall.deposit || "0");
|
|
339
|
+
programs.push(a.FunctionCall.method_name);
|
|
340
|
+
if (d > 0n && d !== ONE_YOCTO) transfers.push({ token: null, from: from2, to, amount: d });
|
|
341
|
+
call ??= { to, method: a.FunctionCall.method_name, programs };
|
|
342
|
+
} else if (a.Delegate) {
|
|
343
|
+
walk(a.Delegate.delegate_action.actions, a.Delegate.delegate_action.sender_id, a.Delegate.delegate_action.receiver_id);
|
|
344
|
+
} else {
|
|
345
|
+
const name = Object.keys(a)[0];
|
|
346
|
+
if (name) {
|
|
347
|
+
const method = name.replace(/([a-z])([A-Z])/g, "$1_$2").toLowerCase();
|
|
348
|
+
programs.push(method);
|
|
349
|
+
call ??= { to, method, programs };
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
if (tx) walk(tx.actions, tx.signer_id, tx.receiver_id);
|
|
355
|
+
let fee = 0n;
|
|
356
|
+
const burnt = r.transaction_outcome?.outcome?.tokens_burnt;
|
|
357
|
+
if (burnt) fee += BigInt(burnt);
|
|
358
|
+
let failed = false;
|
|
359
|
+
for (const ro of r.receipts_outcome ?? []) {
|
|
360
|
+
const o = ro.outcome;
|
|
361
|
+
if (!o) continue;
|
|
362
|
+
if (o.tokens_burnt) fee += BigInt(o.tokens_burnt);
|
|
363
|
+
if (o.status && "Failure" in o.status) failed = true;
|
|
364
|
+
const token = o.executor_id;
|
|
365
|
+
for (const log of o.logs ?? []) {
|
|
366
|
+
if (!token) continue;
|
|
367
|
+
const legacy = /^Transfer (\d+) from (\S+) to (\S+)$/.exec(log);
|
|
368
|
+
if (legacy) {
|
|
369
|
+
transfers.push({ token, from: legacy[2], to: legacy[3], amount: BigInt(legacy[1]), standard: "nep141" });
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
if (!log.startsWith("EVENT_JSON:")) continue;
|
|
373
|
+
let ev;
|
|
374
|
+
try {
|
|
375
|
+
ev = JSON.parse(log.slice("EVENT_JSON:".length));
|
|
376
|
+
} catch {
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (ev.standard !== "nep141") continue;
|
|
380
|
+
for (const d of ev.data ?? []) {
|
|
381
|
+
if (!d.amount || !/^\d+$/.test(d.amount)) continue;
|
|
382
|
+
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" });
|
|
383
|
+
else if (ev.event === "ft_mint" && d.owner_id) transfers.push({ token, from: token, to: d.owner_id, amount: BigInt(d.amount), standard: "nep141" });
|
|
384
|
+
else if (ev.event === "ft_burn" && d.owner_id) transfers.push({ token, from: d.owner_id, to: token, amount: BigInt(d.amount), standard: "nep141" });
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (r.status && "Failure" in r.status) failed = true;
|
|
389
|
+
for (const t of transfers) {
|
|
390
|
+
const known = base?.transfers.find((x) => x.token === t.token && (x.symbol !== void 0 || x.decimals !== void 0));
|
|
391
|
+
if (known?.symbol !== void 0) t.symbol = known.symbol;
|
|
392
|
+
if (known?.decimals !== void 0) t.decimals = known.decimals;
|
|
393
|
+
}
|
|
394
|
+
const from = tx?.signer_id ?? base?.from ?? address;
|
|
395
|
+
const involves = (t) => t.from === address || t.to === address;
|
|
396
|
+
const primary = transfers.find((t) => t.token !== null && involves(t)) ?? transfers.find(involves) ?? transfers[0];
|
|
397
|
+
let nativeValue = 0n;
|
|
398
|
+
for (const t of transfers) if (t.token === null && t.from === from) nativeValue += t.amount;
|
|
399
|
+
const raw = { ...base?.raw ?? { receipts: [], ft: [] }, rpc: r };
|
|
400
|
+
delete raw.approximate;
|
|
401
|
+
const out = {
|
|
402
|
+
chain,
|
|
403
|
+
hash: tx?.hash ?? base?.hash ?? "",
|
|
404
|
+
time: base?.time ?? 0,
|
|
405
|
+
status: failed ? "failed" : "confirmed",
|
|
406
|
+
address,
|
|
407
|
+
from,
|
|
408
|
+
to: call?.to ?? primary?.to ?? tx?.receiver_id ?? base?.to ?? null,
|
|
409
|
+
nativeValue,
|
|
410
|
+
transfers,
|
|
411
|
+
fee,
|
|
412
|
+
raw
|
|
413
|
+
};
|
|
414
|
+
if (call) out.call = call;
|
|
415
|
+
if (base?.block !== void 0) out.block = base.block;
|
|
416
|
+
return out;
|
|
417
|
+
}
|
|
418
|
+
function decodeFunctionCallArgs(args) {
|
|
419
|
+
try {
|
|
420
|
+
return JSON.parse(utf8(fromBase64(args)));
|
|
421
|
+
} catch {
|
|
422
|
+
return void 0;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
function nearExplorerTxUrl(hash, network = "mainnet") {
|
|
426
|
+
return `https://${network === "testnet" ? "testnet." : ""}nearblocks.io/txns/${hash}`;
|
|
427
|
+
}
|
|
428
|
+
function createNearHistory(options = {}) {
|
|
429
|
+
const network = options.network ?? "mainnet";
|
|
430
|
+
const chain = CAIP2[network] ?? CAIP2.mainnet;
|
|
431
|
+
const base = (options.nearblocksUrl ?? (network === "testnet" ? "https://api-testnet.nearblocks.io" : "https://api.nearblocks.io")).replace(/\/+$/, "");
|
|
432
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
433
|
+
if (typeof fetchFn !== "function") throw new Error("@anywalletkit/wallet-near: no global fetch; pass `fetch` in the options");
|
|
434
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
435
|
+
const bucket = new TokenBucket(options.rateLimit ?? (options.apiKey ? 5 : 0.1));
|
|
436
|
+
async function get(path) {
|
|
437
|
+
await bucket.acquire();
|
|
438
|
+
const url = `${base}${path}`;
|
|
439
|
+
let res;
|
|
440
|
+
try {
|
|
441
|
+
const signal = timeoutSignal(timeoutMs);
|
|
442
|
+
res = await fetchFn(url, { headers: { accept: "application/json", ...options.apiKey ? { authorization: `Bearer ${options.apiKey}` } : {} }, ...signal ? { signal } : {} });
|
|
443
|
+
} catch (e) {
|
|
444
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
445
|
+
throw new HistoryUnavailableError(chain, `${path}: ${msg}`, [`nearblocks: ${msg}`]);
|
|
446
|
+
}
|
|
447
|
+
const text = await res.text();
|
|
448
|
+
let body;
|
|
449
|
+
try {
|
|
450
|
+
body = parseJsonPreservingBigInts(text);
|
|
451
|
+
} catch {
|
|
452
|
+
body = void 0;
|
|
453
|
+
}
|
|
454
|
+
if (!res.ok) {
|
|
455
|
+
const msg = body?.message ?? `HTTP ${res.status}`;
|
|
456
|
+
throw new HistoryUnavailableError(chain, `${path}: ${msg}`, [`nearblocks: HTTP ${res.status} ${msg}`]);
|
|
457
|
+
}
|
|
458
|
+
return body;
|
|
459
|
+
}
|
|
460
|
+
async function rpcTxStatus(hash, signer) {
|
|
461
|
+
if (!options.rpcUrl) return void 0;
|
|
462
|
+
const signal = timeoutSignal(timeoutMs);
|
|
463
|
+
const res = await fetchFn(options.rpcUrl, {
|
|
464
|
+
method: "POST",
|
|
465
|
+
headers: { "content-type": "application/json", accept: "application/json" },
|
|
466
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: "1", method: "EXPERIMENTAL_tx_status", params: { tx_hash: hash, sender_account_id: signer, wait_until: "NONE" } }),
|
|
467
|
+
...signal ? { signal } : {}
|
|
468
|
+
});
|
|
469
|
+
const json = JSON.parse(await res.text());
|
|
470
|
+
if (!res.ok || json.error || !json.result) return void 0;
|
|
471
|
+
return json.result;
|
|
472
|
+
}
|
|
473
|
+
return {
|
|
474
|
+
chain,
|
|
475
|
+
async listActivity(address, query = {}) {
|
|
476
|
+
const limit = Math.min(MAX_LIMIT, Math.max(1, Math.floor(query.limit ?? DEFAULT_LIMIT)));
|
|
477
|
+
const cursor = query.cursor ? decodeCursor(query.cursor) : { v: 1, tx: "", ft: "" };
|
|
478
|
+
const acct = encodeURIComponent(address);
|
|
479
|
+
const perPage = Math.min(MAX_LIMIT, limit * 2);
|
|
480
|
+
const txRows = cursor.tx === null ? [] : (await get(`/v1/account/${acct}/txns?per_page=${perPage}&order=desc${cursor.tx ? `&cursor=${encodeURIComponent(cursor.tx)}` : ""}`))?.txns ?? [];
|
|
481
|
+
const ftRows = cursor.ft === null ? [] : (await get(`/v1/account/${acct}/ft-txns?per_page=${limit}&order=desc${cursor.ft ? `&cursor=${encodeURIComponent(cursor.ft)}` : ""}`))?.txns ?? [];
|
|
482
|
+
const key = (r) => BigInt(typeof r.block_timestamp === "string" ? r.block_timestamp : Math.trunc(r.block_timestamp));
|
|
483
|
+
const all = [...txRows.map((r) => ({ k: key(r), h: r.transaction_hash })), ...ftRows.map((r) => ({ k: key(r), h: r.transaction_hash }))];
|
|
484
|
+
all.sort((a, b) => a.k > b.k ? -1 : a.k < b.k ? 1 : 0);
|
|
485
|
+
const chosen = /* @__PURE__ */ new Set();
|
|
486
|
+
let boundary;
|
|
487
|
+
for (const e of all) {
|
|
488
|
+
if (chosen.has(e.h)) continue;
|
|
489
|
+
if (chosen.size >= limit && boundary !== void 0 && e.k < boundary) break;
|
|
490
|
+
chosen.add(e.h);
|
|
491
|
+
if (chosen.size === limit) boundary = e.k;
|
|
492
|
+
}
|
|
493
|
+
const consume = (rows, asked, wasAt, pos) => {
|
|
494
|
+
if (wasAt === null) return { used: [], next: null };
|
|
495
|
+
let n = 0;
|
|
496
|
+
while (n < rows.length && chosen.has(rows[n].transaction_hash)) n++;
|
|
497
|
+
const used = rows.slice(0, n);
|
|
498
|
+
if (rows.length < asked && n === rows.length) return { used, next: null };
|
|
499
|
+
return { used, next: n > 0 ? pos(used[n - 1]) : wasAt };
|
|
500
|
+
};
|
|
501
|
+
const txC = consume(txRows, perPage, cursor.tx, (r) => r.id);
|
|
502
|
+
const ftC = consume(ftRows, limit, cursor.ft, (r) => r.event_index);
|
|
503
|
+
const nextTx = txC.next, nextFt = ftC.next;
|
|
504
|
+
const groups = /* @__PURE__ */ new Map();
|
|
505
|
+
for (const h of chosen) groups.set(h, { receipts: [], ft: [] });
|
|
506
|
+
for (const r of txC.used) groups.get(r.transaction_hash).receipts.push(r);
|
|
507
|
+
for (const r of ftC.used) groups.get(r.transaction_hash).ft.push(r);
|
|
508
|
+
let items = [...groups.entries()].map(([, g]) => mapNearblocksGroup(chain, address, g.receipts, g.ft)).filter((t) => t.hash);
|
|
509
|
+
items.sort((a, b) => b.time - a.time);
|
|
510
|
+
let more = nextTx !== null || nextFt !== null;
|
|
511
|
+
if (query.since !== void 0) {
|
|
512
|
+
const since = query.since;
|
|
513
|
+
if (items.some((t) => t.time < since)) more = false;
|
|
514
|
+
items = items.filter((t) => t.time >= since);
|
|
515
|
+
}
|
|
516
|
+
const page = { items };
|
|
517
|
+
if (more) page.cursor = encodeCursor({ v: 1, tx: nextTx, ft: nextFt });
|
|
518
|
+
return page;
|
|
519
|
+
},
|
|
520
|
+
async getTransaction(hash, address) {
|
|
521
|
+
const body = await get(`/v1/txns/${encodeURIComponent(hash)}`);
|
|
522
|
+
const txn = body?.txns?.[0];
|
|
523
|
+
if (!txn) return void 0;
|
|
524
|
+
const base2 = mapNearblocksTxn(chain, address, txn);
|
|
525
|
+
if (!options.rpcUrl) return base2;
|
|
526
|
+
try {
|
|
527
|
+
const r = await rpcTxStatus(hash, txn.signer_account_id);
|
|
528
|
+
return r ? mapRpcTxStatus(chain, address, r, base2) : base2;
|
|
529
|
+
} catch {
|
|
530
|
+
return base2;
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
explorerTxUrl(hash) {
|
|
534
|
+
return nearExplorerTxUrl(hash, network);
|
|
535
|
+
}
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
//# sourceMappingURL=history.cjs.map
|