@anywalletkit/wallet-tron 0.0.0-stage → 0.2.1
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 +103 -2
- package/dist/chunk-4XN4VJDG.js +389 -0
- package/dist/chunk-4XN4VJDG.js.map +1 -0
- package/dist/history.cjs +394 -0
- package/dist/history.cjs.map +1 -0
- package/dist/history.d.cts +160 -0
- package/dist/history.d.ts +160 -0
- package/dist/history.js +21 -0
- package/dist/history.js.map +1 -0
- package/dist/index.cjs +1845 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +636 -0
- package/dist/index.d.ts +636 -0
- package/dist/index.js +1467 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -3
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
// src/address.ts
|
|
2
|
+
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
3
|
+
import { keccak_256 } from "@noble/hashes/sha3.js";
|
|
4
|
+
import { sha256 } from "@noble/hashes/sha2.js";
|
|
5
|
+
import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
|
|
6
|
+
import { createBase58check } from "@scure/base";
|
|
7
|
+
var b58check = createBase58check(sha256);
|
|
8
|
+
var ADDRESS_PREFIX = 65;
|
|
9
|
+
function addressFromPublicKey(compressed) {
|
|
10
|
+
const xy = secp256k1.Point.fromBytes(compressed).toBytes(false).slice(1);
|
|
11
|
+
const hash = keccak_256(xy);
|
|
12
|
+
const bytes = new Uint8Array(21);
|
|
13
|
+
bytes[0] = ADDRESS_PREFIX;
|
|
14
|
+
bytes.set(hash.slice(12), 1);
|
|
15
|
+
return b58check.encode(bytes);
|
|
16
|
+
}
|
|
17
|
+
function isHexAddress(a) {
|
|
18
|
+
return /^(0x)?41[0-9a-fA-F]{40}$/.test(a);
|
|
19
|
+
}
|
|
20
|
+
function toHexAddress(address) {
|
|
21
|
+
if (isHexAddress(address)) return address.replace(/^0x/, "").toLowerCase();
|
|
22
|
+
const bytes = b58check.decode(address);
|
|
23
|
+
if (bytes.length !== 21 || bytes[0] !== ADDRESS_PREFIX) throw new Error(`Invalid Tron address: ${address}`);
|
|
24
|
+
return bytesToHex(bytes);
|
|
25
|
+
}
|
|
26
|
+
function toBase58Address(address) {
|
|
27
|
+
if (!isHexAddress(address)) {
|
|
28
|
+
toHexAddress(address);
|
|
29
|
+
return address;
|
|
30
|
+
}
|
|
31
|
+
return b58check.encode(hexToBytes(address.replace(/^0x/, "")));
|
|
32
|
+
}
|
|
33
|
+
function toEvmHex(address) {
|
|
34
|
+
return toHexAddress(address).slice(2);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/types.ts
|
|
38
|
+
var CAIP2_GENESIS = {
|
|
39
|
+
mainnet: "tron:0x2b6653dc",
|
|
40
|
+
shasta: "tron:0x94a9059e",
|
|
41
|
+
nile: "tron:0xcd8690dc"
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// src/history.ts
|
|
45
|
+
var HistoryUnavailableError = class extends Error {
|
|
46
|
+
chain;
|
|
47
|
+
reason;
|
|
48
|
+
attempts;
|
|
49
|
+
constructor(chain, reason, attempts = []) {
|
|
50
|
+
super(`History unavailable for ${chain}: ${reason}`);
|
|
51
|
+
this.name = "HistoryUnavailableError";
|
|
52
|
+
this.chain = chain;
|
|
53
|
+
this.reason = reason;
|
|
54
|
+
this.attempts = attempts;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
var DEFAULT_LIMIT = 25;
|
|
58
|
+
var MAX_LIMIT = 200;
|
|
59
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
60
|
+
var DEFAULT_URLS = { mainnet: "https://api.trongrid.io", shasta: "https://api.shasta.trongrid.io", nile: "https://nile.trongrid.io" };
|
|
61
|
+
var TRANSFER_TOPIC = "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef";
|
|
62
|
+
var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
63
|
+
function b64encode(s) {
|
|
64
|
+
let out = "";
|
|
65
|
+
for (let i = 0; i < s.length; i += 3) {
|
|
66
|
+
const c = [s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)];
|
|
67
|
+
for (const x of c) if (x > 255) throw new Error("cursor must be ASCII");
|
|
68
|
+
const n = c[0] << 16 | (c[1] || 0) << 8 | (c[2] || 0);
|
|
69
|
+
out += B64[n >> 18 & 63] + B64[n >> 12 & 63] + (Number.isNaN(c[1]) ? "=" : B64[n >> 6 & 63]) + (Number.isNaN(c[2]) ? "=" : B64[n & 63]);
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
function b64decode(s) {
|
|
74
|
+
const clean = s.replace(/[^A-Za-z0-9+/]/g, "");
|
|
75
|
+
let out = "";
|
|
76
|
+
for (let i = 0; i < clean.length; i += 4) {
|
|
77
|
+
const c = [0, 1, 2, 3].map((k) => i + k < clean.length ? B64.indexOf(clean[i + k]) : -1);
|
|
78
|
+
if (c[0] < 0 || c[1] < 0) throw new Error("bad base64");
|
|
79
|
+
const n = c[0] << 18 | c[1] << 12 | (c[2] < 0 ? 0 : c[2]) << 6 | (c[3] < 0 ? 0 : c[3]);
|
|
80
|
+
out += String.fromCharCode(n >> 16 & 255);
|
|
81
|
+
if (c[2] >= 0) out += String.fromCharCode(n >> 8 & 255);
|
|
82
|
+
if (c[3] >= 0) out += String.fromCharCode(n & 255);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function encodeCursor(c) {
|
|
87
|
+
return b64encode(JSON.stringify(c));
|
|
88
|
+
}
|
|
89
|
+
function decodeCursor(s) {
|
|
90
|
+
let parsed;
|
|
91
|
+
try {
|
|
92
|
+
parsed = JSON.parse(b64decode(s));
|
|
93
|
+
} catch {
|
|
94
|
+
throw new Error("@anywalletkit/wallet-tron: malformed history cursor");
|
|
95
|
+
}
|
|
96
|
+
const c = parsed;
|
|
97
|
+
if (!c || c.v !== 1 || typeof c.w !== "number" || !Array.isArray(c.x) || !Array.isArray(c.e)) throw new Error("@anywalletkit/wallet-tron: malformed history cursor");
|
|
98
|
+
return { v: 1, w: c.w, x: c.x.filter((x) => typeof x === "string"), e: c.e.filter((x) => x === "tx" || x === "trc20") };
|
|
99
|
+
}
|
|
100
|
+
var TokenBucket = class {
|
|
101
|
+
constructor(rate, burst = Math.max(1, Math.ceil(rate))) {
|
|
102
|
+
this.rate = rate;
|
|
103
|
+
this.burst = burst;
|
|
104
|
+
this.tokens = burst;
|
|
105
|
+
}
|
|
106
|
+
rate;
|
|
107
|
+
burst;
|
|
108
|
+
tokens;
|
|
109
|
+
last = Date.now();
|
|
110
|
+
chain = Promise.resolve();
|
|
111
|
+
acquire() {
|
|
112
|
+
const next = this.chain.then(() => this.take());
|
|
113
|
+
this.chain = next.catch(() => void 0);
|
|
114
|
+
return next;
|
|
115
|
+
}
|
|
116
|
+
refill() {
|
|
117
|
+
const now = Date.now();
|
|
118
|
+
this.tokens = Math.min(this.burst, this.tokens + (now - this.last) / 1e3 * this.rate);
|
|
119
|
+
this.last = now;
|
|
120
|
+
}
|
|
121
|
+
async take() {
|
|
122
|
+
this.refill();
|
|
123
|
+
if (this.tokens >= 1) {
|
|
124
|
+
this.tokens -= 1;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
await new Promise((r) => setTimeout(r, Math.ceil((1 - this.tokens) / this.rate * 1e3)));
|
|
128
|
+
this.refill();
|
|
129
|
+
this.tokens = Math.max(0, this.tokens - 1);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
function timeoutSignal(ms) {
|
|
133
|
+
const ctor = globalThis.AbortSignal;
|
|
134
|
+
return typeof ctor?.timeout === "function" ? ctor.timeout(ms) : void 0;
|
|
135
|
+
}
|
|
136
|
+
var big = (v) => {
|
|
137
|
+
if (typeof v === "bigint") return v;
|
|
138
|
+
if (typeof v === "number" && Number.isFinite(v)) return BigInt(Math.trunc(v));
|
|
139
|
+
if (typeof v === "string" && /^-?\d+$/.test(v)) return BigInt(v);
|
|
140
|
+
return 0n;
|
|
141
|
+
};
|
|
142
|
+
var b58 = (a) => {
|
|
143
|
+
if (typeof a !== "string" || a.length === 0) return void 0;
|
|
144
|
+
try {
|
|
145
|
+
return toBase58Address(a);
|
|
146
|
+
} catch {
|
|
147
|
+
return a;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
var wordToAddress = (word) => toBase58Address("41" + word.slice(-40).toLowerCase());
|
|
151
|
+
var SELF_TYPES_WITH_RECEIVER = {
|
|
152
|
+
DelegateResourceContract: "receiver_address",
|
|
153
|
+
UnDelegateResourceContract: "receiver_address",
|
|
154
|
+
AccountPermissionUpdateContract: "owner_address"
|
|
155
|
+
};
|
|
156
|
+
function mapTransactionRow(chain, address, tx, extra = {}) {
|
|
157
|
+
const contract = tx.raw_data.contract[0];
|
|
158
|
+
const v = contract?.parameter.value ?? {};
|
|
159
|
+
const type = contract?.type ?? "Unknown";
|
|
160
|
+
const owner = b58(v.owner_address) ?? address;
|
|
161
|
+
const transfers = [];
|
|
162
|
+
let call;
|
|
163
|
+
let to = null;
|
|
164
|
+
let nativeValue = 0n;
|
|
165
|
+
switch (type) {
|
|
166
|
+
case "TransferContract": {
|
|
167
|
+
to = b58(v.to_address) ?? null;
|
|
168
|
+
nativeValue = big(v.amount);
|
|
169
|
+
if (to && nativeValue > 0n) transfers.push({ token: null, from: owner, to, amount: nativeValue });
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case "TransferAssetContract": {
|
|
173
|
+
to = b58(v.to_address) ?? null;
|
|
174
|
+
const asset = typeof v.asset_name === "string" ? v.asset_name : void 0;
|
|
175
|
+
const amount = big(v.amount);
|
|
176
|
+
if (to && asset && amount > 0n) transfers.push({ token: asset, from: owner, to, amount, symbol: `TRC-10 #${asset}`, decimals: 0 });
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case "TriggerSmartContract": {
|
|
180
|
+
const contractAddress = b58(v.contract_address);
|
|
181
|
+
nativeValue = big(v.call_value);
|
|
182
|
+
if (contractAddress) {
|
|
183
|
+
to = contractAddress;
|
|
184
|
+
call = { to: contractAddress };
|
|
185
|
+
const data = typeof v.data === "string" ? v.data.toLowerCase() : "";
|
|
186
|
+
if (data.length >= 8) {
|
|
187
|
+
call.selector = `0x${data.slice(0, 8)}`;
|
|
188
|
+
call.data = `0x${data}`;
|
|
189
|
+
}
|
|
190
|
+
if (nativeValue > 0n) transfers.push({ token: null, from: owner, to: contractAddress, amount: nativeValue });
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
default: {
|
|
195
|
+
const receiverKey = SELF_TYPES_WITH_RECEIVER[type];
|
|
196
|
+
const receiver = receiverKey ? b58(v[receiverKey]) : void 0;
|
|
197
|
+
call = { to: receiver ?? owner, method: type };
|
|
198
|
+
to = receiver ?? owner;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const it of tx.internal_transactions ?? []) {
|
|
202
|
+
if (it.rejected) continue;
|
|
203
|
+
const from = b58(it.caller_address), dest = b58(it.transferTo_address);
|
|
204
|
+
if (!from || !dest) continue;
|
|
205
|
+
for (const cv of it.callValueInfo ?? []) {
|
|
206
|
+
const amount = big(cv.callValue);
|
|
207
|
+
if (amount > 0n && !cv.tokenId) transfers.push({ token: null, from, to: dest, amount });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const trc20 = extra.trc20 ?? [];
|
|
211
|
+
if (trc20.length > 0) {
|
|
212
|
+
for (const row of trc20) if (row.type === "Transfer") transfers.push(trc20Transfer(row));
|
|
213
|
+
} else if (extra.info?.log && extra.info.log.length > 0) {
|
|
214
|
+
for (const log of extra.info.log) {
|
|
215
|
+
if (log.topics[0]?.toLowerCase() !== TRANSFER_TOPIC || log.topics.length < 3) continue;
|
|
216
|
+
transfers.push({ token: toBase58Address("41" + log.address.toLowerCase().slice(-40)), from: wordToAddress(log.topics[1]), to: wordToAddress(log.topics[2]), amount: BigInt(`0x${log.data || "0"}`), standard: "trc20" });
|
|
217
|
+
}
|
|
218
|
+
} else if (call?.selector === "0xa9059cbb" && call.data && call.data.length >= 2 + 8 + 128) {
|
|
219
|
+
const words = call.data.slice(10);
|
|
220
|
+
transfers.push({ token: call.to, from: owner, to: wordToAddress(words.slice(0, 64)), amount: BigInt(`0x${words.slice(64, 128)}`), standard: "trc20" });
|
|
221
|
+
}
|
|
222
|
+
if (call?.selector === "0xa9059cbb" && !call.method) call.method = "transfer";
|
|
223
|
+
const ret = tx.ret?.[0];
|
|
224
|
+
const result = extra.info?.receipt?.result ?? ret?.contractRet;
|
|
225
|
+
const status = result === void 0 ? tx.blockNumber ? "confirmed" : "pending" : result === "SUCCESS" ? "confirmed" : "failed";
|
|
226
|
+
const feeNum = extra.info?.fee ?? (typeof ret?.fee === "number" ? ret.fee : void 0) ?? (tx.net_fee !== void 0 || tx.energy_fee !== void 0 ? (tx.net_fee ?? 0) + (tx.energy_fee ?? 0) : void 0);
|
|
227
|
+
const ts = tx.block_timestamp ?? extra.info?.blockTimeStamp ?? tx.raw_data.timestamp;
|
|
228
|
+
const blockNumber = tx.blockNumber ?? extra.info?.blockNumber;
|
|
229
|
+
const raw = { tx, trc20 };
|
|
230
|
+
if (contract?.type === "TransferAssetContract" && owner !== address && to === address) {
|
|
231
|
+
raw.spam = true;
|
|
232
|
+
raw.spamReason = "trc10-airdrop";
|
|
233
|
+
}
|
|
234
|
+
if (extra.info) raw.info = extra.info;
|
|
235
|
+
const out = { chain, hash: tx.txID, time: ts ? Math.floor(ts / 1e3) : 0, status, address, from: owner, to: call?.to ?? to, nativeValue, transfers, raw };
|
|
236
|
+
if (feeNum !== void 0) out.fee = BigInt(Math.trunc(feeNum));
|
|
237
|
+
if (call) out.call = call;
|
|
238
|
+
if (blockNumber !== void 0) out.block = BigInt(blockNumber);
|
|
239
|
+
return out;
|
|
240
|
+
}
|
|
241
|
+
function trc20Transfer(row) {
|
|
242
|
+
const t = { token: row.token_info.address, from: row.from, to: row.to, amount: big(row.value), standard: "trc20" };
|
|
243
|
+
if (row.token_info.symbol !== void 0) t.symbol = row.token_info.symbol;
|
|
244
|
+
if (row.token_info.decimals !== void 0) t.decimals = row.token_info.decimals;
|
|
245
|
+
return t;
|
|
246
|
+
}
|
|
247
|
+
function mapTrc20Only(chain, address, rows) {
|
|
248
|
+
const first = rows[0];
|
|
249
|
+
const transfers = rows.filter((r) => r.type === "Transfer").map(trc20Transfer);
|
|
250
|
+
const primary = transfers.find((t) => t.from === address || t.to === address) ?? transfers[0];
|
|
251
|
+
const out = {
|
|
252
|
+
chain,
|
|
253
|
+
hash: first.transaction_id,
|
|
254
|
+
time: Math.floor(first.block_timestamp / 1e3),
|
|
255
|
+
status: "confirmed",
|
|
256
|
+
address,
|
|
257
|
+
from: primary?.from ?? first.from,
|
|
258
|
+
to: primary?.to ?? first.to,
|
|
259
|
+
nativeValue: 0n,
|
|
260
|
+
transfers,
|
|
261
|
+
raw: { trc20: rows }
|
|
262
|
+
};
|
|
263
|
+
if (transfers.length === 0) {
|
|
264
|
+
out.call = { to: first.token_info.address, method: first.type.toLowerCase() };
|
|
265
|
+
out.to = first.token_info.address;
|
|
266
|
+
}
|
|
267
|
+
return out;
|
|
268
|
+
}
|
|
269
|
+
function tronExplorerTxUrl(hash, network = "mainnet") {
|
|
270
|
+
const host = network === "mainnet" ? "tronscan.org" : `${network}.tronscan.org`;
|
|
271
|
+
return `https://${host}/#/transaction/${hash}`;
|
|
272
|
+
}
|
|
273
|
+
function createTronHistory(options = {}) {
|
|
274
|
+
const network = options.network ?? "mainnet";
|
|
275
|
+
const chain = CAIP2_GENESIS[network] ?? CAIP2_GENESIS.mainnet;
|
|
276
|
+
const apiUrl = (options.apiUrl ?? DEFAULT_URLS[network]).replace(/\/+$/, "");
|
|
277
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
278
|
+
if (typeof fetchFn !== "function") throw new Error("@anywalletkit/wallet-tron: no global fetch; pass `fetch` in the options");
|
|
279
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
280
|
+
const bucket = new TokenBucket(options.rateLimit ?? (options.apiKey ? 10 : 1));
|
|
281
|
+
const headers = () => ({ accept: "application/json", ...options.apiKey ? { "TRON-PRO-API-KEY": options.apiKey } : {} });
|
|
282
|
+
async function request(path, init) {
|
|
283
|
+
await bucket.acquire();
|
|
284
|
+
const url = `${apiUrl}${path}`;
|
|
285
|
+
let res;
|
|
286
|
+
try {
|
|
287
|
+
const signal = timeoutSignal(timeoutMs);
|
|
288
|
+
res = await fetchFn(url, {
|
|
289
|
+
...init ? { method: "POST", body: JSON.stringify(init.body) } : {},
|
|
290
|
+
headers: { ...headers(), ...init ? { "content-type": "application/json" } : {} },
|
|
291
|
+
...signal ? { signal } : {}
|
|
292
|
+
});
|
|
293
|
+
} catch (e) {
|
|
294
|
+
throw new HistoryUnavailableError(chain, `${path}: ${e instanceof Error ? e.message : String(e)}`, [`trongrid: ${e instanceof Error ? e.message : String(e)}`]);
|
|
295
|
+
}
|
|
296
|
+
let body;
|
|
297
|
+
try {
|
|
298
|
+
body = await res.json();
|
|
299
|
+
} catch {
|
|
300
|
+
body = void 0;
|
|
301
|
+
}
|
|
302
|
+
const b = body;
|
|
303
|
+
if (!res.ok || b?.success === false || typeof b?.Error === "string") {
|
|
304
|
+
const msg = b?.error ?? b?.Error ?? `HTTP ${res.status}`;
|
|
305
|
+
throw new HistoryUnavailableError(chain, `${path}: ${msg}`, [`trongrid: HTTP ${res.status} ${msg}`]);
|
|
306
|
+
}
|
|
307
|
+
return body;
|
|
308
|
+
}
|
|
309
|
+
async function list(path, params) {
|
|
310
|
+
const q = Object.entries(params).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`).join("&");
|
|
311
|
+
const body = await request(`${path}?${q}`);
|
|
312
|
+
return body?.data ?? [];
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
chain,
|
|
316
|
+
async listActivity(address, query = {}) {
|
|
317
|
+
const limit = Math.min(MAX_LIMIT, Math.max(1, Math.floor(query.limit ?? DEFAULT_LIMIT)));
|
|
318
|
+
const cursor = query.cursor ? decodeCursor(query.cursor) : void 0;
|
|
319
|
+
const exhausted = new Set(cursor?.e ?? []);
|
|
320
|
+
const skip = new Set(cursor?.x ?? []);
|
|
321
|
+
const common = { limit, order_by: "block_timestamp,desc", max_timestamp: cursor?.w };
|
|
322
|
+
if (query.since !== void 0) common.min_timestamp = query.since * 1e3;
|
|
323
|
+
const txRows = exhausted.has("tx") ? [] : await list(`/v1/accounts/${encodeURIComponent(address)}/transactions`, common);
|
|
324
|
+
const trc20Rows = exhausted.has("trc20") ? [] : await list(`/v1/accounts/${encodeURIComponent(address)}/transactions/trc20`, common);
|
|
325
|
+
const tails = [];
|
|
326
|
+
if (!exhausted.has("tx") && txRows.length >= limit) tails.push(txRows[txRows.length - 1].block_timestamp ?? 0);
|
|
327
|
+
if (!exhausted.has("trc20") && trc20Rows.length >= limit) tails.push(trc20Rows[trc20Rows.length - 1].block_timestamp);
|
|
328
|
+
const cutoff = tails.length ? Math.max(...tails) : Number.NEGATIVE_INFINITY;
|
|
329
|
+
const byId = /* @__PURE__ */ new Map();
|
|
330
|
+
for (const r of txRows) {
|
|
331
|
+
if (skip.has(r.txID)) continue;
|
|
332
|
+
const e = byId.get(r.txID) ?? { ts: r.block_timestamp ?? 0, trc20: [] };
|
|
333
|
+
e.tx = r;
|
|
334
|
+
byId.set(r.txID, e);
|
|
335
|
+
}
|
|
336
|
+
for (const r of trc20Rows) {
|
|
337
|
+
if (skip.has(r.transaction_id)) continue;
|
|
338
|
+
const e = byId.get(r.transaction_id) ?? { ts: r.block_timestamp, trc20: [] };
|
|
339
|
+
e.trc20.push(r);
|
|
340
|
+
byId.set(r.transaction_id, e);
|
|
341
|
+
}
|
|
342
|
+
let entries = [...byId.entries()].sort((a, b) => b[1].ts - a[1].ts);
|
|
343
|
+
let inWindow = entries.filter(([, e]) => e.ts > cutoff);
|
|
344
|
+
if (inWindow.length === 0 && entries.length > 0) inWindow = entries.filter(([, e]) => e.ts === cutoff);
|
|
345
|
+
entries = inWindow.slice(0, limit);
|
|
346
|
+
const items = entries.map(([, e]) => e.tx ? mapTransactionRow(chain, address, e.tx, { trc20: e.trc20 }) : mapTrc20Only(chain, address, e.trc20));
|
|
347
|
+
const emitted = new Set(entries.map(([id]) => id));
|
|
348
|
+
const done = (id) => emitted.has(id) || skip.has(id);
|
|
349
|
+
if (!exhausted.has("tx") && txRows.length < limit && txRows.every((r) => done(r.txID))) exhausted.add("tx");
|
|
350
|
+
if (!exhausted.has("trc20") && trc20Rows.length < limit && trc20Rows.every((r) => done(r.transaction_id))) exhausted.add("trc20");
|
|
351
|
+
const page = { items };
|
|
352
|
+
const more = exhausted.size < 2;
|
|
353
|
+
if (more && entries.length > 0) {
|
|
354
|
+
const last = entries[entries.length - 1][1].ts;
|
|
355
|
+
const x = entries.filter(([, e]) => e.ts === last).map(([id]) => id);
|
|
356
|
+
if (last === cursor?.w) for (const id of skip) x.push(id);
|
|
357
|
+
page.cursor = encodeCursor({ v: 1, w: last, x, e: [...exhausted] });
|
|
358
|
+
}
|
|
359
|
+
return page;
|
|
360
|
+
},
|
|
361
|
+
async getTransaction(hash, address) {
|
|
362
|
+
const tx = await request("/wallet/gettransactionbyid", { method: "POST", body: { value: hash } });
|
|
363
|
+
if (!tx || typeof tx.txID !== "string") return void 0;
|
|
364
|
+
const info = await request("/wallet/gettransactioninfobyid", { method: "POST", body: { value: hash } });
|
|
365
|
+
return mapTransactionRow(chain, address, tx, info && typeof info.id === "string" ? { info } : {});
|
|
366
|
+
},
|
|
367
|
+
explorerTxUrl(hash) {
|
|
368
|
+
return tronExplorerTxUrl(hash, network);
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export {
|
|
374
|
+
CAIP2_GENESIS,
|
|
375
|
+
addressFromPublicKey,
|
|
376
|
+
isHexAddress,
|
|
377
|
+
toHexAddress,
|
|
378
|
+
toBase58Address,
|
|
379
|
+
toEvmHex,
|
|
380
|
+
HistoryUnavailableError,
|
|
381
|
+
TRANSFER_TOPIC,
|
|
382
|
+
encodeCursor,
|
|
383
|
+
decodeCursor,
|
|
384
|
+
mapTransactionRow,
|
|
385
|
+
mapTrc20Only,
|
|
386
|
+
tronExplorerTxUrl,
|
|
387
|
+
createTronHistory
|
|
388
|
+
};
|
|
389
|
+
//# sourceMappingURL=chunk-4XN4VJDG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/address.ts","../src/types.ts","../src/history.ts"],"sourcesContent":["import { secp256k1 } from '@noble/curves/secp256k1.js'\nimport { keccak_256 } from '@noble/hashes/sha3.js'\nimport { sha256 } from '@noble/hashes/sha2.js'\nimport { bytesToHex, hexToBytes } from '@noble/hashes/utils.js'\nimport { createBase58check } from '@scure/base'\n\nconst b58check = createBase58check(sha256)\nexport const ADDRESS_PREFIX = 0x41\n\n/** Compressed secp256k1 pubkey → base58 T… address (keccak of X||Y, last 20 bytes, 0x41 prefix, sha256d checksum). */\nexport function addressFromPublicKey(compressed: Uint8Array): string {\n const xy = secp256k1.Point.fromBytes(compressed).toBytes(false).slice(1)\n const hash = keccak_256(xy)\n const bytes = new Uint8Array(21)\n bytes[0] = ADDRESS_PREFIX\n bytes.set(hash.slice(12), 1)\n return b58check.encode(bytes)\n}\n\n/** True for a hex Tron address (`41` plus 20 bytes, optional `0x`). */\nexport function isHexAddress(a: string): boolean {\n return /^(0x)?41[0-9a-fA-F]{40}$/.test(a)\n}\n\n/** Any accepted form → 21-byte hex \"41…\" (lowercase, no 0x). */\nexport function toHexAddress(address: string): string {\n if (isHexAddress(address)) return address.replace(/^0x/, '').toLowerCase()\n const bytes = b58check.decode(address)\n if (bytes.length !== 21 || bytes[0] !== ADDRESS_PREFIX) throw new Error(`Invalid Tron address: ${address}`)\n return bytesToHex(bytes)\n}\n\n/** Any accepted form → base58 T… */\nexport function toBase58Address(address: string): string {\n if (!isHexAddress(address)) { toHexAddress(address); return address }\n return b58check.encode(hexToBytes(address.replace(/^0x/, '')))\n}\n\n/** 20-byte EVM-style hex (no 0x) for ABI encoding. */\nexport function toEvmHex(address: string): string {\n return toHexAddress(address).slice(2)\n}\n","/** JSON-RPC-ish HTTP transport: POST `path` with a JSON body, returns parsed JSON. */\nexport type TronFetch = (path: string, body: unknown) => Promise<unknown>\n\n/** One full-node base url (e.g. \"https://api.trongrid.io\") or a ready transport. */\nexport type TronProvider = string | TronFetch\n\n/**\n * Options for a Tron wallet manager or account: full-node endpoints, network, fee limits and the\n * pre-sign checks.\n */\nexport interface TronConfig {\n /** Full-node url(s) / transport(s). A list fails over in order. Omit for an offline (sign-only) wallet. */\n provider?: TronProvider | TronProvider[]\n /** Extra attempts across the provider list after the first failure (default 3). */\n retries?: number\n /** Optional headers for every request (e.g. `TRON-PRO-API-KEY`). */\n headers?: Record<string, string>\n /** Max fee (sun) for `transfer`. */\n transferMaxFee?: bigint | number\n /** Max fee (sun) for `sendTransaction` / `signTransaction`. */\n transactionMaxFee?: bigint | number\n /** CAIP-2 suffix; default mainnet genesis \"0x2b6653dc\". */\n network?: 'mainnet' | 'shasta' | 'nile' | string\n /** Run `simulateTransaction` before signing in `sendTransaction` / `transfer` (default true). */\n simulate?: boolean\n /** Allow TRX / TRC-20 transfers to the zero address (default false — refused as a burn). */\n allowBurn?: boolean\n}\n\n/** Native TRX transfer. `value` in sun. `memo` → `raw_data.data` (charged the memo fee). */\nexport interface TronNativeTransfer { to: string; value: bigint | number | string; memo?: string; /** 'hex' = binary memo given as 0x-hex (default 'utf8'). */ memoEncoding?: 'utf8' | 'hex' }\n\n/** Smart-contract call. */\nexport interface TronContractCall {\n contractAddress: string\n /** e.g. \"transfer(address,uint256)\" */\n functionSelector: string\n parameters?: Array<{ type: string; value: unknown }>\n options?: { feeLimit?: number; callValue?: number }\n /** Attached as `raw_data.data` (e.g. a THORChain swap memo on a TRC-20 transfer). */\n memo?: string\n /** 'hex' = binary memo given as 0x-hex, e.g. a Chainflip vault-swap note (default 'utf8'). */\n memoEncoding?: 'utf8' | 'hex'\n}\n\n/** A transaction as the full node returns it (`/wallet/createtransaction`, `/wallet/triggersmartcontract`). */\nexport interface TronRawTransaction {\n txID: string\n raw_data_hex: string\n raw_data: {\n contract: Array<{ type: string; parameter: { value: Record<string, unknown>; type_url?: string } }>\n ref_block_bytes?: string\n ref_block_hash?: string\n expiration?: number\n timestamp?: number\n fee_limit?: number\n /** Memo, hex-encoded. Charged `getMemoFee` when present. */\n data?: string\n }\n /** Execution result the node attaches (also returned by `triggerconstantcontract` on revert: `ret: 'FAILED'`). */\n ret?: Array<{ ret?: string; contractRet?: string }>\n visible?: boolean\n signature?: string[]\n}\n\n/**\n * Anything `sendTransaction` accepts: a TRX transfer, a contract call, or a transaction prebuilt by\n * a provider.\n */\nexport type TronTransaction = TronNativeTransfer | TronContractCall | TronRawTransaction\n\n/** A TRX or TRC-20 transfer. Amount in sun or the token's base units. */\nexport interface TronTransferOptions {\n /** TRC-20 contract (base58 T… or hex 41…). Omit for native TRX. */\n token?: string\n /** Address that receives (base58 `T…` or hex `41…`). */\n recipient: string\n amount: bigint | number | string\n /** Attached as `raw_data.data`; the network charges `getMemoFee` (1 TRX). */\n memo?: string\n /** 'hex' = binary memo given as 0x-hex, e.g. a Chainflip vault-swap note (default 'utf8'). */\n memoEncoding?: 'utf8' | 'hex'\n}\n\n/** What a transaction will cost, resource by resource. All sun values are what the SENDER burns. */\nexport interface TronFeeBreakdown {\n /** Free bandwidth points left on the account (`freeNetLimit − freeNetUsed`). */\n bandwidthFree: number\n /** Staked bandwidth points left (`NetLimit − NetUsed`). */\n bandwidthStaked: number\n /** Staked energy left (`EnergyLimit − EnergyUsed`). */\n energyStaked: number\n /** sun per energy unit (`getEnergyFee`). */\n energyPrice: bigint\n /** sun per bandwidth byte (`getTransactionFee`). */\n bandwidthPrice: bigint\n /** sun burned for a memo (`getMemoFee`), 0 without one. */\n memoFee: bigint\n /**\n * sun burned to create the recipient account: `getCreateNewAccountFeeInSystemContract` (1 TRX)\n * plus `getCreateAccountFee` (0.1 TRX) when staked bandwidth cannot cover the creation; 0 when it exists.\n */\n accountCreationFee: bigint\n /** sun burned for bandwidth not covered by staked/free allowance. */\n bandwidthBurn: bigint\n /** sun burned for energy not covered by staked energy. */\n energyBurn: bigint\n}\n\n/**\n * Resources a transaction consumes and the TRX burned for what the account's free bandwidth and\n * staked energy do not cover.\n */\nexport interface TronFeeEstimate {\n /** Bandwidth points the transaction consumes (serialized size + signature + 64-byte result reserve). */\n bandwidth: number\n /** Energy the call consumes (`energy_used` from a constant call); 0 for non-contract transactions. */\n energy: number\n /** Total sun the sender pays on top of the amount. */\n trxBurn: bigint\n breakdown: TronFeeBreakdown\n}\n\n/** Fee of a transaction in sun (TRX burned), with the estimate behind it. */\nexport interface TronQuote {\n /** = `estimate.trxBurn`. */\n fee: bigint\n /** = `estimate.breakdown.accountCreationFee` (TransferContract to a new account). */\n activationFee: bigint\n estimate: TronFeeEstimate\n}\n\n/** Outcome of a constant call (`/wallet/triggerconstantcontract`) or a balance pre-check. */\nexport interface TronSimulation {\n ok: boolean\n /** `energy_used` reported by the node (0 for non-contract transactions). */\n energy: number\n /** Decoded revert reason / node message when `ok` is false. */\n reason?: string\n /** Raw `constant_result` entries. */\n constantResult?: string[] | undefined\n}\n\n/** What a Tron transaction does. */\nexport type TronTxKind = 'trx-transfer' | 'trc10-transfer' | 'trc20-transfer' | 'trc20-approve' | 'contract-call' | 'freeze' | 'unfreeze' | 'unknown'\n/** Problems a Tron description is flagged with. */\nexport type TronTxWarningCode =\n | 'unlimited-approve' | 'zero-address' | 'unactivated-recipient' | 'memo-fee' | 'expired'\n /** Prebuilt transaction without `raw_data_hex`: described from the unsigned JSON copy, cannot be signed. */\n | 'no-raw-hex'\n /** `raw_data_hex` is not a well-formed Transaction.raw: nothing can be said about it. */\n | 'raw-undecodable'\n /** A contract type or parameter fields the wallet has no decoder for: only the raw bytes are known. */\n | 'undecoded'\n /** More than one contract in the transaction (the node refuses these; the wallet does too). */\n | 'multi-contract'\n /** AccountPermissionUpdateContract: changes who controls the account. */\n | 'account-permission'\n/** One flagged problem, with a sentence a wallet can show. */\nexport interface TronTxWarning { code: TronTxWarningCode; message: string }\n\n/** What a transaction does, decoded offline (see `describeTransaction`). Addresses are base58. */\nexport interface TronTxDescription {\n /** What it does. */\n kind: TronTxKind\n warnings: TronTxWarning[]\n /** Sender (owner_address) when known. */\n from?: string\n /** TRX / TRC-20 recipient. */\n to?: string\n /** sun (TRX) or token base units (TRC-20) or frozen/unfrozen sun. */\n amount?: bigint\n /** TRC-20 contract. */\n token?: string\n /** Spender of a TRC-20 approval. */\n spender?: string\n /** Called contract (contract-call). */\n contract?: string\n /** 4-byte selector, hex. */\n selector?: string\n /** sun attached to the call. */\n callValue?: bigint\n feeLimit?: number\n /** Decoded memo (`raw_data.data`). */\n memo?: string\n /** Freeze / unfreeze resource. */\n resource?: 'BANDWIDTH' | 'ENERGY'\n expiration?: number\n}\n\n/** Outcome of a confirmed Tron transaction. */\nexport interface TronReceipt {\n hash: string\n /** 1 success, 0 failed. */\n status: 0 | 1\n blockNumber: bigint\n fee: bigint\n /** Raw `/wallet/gettransactioninfobyid` payload. */\n raw: Record<string, unknown>\n}\n\n/** CAIP-2 ids of the Tron networks, by name. */\nexport const CAIP2_GENESIS: Record<string, string> = {\n mainnet: 'tron:0x2b6653dc',\n shasta: 'tron:0x94a9059e',\n nile: 'tron:0xcd8690dc',\n}\n","/**\n * Activity history for Tron: a `HistorySource` over TronGrid's account\n * endpoints (`/v1/accounts/{a}/transactions` and `/transactions/trc20`),\n * merged into one `ChainTx` per txID, with the full-node\n * `/wallet/gettransactionbyid` + `/wallet/gettransactioninfobyid` for a single\n * transaction (exact fee, TRC-20 Transfer logs).\n *\n * Both lists page by `max_timestamp` (inclusive, ms), so a page is a time\n * window that is complete across both lists; the cursor carries the window's\n * lower edge plus the txIDs already emitted at exactly that timestamp. Keyless\n * TronGrid allows ~1 request/s per endpoint; pass `apiKey` for more.\n * `fetch` + `AbortSignal.timeout` only — Hermes-safe.\n */\nimport type { ChainCall, ChainTransfer, ChainTx, HistoryPage, HistoryQuery, HistorySource } from '@anywalletkit/core'\nimport { toBase58Address } from './address.js'\nimport { CAIP2_GENESIS } from './types.js'\n\n// ── Public types ─────────────────────────────────────────────────────────────\n\n/** The `fetch` shape the history source uses; pass your own for proxies or tests. */\nexport type HistoryFetch = (\n input: string,\n init?: { method?: string; headers?: Record<string, string>; body?: string; signal?: AbortSignal },\n) => Promise<{ ok: boolean; status: number; json(): Promise<unknown> }>\n\n/** Tron mainnet or the Shasta and Nile testnets. */\nexport type TronNetwork = 'mainnet' | 'shasta' | 'nile'\n\n/** Options for {@link createTronHistory}. */\nexport interface TronHistoryOptions {\n /** TronGrid-compatible root. Default by network: `https://api.trongrid.io`, `https://api.shasta.trongrid.io`, `https://nile.trongrid.io`. */\n apiUrl?: string\n /** `TRON-PRO-API-KEY`. */\n apiKey?: string\n network?: TronNetwork\n fetch?: HistoryFetch\n /** Requests per second. Default 1 without a key (TronGrid's keyless limit), 10 with one. */\n rateLimit?: number\n /** Per request, ms. Default 15 000. */\n timeoutMs?: number\n}\n\nexport interface TronHistoryRaw {\n /** The `/transactions` row (absent when only a TRC-20 transfer to the address was indexed). */\n tx?: unknown\n /** `/transactions/trc20` rows for this txID. */\n trc20: unknown[]\n /** `/wallet/gettransactioninfobyid` (single-transaction reads only). */\n info?: unknown\n spam?: true\n spamReason?: string\n}\n\nexport interface TronChainTx extends ChainTx {\n raw: TronHistoryRaw\n}\n\nexport interface TronHistoryPage extends HistoryPage {\n items: TronChainTx[]\n}\n\n/**\n * Tron history from TronGrid's account endpoints (TRX and TRC-20). Build it with {@link\n * createTronHistory}.\n */\nexport interface TronHistorySource extends HistorySource {\n listActivity(address: string, query?: HistoryQuery): Promise<TronHistoryPage>\n getTransaction(hash: string, address: string): Promise<TronChainTx | undefined>\n}\n\n/** Every configured TronGrid endpoint failed. */\nexport class HistoryUnavailableError extends Error {\n readonly chain: string\n readonly reason: string\n readonly attempts: readonly string[]\n constructor(chain: string, reason: string, attempts: readonly string[] = []) {\n super(`History unavailable for ${chain}: ${reason}`)\n this.name = 'HistoryUnavailableError'\n this.chain = chain\n this.reason = reason\n this.attempts = attempts\n }\n}\n\nconst DEFAULT_LIMIT = 25\nconst MAX_LIMIT = 200\nconst DEFAULT_TIMEOUT_MS = 15_000\nconst DEFAULT_URLS: Record<TronNetwork, string> = { mainnet: 'https://api.trongrid.io', shasta: 'https://api.shasta.trongrid.io', nile: 'https://nile.trongrid.io' }\n/** keccak256(\"Transfer(address,address,uint256)\") */\nexport const TRANSFER_TOPIC = 'ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'\n\n// ── Cursor: time window, base64 JSON ─────────────────────────────────────────\n\nexport interface TronHistoryCursor {\n v: 1\n /** `max_timestamp` (ms, inclusive) for the next page. */\n w: number\n /** txIDs already emitted at exactly `w`. */\n x: string[]\n /** Lists that returned their last row. */\n e: Array<'tx' | 'trc20'>\n}\n\nconst B64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n\nfunction b64encode(s: string): string {\n let out = ''\n for (let i = 0; i < s.length; i += 3) {\n const c = [s.charCodeAt(i), s.charCodeAt(i + 1), s.charCodeAt(i + 2)]\n for (const x of c) if (x > 0xff) throw new Error('cursor must be ASCII')\n const n = (c[0]! << 16) | ((c[1]! || 0) << 8) | (c[2]! || 0)\n out += B64[(n >> 18) & 63]! + B64[(n >> 12) & 63]! + (Number.isNaN(c[1]) ? '=' : B64[(n >> 6) & 63]!) + (Number.isNaN(c[2]) ? '=' : B64[n & 63]!)\n }\n return out\n}\n\nfunction b64decode(s: string): string {\n const clean = s.replace(/[^A-Za-z0-9+/]/g, '')\n let out = ''\n for (let i = 0; i < clean.length; i += 4) {\n const c = [0, 1, 2, 3].map((k) => (i + k < clean.length ? B64.indexOf(clean[i + k]!) : -1))\n if (c[0]! < 0 || c[1]! < 0) throw new Error('bad base64')\n const n = (c[0]! << 18) | (c[1]! << 12) | ((c[2]! < 0 ? 0 : c[2]!) << 6) | (c[3]! < 0 ? 0 : c[3]!)\n out += String.fromCharCode((n >> 16) & 0xff)\n if (c[2]! >= 0) out += String.fromCharCode((n >> 8) & 0xff)\n if (c[3]! >= 0) out += String.fromCharCode(n & 0xff)\n }\n return out\n}\n\nexport function encodeCursor(c: TronHistoryCursor): string {\n return b64encode(JSON.stringify(c))\n}\n\nexport function decodeCursor(s: string): TronHistoryCursor {\n let parsed: unknown\n try {\n parsed = JSON.parse(b64decode(s))\n } catch {\n throw new Error('@anywalletkit/wallet-tron: malformed history cursor')\n }\n const c = parsed as Partial<TronHistoryCursor> | null\n if (!c || c.v !== 1 || typeof c.w !== 'number' || !Array.isArray(c.x) || !Array.isArray(c.e)) throw new Error('@anywalletkit/wallet-tron: malformed history cursor')\n return { v: 1, w: c.w, x: c.x.filter((x): x is string => typeof x === 'string'), e: c.e.filter((x): x is 'tx' | 'trc20' => x === 'tx' || x === 'trc20') }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nclass TokenBucket {\n private tokens: number\n private last = Date.now()\n private chain: Promise<void> = Promise.resolve()\n constructor(private readonly rate: number, private readonly burst = Math.max(1, Math.ceil(rate))) {\n this.tokens = burst\n }\n acquire(): Promise<void> {\n const next = this.chain.then(() => this.take())\n this.chain = next.catch(() => undefined)\n return next\n }\n private refill(): void {\n const now = Date.now()\n this.tokens = Math.min(this.burst, this.tokens + ((now - this.last) / 1000) * this.rate)\n this.last = now\n }\n private async take(): Promise<void> {\n this.refill()\n if (this.tokens >= 1) {\n this.tokens -= 1\n return\n }\n await new Promise((r) => setTimeout(r, Math.ceil(((1 - this.tokens) / this.rate) * 1000)))\n this.refill()\n this.tokens = Math.max(0, this.tokens - 1)\n }\n}\n\nfunction timeoutSignal(ms: number): AbortSignal | undefined {\n const ctor = (globalThis as { AbortSignal?: { timeout?: (ms: number) => AbortSignal } }).AbortSignal\n return typeof ctor?.timeout === 'function' ? ctor.timeout(ms) : undefined\n}\n\nconst big = (v: unknown): bigint => {\n if (typeof v === 'bigint') return v\n if (typeof v === 'number' && Number.isFinite(v)) return BigInt(Math.trunc(v))\n if (typeof v === 'string' && /^-?\\d+$/.test(v)) return BigInt(v)\n return 0n\n}\n\n/** Hex `41…` (or base58) → base58; anything unparsable is returned as-is. */\nconst b58 = (a: unknown): string | undefined => {\n if (typeof a !== 'string' || a.length === 0) return undefined\n try {\n return toBase58Address(a)\n } catch {\n return a\n }\n}\n\n/** 32-byte ABI word → base58 address. */\nconst wordToAddress = (word: string): string => toBase58Address('41' + word.slice(-40).toLowerCase())\n\n// ── TronGrid shapes ──────────────────────────────────────────────────────────\n\ninterface Contract {\n type: string\n parameter: { value: Record<string, unknown> }\n}\nexport interface TronGridTx {\n txID: string\n ret?: Array<{ contractRet?: string; fee?: number }>\n net_fee?: number\n energy_fee?: number\n blockNumber?: number\n block_timestamp?: number\n internal_transactions?: Array<{ caller_address?: string; transferTo_address?: string; callValueInfo?: Array<{ callValue?: number; tokenId?: string }>; rejected?: boolean }>\n raw_data: { contract: Contract[]; data?: string; timestamp?: number }\n}\nexport interface TronGridTrc20 {\n transaction_id: string\n token_info: { symbol?: string; address: string; decimals?: number; name?: string }\n block_timestamp: number\n from: string\n to: string\n type: string\n value: string\n}\nexport interface FullNodeTxInfo {\n id?: string\n fee?: number\n blockNumber?: number\n blockTimeStamp?: number\n receipt?: { result?: string; net_fee?: number; energy_fee?: number }\n log?: Array<{ address: string; topics: string[]; data?: string }>\n}\n\nconst SELF_TYPES_WITH_RECEIVER: Record<string, string> = {\n DelegateResourceContract: 'receiver_address',\n UnDelegateResourceContract: 'receiver_address',\n AccountPermissionUpdateContract: 'owner_address',\n}\n\n/** Decode what a TronGrid / full-node transaction row says on its own (no TRC-20 list rows yet). */\nexport function mapTransactionRow(chain: string, address: string, tx: TronGridTx, extra: { trc20?: TronGridTrc20[]; info?: FullNodeTxInfo } = {}): TronChainTx {\n const contract = tx.raw_data.contract[0]\n const v = contract?.parameter.value ?? {}\n const type = contract?.type ?? 'Unknown'\n const owner = b58(v.owner_address) ?? address\n const transfers: ChainTransfer[] = []\n let call: ChainCall | undefined\n let to: string | null = null\n let nativeValue = 0n\n switch (type) {\n case 'TransferContract': {\n to = b58(v.to_address) ?? null\n nativeValue = big(v.amount)\n if (to && nativeValue > 0n) transfers.push({ token: null, from: owner, to, amount: nativeValue })\n break\n }\n case 'TransferAssetContract': {\n to = b58(v.to_address) ?? null\n const asset = typeof v.asset_name === 'string' ? v.asset_name : undefined\n const amount = big(v.amount)\n // TRC-10 assets are known only by numeric id here (no symbol / decimals without getassetissuebyid); the amount is raw units.\n if (to && asset && amount > 0n) transfers.push({ token: asset, from: owner, to, amount, symbol: `TRC-10 #${asset}`, decimals: 0 })\n break\n }\n case 'TriggerSmartContract': {\n const contractAddress = b58(v.contract_address)\n nativeValue = big(v.call_value)\n if (contractAddress) {\n to = contractAddress\n call = { to: contractAddress }\n const data = typeof v.data === 'string' ? v.data.toLowerCase() : ''\n if (data.length >= 8) {\n call.selector = `0x${data.slice(0, 8)}`\n call.data = `0x${data}`\n }\n if (nativeValue > 0n) transfers.push({ token: null, from: owner, to: contractAddress, amount: nativeValue })\n }\n break\n }\n default: {\n // Staking / resource / permission system contracts: the owner acts on itself (or a receiver).\n const receiverKey = SELF_TYPES_WITH_RECEIVER[type]\n const receiver = receiverKey ? b58(v[receiverKey]) : undefined\n call = { to: receiver ?? owner, method: type }\n to = receiver ?? owner\n }\n }\n for (const it of tx.internal_transactions ?? []) {\n if (it.rejected) continue\n const from = b58(it.caller_address), dest = b58(it.transferTo_address)\n if (!from || !dest) continue\n for (const cv of it.callValueInfo ?? []) {\n const amount = big(cv.callValue)\n if (amount > 0n && !cv.tokenId) transfers.push({ token: null, from, to: dest, amount })\n }\n }\n // TRC-20 legs: list rows first; else Transfer logs from the full node; else the calldata of a plain `transfer(address,uint256)`.\n const trc20 = extra.trc20 ?? []\n if (trc20.length > 0) {\n for (const row of trc20) if (row.type === 'Transfer') transfers.push(trc20Transfer(row))\n } else if (extra.info?.log && extra.info.log.length > 0) {\n for (const log of extra.info.log) {\n if (log.topics[0]?.toLowerCase() !== TRANSFER_TOPIC || log.topics.length < 3) continue\n transfers.push({ token: toBase58Address('41' + log.address.toLowerCase().slice(-40)), from: wordToAddress(log.topics[1]!), to: wordToAddress(log.topics[2]!), amount: BigInt(`0x${log.data || '0'}`), standard: 'trc20' })\n }\n } else if (call?.selector === '0xa9059cbb' && call.data && call.data.length >= 2 + 8 + 128) {\n const words = call.data.slice(10)\n transfers.push({ token: call.to, from: owner, to: wordToAddress(words.slice(0, 64)), amount: BigInt(`0x${words.slice(64, 128)}`), standard: 'trc20' })\n }\n if (call?.selector === '0xa9059cbb' && !call.method) call.method = 'transfer'\n const ret = tx.ret?.[0]\n const result = extra.info?.receipt?.result ?? ret?.contractRet\n const status: ChainTx['status'] = result === undefined ? (tx.blockNumber ? 'confirmed' : 'pending') : result === 'SUCCESS' ? 'confirmed' : 'failed'\n const feeNum = extra.info?.fee ?? (typeof ret?.fee === 'number' ? ret.fee : undefined) ?? (tx.net_fee !== undefined || tx.energy_fee !== undefined ? (tx.net_fee ?? 0) + (tx.energy_fee ?? 0) : undefined)\n const ts = tx.block_timestamp ?? extra.info?.blockTimeStamp ?? tx.raw_data.timestamp\n const blockNumber = tx.blockNumber ?? extra.info?.blockNumber\n const raw: TronHistoryRaw = { tx, trc20 }\n // Unsolicited TRC-10 airdrops (the sender is a stranger, the asset a numeric id) are the chain's spam channel.\n if (contract?.type === 'TransferAssetContract' && owner !== address && to === address) { raw.spam = true; raw.spamReason = 'trc10-airdrop' }\n if (extra.info) raw.info = extra.info\n const out: TronChainTx = { chain, hash: tx.txID, time: ts ? Math.floor(ts / 1000) : 0, status, address, from: owner, to: call?.to ?? to, nativeValue, transfers, raw }\n if (feeNum !== undefined) out.fee = BigInt(Math.trunc(feeNum))\n if (call) out.call = call\n if (blockNumber !== undefined) out.block = BigInt(blockNumber)\n return out\n}\n\nfunction trc20Transfer(row: TronGridTrc20): ChainTransfer {\n const t: ChainTransfer = { token: row.token_info.address, from: row.from, to: row.to, amount: big(row.value), standard: 'trc20' }\n if (row.token_info.symbol !== undefined) t.symbol = row.token_info.symbol\n if (row.token_info.decimals !== undefined) t.decimals = row.token_info.decimals\n return t\n}\n\n/** A transaction seen only through the TRC-20 list (someone else's call that moved tokens to / from the address). */\nexport function mapTrc20Only(chain: string, address: string, rows: TronGridTrc20[]): TronChainTx {\n const first = rows[0]!\n const transfers = rows.filter((r) => r.type === 'Transfer').map(trc20Transfer)\n const primary = transfers.find((t) => t.from === address || t.to === address) ?? transfers[0]\n const out: TronChainTx = {\n chain, hash: first.transaction_id, time: Math.floor(first.block_timestamp / 1000), status: 'confirmed', address,\n from: primary?.from ?? first.from, to: primary?.to ?? first.to, nativeValue: 0n, transfers, raw: { trc20: rows },\n }\n if (transfers.length === 0) {\n // Approval-only rows: the token contract was called.\n out.call = { to: first.token_info.address, method: first.type.toLowerCase() }\n out.to = first.token_info.address\n }\n return out\n}\n\n// ── Source ───────────────────────────────────────────────────────────────────\n\n/** Tronscan link for a transaction. */\nexport function tronExplorerTxUrl(hash: string, network: TronNetwork = 'mainnet'): string {\n const host = network === 'mainnet' ? 'tronscan.org' : `${network}.tronscan.org`\n return `https://${host}/#/transaction/${hash}`\n}\n\n/** A history source for Tron addresses backed by TronGrid or a compatible API. */\nexport function createTronHistory(options: TronHistoryOptions = {}): TronHistorySource {\n const network = options.network ?? 'mainnet'\n const chain = CAIP2_GENESIS[network] ?? CAIP2_GENESIS.mainnet!\n const apiUrl = (options.apiUrl ?? DEFAULT_URLS[network]).replace(/\\/+$/, '')\n const fetchFn: HistoryFetch = options.fetch ?? ((globalThis as { fetch?: HistoryFetch }).fetch as HistoryFetch)\n if (typeof fetchFn !== 'function') throw new Error('@anywalletkit/wallet-tron: no global fetch; pass `fetch` in the options')\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const bucket = new TokenBucket(options.rateLimit ?? (options.apiKey ? 10 : 1))\n const headers = (): Record<string, string> => ({ accept: 'application/json', ...(options.apiKey ? { 'TRON-PRO-API-KEY': options.apiKey } : {}) })\n\n async function request(path: string, init?: { method: 'POST'; body: unknown }): Promise<unknown> {\n await bucket.acquire()\n const url = `${apiUrl}${path}`\n let res: Awaited<ReturnType<HistoryFetch>>\n try {\n const signal = timeoutSignal(timeoutMs)\n res = await fetchFn(url, {\n ...(init ? { method: 'POST', body: JSON.stringify(init.body) } : {}),\n headers: { ...headers(), ...(init ? { 'content-type': 'application/json' } : {}) },\n ...(signal ? { signal } : {}),\n })\n } catch (e) {\n throw new HistoryUnavailableError(chain, `${path}: ${e instanceof Error ? e.message : String(e)}`, [`trongrid: ${e instanceof Error ? e.message : String(e)}`])\n }\n let body: unknown\n try {\n body = await res.json()\n } catch {\n body = undefined\n }\n const b = body as { success?: boolean; error?: string; Error?: string; statusCode?: number } | undefined\n if (!res.ok || b?.success === false || typeof b?.Error === 'string') {\n const msg = b?.error ?? b?.Error ?? `HTTP ${res.status}`\n throw new HistoryUnavailableError(chain, `${path}: ${msg}`, [`trongrid: HTTP ${res.status} ${msg}`])\n }\n return body\n }\n\n async function list<T>(path: string, params: Record<string, string | number | undefined>): Promise<T[]> {\n const q = Object.entries(params).filter(([, v]) => v !== undefined).map(([k, v]) => `${k}=${encodeURIComponent(String(v))}`).join('&')\n const body = (await request(`${path}?${q}`)) as { data?: T[] } | undefined\n return body?.data ?? []\n }\n\n return {\n chain,\n\n async listActivity(address: string, query: HistoryQuery = {}): Promise<TronHistoryPage> {\n const limit = Math.min(MAX_LIMIT, Math.max(1, Math.floor(query.limit ?? DEFAULT_LIMIT)))\n const cursor = query.cursor ? decodeCursor(query.cursor) : undefined\n const exhausted = new Set<'tx' | 'trc20'>(cursor?.e ?? [])\n const skip = new Set(cursor?.x ?? [])\n const common: Record<string, string | number | undefined> = { limit, order_by: 'block_timestamp,desc', max_timestamp: cursor?.w }\n if (query.since !== undefined) common.min_timestamp = query.since * 1000\n const txRows = exhausted.has('tx') ? [] : await list<TronGridTx>(`/v1/accounts/${encodeURIComponent(address)}/transactions`, common)\n const trc20Rows = exhausted.has('trc20') ? [] : await list<TronGridTrc20>(`/v1/accounts/${encodeURIComponent(address)}/transactions/trc20`, common)\n // A list that came back full has more below its last row: the window is complete only above the newest such tail.\n const tails: number[] = []\n if (!exhausted.has('tx') && txRows.length >= limit) tails.push(txRows[txRows.length - 1]!.block_timestamp ?? 0)\n if (!exhausted.has('trc20') && trc20Rows.length >= limit) tails.push(trc20Rows[trc20Rows.length - 1]!.block_timestamp)\n const cutoff = tails.length ? Math.max(...tails) : Number.NEGATIVE_INFINITY\n\n const byId = new Map<string, { ts: number; tx?: TronGridTx; trc20: TronGridTrc20[] }>()\n for (const r of txRows) {\n if (skip.has(r.txID)) continue\n const e = byId.get(r.txID) ?? { ts: r.block_timestamp ?? 0, trc20: [] }\n e.tx = r\n byId.set(r.txID, e)\n }\n for (const r of trc20Rows) {\n if (skip.has(r.transaction_id)) continue\n const e = byId.get(r.transaction_id) ?? { ts: r.block_timestamp, trc20: [] }\n e.trc20.push(r)\n byId.set(r.transaction_id, e)\n }\n let entries = [...byId.entries()].sort((a, b) => b[1].ts - a[1].ts)\n let inWindow = entries.filter(([, e]) => e.ts > cutoff)\n // Degenerate case: everything sits at the cutoff timestamp; emit those and remember them.\n if (inWindow.length === 0 && entries.length > 0) inWindow = entries.filter(([, e]) => e.ts === cutoff)\n entries = inWindow.slice(0, limit)\n const items = entries.map(([, e]) => (e.tx ? mapTransactionRow(chain, address, e.tx, { trc20: e.trc20 }) : mapTrc20Only(chain, address, e.trc20)))\n // A short list is finished only once every row it returned has been emitted (now or on an earlier page).\n const emitted = new Set(entries.map(([id]) => id))\n const done = (id: string) => emitted.has(id) || skip.has(id)\n if (!exhausted.has('tx') && txRows.length < limit && txRows.every((r) => done(r.txID))) exhausted.add('tx')\n if (!exhausted.has('trc20') && trc20Rows.length < limit && trc20Rows.every((r) => done(r.transaction_id))) exhausted.add('trc20')\n const page: TronHistoryPage = { items }\n const more = exhausted.size < 2\n if (more && entries.length > 0) {\n const last = entries[entries.length - 1]![1].ts\n const x = entries.filter(([, e]) => e.ts === last).map(([id]) => id)\n if (last === cursor?.w) for (const id of skip) x.push(id)\n page.cursor = encodeCursor({ v: 1, w: last, x, e: [...exhausted] })\n }\n return page\n },\n\n async getTransaction(hash: string, address: string): Promise<TronChainTx | undefined> {\n const tx = (await request('/wallet/gettransactionbyid', { method: 'POST', body: { value: hash } })) as TronGridTx | Record<string, never> | undefined\n if (!tx || typeof (tx as TronGridTx).txID !== 'string') return undefined\n const info = (await request('/wallet/gettransactioninfobyid', { method: 'POST', body: { value: hash } })) as FullNodeTxInfo | undefined\n return mapTransactionRow(chain, address, tx as TronGridTx, info && typeof info.id === 'string' ? { info } : {})\n },\n\n explorerTxUrl(hash: string): string {\n return tronExplorerTxUrl(hash, network)\n },\n }\n}\n"],"mappings":"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","names":[]}
|