@ironwallet/mcp-server 1.1.0 → 1.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/README.md +11 -4
- package/dist/api/balances.d.ts +1 -0
- package/dist/api/balances.js +1 -1
- package/dist/api/balances.js.map +1 -1
- package/dist/api/history/index.d.ts +49 -0
- package/dist/api/history/index.js +209 -0
- package/dist/api/history/index.js.map +1 -0
- package/dist/api/history/merge.d.ts +63 -0
- package/dist/api/history/merge.js +208 -0
- package/dist/api/history/merge.js.map +1 -0
- package/dist/api/history/normalize.d.ts +37 -0
- package/dist/api/history/normalize.js +149 -0
- package/dist/api/history/normalize.js.map +1 -0
- package/dist/api/history/pace.d.ts +21 -0
- package/dist/api/history/pace.js +40 -0
- package/dist/api/history/pace.js.map +1 -0
- package/dist/api/history/providers/blockcypher.d.ts +24 -0
- package/dist/api/history/providers/blockcypher.js +70 -0
- package/dist/api/history/providers/blockcypher.js.map +1 -0
- package/dist/api/history/providers/esplora.d.ts +41 -0
- package/dist/api/history/providers/esplora.js +100 -0
- package/dist/api/history/providers/esplora.js.map +1 -0
- package/dist/api/history/providers/etherscan.d.ts +36 -0
- package/dist/api/history/providers/etherscan.js +118 -0
- package/dist/api/history/providers/etherscan.js.map +1 -0
- package/dist/api/history/providers/nodereal.d.ts +27 -0
- package/dist/api/history/providers/nodereal.js +93 -0
- package/dist/api/history/providers/nodereal.js.map +1 -0
- package/dist/api/history/providers/solana.d.ts +47 -0
- package/dist/api/history/providers/solana.js +211 -0
- package/dist/api/history/providers/solana.js.map +1 -0
- package/dist/api/history/providers/ton-shared.d.ts +18 -0
- package/dist/api/history/providers/ton-shared.js +38 -0
- package/dist/api/history/providers/ton-shared.js.map +1 -0
- package/dist/api/history/providers/tonapi.d.ts +52 -0
- package/dist/api/history/providers/tonapi.js +183 -0
- package/dist/api/history/providers/tonapi.js.map +1 -0
- package/dist/api/history/providers/toncenter.d.ts +55 -0
- package/dist/api/history/providers/toncenter.js +191 -0
- package/dist/api/history/providers/toncenter.js.map +1 -0
- package/dist/api/history/providers/trongrid.d.ts +48 -0
- package/dist/api/history/providers/trongrid.js +144 -0
- package/dist/api/history/providers/trongrid.js.map +1 -0
- package/dist/api/history/providers/tronscan.d.ts +55 -0
- package/dist/api/history/providers/tronscan.js +153 -0
- package/dist/api/history/providers/tronscan.js.map +1 -0
- package/dist/api/history/providers/xrp.d.ts +39 -0
- package/dist/api/history/providers/xrp.js +150 -0
- package/dist/api/history/providers/xrp.js.map +1 -0
- package/dist/api/history/types.d.ts +112 -0
- package/dist/api/history/types.js +27 -0
- package/dist/api/history/types.js.map +1 -0
- package/dist/api/swap.d.ts +2 -0
- package/dist/api/swap.js +24 -10
- package/dist/api/swap.js.map +1 -1
- package/dist/config.d.ts +12 -3
- package/dist/config.js +83 -7
- package/dist/config.js.map +1 -1
- package/dist/consent/copy.d.ts +2 -2
- package/dist/consent/copy.js +2 -1
- package/dist/consent/copy.js.map +1 -1
- package/dist/generated/env-config.js +96 -1
- package/dist/generated/env-config.js.map +1 -1
- package/dist/generated/env-profile.d.ts +7 -0
- package/dist/keystore/store.js +33 -4
- package/dist/keystore/store.js.map +1 -1
- package/dist/local-secrets.d.ts +23 -1
- package/dist/local-secrets.js +36 -2
- package/dist/local-secrets.js.map +1 -1
- package/dist/networks.d.ts +3 -0
- package/dist/networks.js +20 -0
- package/dist/networks.js.map +1 -1
- package/dist/npm-registry.d.ts +45 -0
- package/dist/npm-registry.js +175 -0
- package/dist/npm-registry.js.map +1 -0
- package/dist/policy.d.ts +31 -0
- package/dist/policy.js +95 -0
- package/dist/policy.js.map +1 -1
- package/dist/qr/deposit-qr.d.ts +21 -1
- package/dist/qr/deposit-qr.js +100 -21
- package/dist/qr/deposit-qr.js.map +1 -1
- package/dist/qr/font.js +3 -0
- package/dist/qr/font.js.map +1 -1
- package/dist/server.js +3 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/definitions.d.ts +23 -1
- package/dist/tools/definitions.js +87 -29
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/helpers.d.ts +10 -0
- package/dist/tools/helpers.js +26 -0
- package/dist/tools/helpers.js.map +1 -1
- package/dist/tools/history.d.ts +7 -0
- package/dist/tools/history.js +70 -0
- package/dist/tools/history.js.map +1 -0
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/runtime.d.ts +8 -0
- package/dist/tools/runtime.js +110 -0
- package/dist/tools/runtime.js.map +1 -0
- package/dist/tools/swap.d.ts +9 -1
- package/dist/tools/swap.js +41 -7
- package/dist/tools/swap.js.map +1 -1
- package/dist/tools/transfer.d.ts +1 -1
- package/dist/tools/transfer.js +5 -2
- package/dist/tools/transfer.js.map +1 -1
- package/dist/tools/wallets.js +31 -13
- package/dist/tools/wallets.js.map +1 -1
- package/dist/web/manager.d.ts +6 -0
- package/dist/web/manager.js +149 -8
- package/dist/web/manager.js.map +1 -1
- package/package.json +2 -2
- package/server.json +19 -3
- package/tools.json +99 -20
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TronGrid `/v1/accounts/{address}/transactions` (+ `/trc20`). Independent
|
|
3
|
+
* fallback for Tron. Cursor-based via `meta.fingerprint`; addresses in the
|
|
4
|
+
* raw transaction are hex (41…) and are re-encoded to base58 here.
|
|
5
|
+
*/
|
|
6
|
+
import bs58check from "bs58check";
|
|
7
|
+
import { httpJson } from "../../http.js";
|
|
8
|
+
import { paced } from "../pace.js";
|
|
9
|
+
import { amountOf, asString, clampDecimals, directionOf, exactAddressMatcher, feeOf, timeFrom, tokenAsset, toBigInt, toBlockNumber, } from "../normalize.js";
|
|
10
|
+
import { HISTORY_MAX_LIMIT, } from "../types.js";
|
|
11
|
+
/** 41-prefixed hex → base58check "T…" address. Returns the input when it is not hex. */
|
|
12
|
+
export function tronHexToBase58(value) {
|
|
13
|
+
if (!value)
|
|
14
|
+
return null;
|
|
15
|
+
if (!/^(0x)?41[0-9a-fA-F]{40}$/.test(value))
|
|
16
|
+
return value;
|
|
17
|
+
try {
|
|
18
|
+
return bs58check.encode(Buffer.from(value.replace(/^0x/, ""), "hex"));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function mapTronGridTx(tx, address) {
|
|
25
|
+
const hash = asString(tx.txID);
|
|
26
|
+
if (!hash)
|
|
27
|
+
return null;
|
|
28
|
+
const time = timeFrom(tx.block_timestamp);
|
|
29
|
+
const isSelf = exactAddressMatcher(address);
|
|
30
|
+
const contract = tx.raw_data?.contract?.[0];
|
|
31
|
+
const value = contract?.parameter?.value ?? {};
|
|
32
|
+
const type = contract?.type ?? "";
|
|
33
|
+
const from = tronHexToBase58(value.owner_address);
|
|
34
|
+
const to = tronHexToBase58(value.to_address) ?? tronHexToBase58(value.contract_address);
|
|
35
|
+
const direction = directionOf(from, to, isSelf);
|
|
36
|
+
const ret = tx.ret?.[0];
|
|
37
|
+
const status = ret?.contractRet && ret.contractRet !== "SUCCESS" ? "failed" : "confirmed";
|
|
38
|
+
const fee = direction === "in" ? null : feeOf(toBigInt(ret?.fee ?? 0), 6, "TRX");
|
|
39
|
+
const base = {
|
|
40
|
+
hash,
|
|
41
|
+
timestamp: time?.iso ?? null,
|
|
42
|
+
block: toBlockNumber(tx.blockNumber),
|
|
43
|
+
direction,
|
|
44
|
+
status,
|
|
45
|
+
from,
|
|
46
|
+
to,
|
|
47
|
+
fee,
|
|
48
|
+
};
|
|
49
|
+
let item;
|
|
50
|
+
if (type === "TransferContract") {
|
|
51
|
+
item = {
|
|
52
|
+
...base,
|
|
53
|
+
kind: "transfer",
|
|
54
|
+
asset: { symbol: "TRX", contractAddress: null, decimals: 6 },
|
|
55
|
+
amount: amountOf(toBigInt(value.amount), 6),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
else if (type === "TransferAssetContract") {
|
|
59
|
+
// TRC-10: TronGrid gives the asset id as hex ASCII; decimals are not in the
|
|
60
|
+
// payload, so amounts are reported in base units (decimals 0).
|
|
61
|
+
const assetId = value.asset_name ? Buffer.from(value.asset_name, "hex").toString("utf8") : null;
|
|
62
|
+
item = {
|
|
63
|
+
...base,
|
|
64
|
+
kind: "token_transfer",
|
|
65
|
+
asset: tokenAsset(assetId, "TRC10", assetId, 0),
|
|
66
|
+
amount: amountOf(toBigInt(value.amount), 0),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
item = {
|
|
71
|
+
...base,
|
|
72
|
+
kind: type === "TriggerSmartContract" ? "contract_call" : "other",
|
|
73
|
+
asset: { symbol: "TRX", contractAddress: null, decimals: 6 },
|
|
74
|
+
amount: amountOf(toBigInt(value.call_value ?? 0), 6),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return { ts: time?.ts ?? 0, item };
|
|
78
|
+
}
|
|
79
|
+
export function mapTronGridTrc20(row, address) {
|
|
80
|
+
const hash = asString(row.transaction_id);
|
|
81
|
+
const contract = asString(row.token_info?.address);
|
|
82
|
+
if (!hash || !contract)
|
|
83
|
+
return null;
|
|
84
|
+
if (row.type && row.type !== "Transfer")
|
|
85
|
+
return null; // Approval events etc.
|
|
86
|
+
const time = timeFrom(row.block_timestamp);
|
|
87
|
+
const decimals = clampDecimals(row.token_info?.decimals, 6);
|
|
88
|
+
const from = asString(row.from);
|
|
89
|
+
const to = asString(row.to);
|
|
90
|
+
const item = {
|
|
91
|
+
hash,
|
|
92
|
+
timestamp: time?.iso ?? null,
|
|
93
|
+
block: null,
|
|
94
|
+
kind: "token_transfer",
|
|
95
|
+
direction: directionOf(from, to, exactAddressMatcher(address)),
|
|
96
|
+
status: "confirmed",
|
|
97
|
+
from,
|
|
98
|
+
to,
|
|
99
|
+
asset: tokenAsset(row.token_info?.symbol, "TRC20", contract, decimals),
|
|
100
|
+
amount: amountOf(toBigInt(row.value), decimals),
|
|
101
|
+
fee: null,
|
|
102
|
+
};
|
|
103
|
+
return { ts: time?.ts ?? 0, item };
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Keyless TronGrid advertises 3 requests per second per IP, but after a few
|
|
107
|
+
* violations it drops the IP to 1 rps and suspends it for ~5 s on each
|
|
108
|
+
* further burst. Two sources × two pages in parallel trip that on every call,
|
|
109
|
+
* so requests are spaced ≥1.1 s apart process-wide. Slower, but this is the
|
|
110
|
+
* fallback: it has to answer, not to be fast.
|
|
111
|
+
*/
|
|
112
|
+
const KEYLESS_GAP_MS = 1100;
|
|
113
|
+
/**
|
|
114
|
+
* A TronGrid fingerprint is bound to the exact query, `limit` included, so
|
|
115
|
+
* the page size must not follow the caller's `limit`: fixed at the tool cap.
|
|
116
|
+
*/
|
|
117
|
+
const PAGE_SIZE = HISTORY_MAX_LIMIT;
|
|
118
|
+
function makeSource(name, path, baseUrl, address, map) {
|
|
119
|
+
return {
|
|
120
|
+
name,
|
|
121
|
+
async fetchPage(cursor, _pageSize, ctx) {
|
|
122
|
+
const url = `${baseUrl}/v1/accounts/${encodeURIComponent(address)}/transactions${path}` +
|
|
123
|
+
`?limit=${PAGE_SIZE}&order_by=block_timestamp,desc&only_confirmed=true` +
|
|
124
|
+
(cursor ? `&fingerprint=${encodeURIComponent(cursor)}` : "");
|
|
125
|
+
const res = await paced("trongrid", KEYLESS_GAP_MS, () => httpJson(url, { method: "GET" }, { ...ctx.http, label: `history.trongrid${path || ".tx"}` }));
|
|
126
|
+
if (res.success === false || !Array.isArray(res.data)) {
|
|
127
|
+
throw new Error(`trongrid${path}: ${res.error ?? "unexpected response"}`);
|
|
128
|
+
}
|
|
129
|
+
const items = res.data.map((row) => map(row, address)).filter((x) => x !== null);
|
|
130
|
+
const next = res.data.length < PAGE_SIZE ? null : (res.meta?.fingerprint ?? null);
|
|
131
|
+
return { items, next };
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
export function trongridProvider(baseUrl, address) {
|
|
136
|
+
return {
|
|
137
|
+
label: "trongrid",
|
|
138
|
+
sources: [
|
|
139
|
+
makeSource("native", "", baseUrl, address, mapTronGridTx),
|
|
140
|
+
makeSource("trc20", "/trc20", baseUrl, address, mapTronGridTrc20),
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=trongrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trongrid.js","sourceRoot":"","sources":["../../../../src/api/history/providers/trongrid.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,WAAW,EACX,mBAAmB,EACnB,KAAK,EACL,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,aAAa,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,iBAAiB,GAOlB,MAAM,aAAa,CAAC;AAyCrB,wFAAwF;AACxF,MAAM,UAAU,eAAe,CAAC,KAAgC;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1D,IAAI,CAAC;QACH,OAAO,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAc,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,EAAE,CAAC;IAC/C,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,IAAI,EAAE,CAAC;IAClC,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAClD,MAAM,EAAE,GAAG,eAAe,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACxF,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,MAAM,GAAG,GAAG,EAAE,WAAW,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;IAC1F,MAAM,GAAG,GAAG,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACjF,MAAM,IAAI,GAAG;QACX,IAAI;QACJ,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI;QAC5B,KAAK,EAAE,aAAa,CAAC,EAAE,CAAC,WAAW,CAAC;QACpC,SAAS;QACT,MAAM;QACN,IAAI;QACJ,EAAE;QACF,GAAG;KACK,CAAC;IAEX,IAAI,IAAiB,CAAC;IACtB,IAAI,IAAI,KAAK,kBAAkB,EAAE,CAAC;QAChC,IAAI,GAAG;YACL,GAAG,IAAI;YACP,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE;YAC5D,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;SAC5C,CAAC;IACJ,CAAC;SAAM,IAAI,IAAI,KAAK,uBAAuB,EAAE,CAAC;QAC5C,4EAA4E;QAC5E,+DAA+D;QAC/D,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChG,IAAI,GAAG;YACL,GAAG,IAAI;YACP,IAAI,EAAE,gBAAgB;YACtB,KAAK,EAAE,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;YAC/C,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;SAC5C,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,IAAI,GAAG;YACL,GAAG,IAAI;YACP,IAAI,EAAE,IAAI,KAAK,sBAAsB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO;YACjE,KAAK,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE;YAC5D,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;SACrD,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAkB,EAAE,OAAe;IAClE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC,CAAC,uBAAuB;IAC7E,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAgB;QACxB,IAAI;QACJ,SAAS,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI;QAC5B,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,gBAAgB;QACtB,SAAS,EAAE,WAAW,CAAC,IAAI,EAAE,EAAE,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC9D,MAAM,EAAE,WAAW;QACnB,IAAI;QACJ,EAAE;QACF,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC;QACtE,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;QAC/C,GAAG,EAAE,IAAI;KACV,CAAC;IACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC;AACrC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,cAAc,GAAG,IAAI,CAAC;AAE5B;;;GAGG;AACH,MAAM,SAAS,GAAG,iBAAiB,CAAC;AAEpC,SAAS,UAAU,CACjB,IAAY,EACZ,IAAY,EACZ,OAAe,EACf,OAAe,EACf,GAAmD;IAEnD,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,SAAS,CAAC,MAAqB,EAAE,SAAiB,EAAE,GAAkB;YAC1E,MAAM,GAAG,GACP,GAAG,OAAO,gBAAgB,kBAAkB,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE;gBAC3E,UAAU,SAAS,oDAAoD;gBACvE,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,EAAE,CACvD,QAAQ,CACN,GAAG,EACH,EAAE,MAAM,EAAE,KAAK,EAAE,EACjB,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,mBAAmB,IAAI,IAAI,KAAK,EAAE,EAAE,CAC3D,CACF,CAAC;YACF,IAAI,GAAG,CAAC,OAAO,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtD,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,GAAG,CAAC,KAAK,IAAI,qBAAqB,EAAE,CAAC,CAAC;YAC5E,CAAC;YACD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAmB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;YAClG,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,IAAI,IAAI,CAAC,CAAC;YAClF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,OAAe;IAC/D,OAAO;QACL,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE;YACP,UAAU,CAAa,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC;YACrE,UAAU,CAAgB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,CAAC;SACjF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TronScan API (apilist.tronscanapi.com shape), reached through the team's
|
|
3
|
+
* keyless caching proxy at tronscanner.org/api/tron. Two sources:
|
|
4
|
+
* `/transaction` (all transactions of the address, newest first) and
|
|
5
|
+
* `/token_trc20/transfers`. Offset-based (`start` / `limit`), TronScan caps
|
|
6
|
+
* `limit` at 50 — same as the tool's max.
|
|
7
|
+
*/
|
|
8
|
+
import type { HistoryProvider, SourceItem } from "../types.js";
|
|
9
|
+
export interface TronScanTx {
|
|
10
|
+
hash?: string;
|
|
11
|
+
block?: number;
|
|
12
|
+
timestamp?: number;
|
|
13
|
+
ownerAddress?: string;
|
|
14
|
+
toAddress?: string;
|
|
15
|
+
contractType?: number;
|
|
16
|
+
confirmed?: boolean;
|
|
17
|
+
revert?: boolean;
|
|
18
|
+
contractRet?: string;
|
|
19
|
+
amount?: string | number;
|
|
20
|
+
cost?: {
|
|
21
|
+
fee?: number;
|
|
22
|
+
net_fee?: number;
|
|
23
|
+
energy_fee?: number;
|
|
24
|
+
};
|
|
25
|
+
tokenInfo?: {
|
|
26
|
+
tokenId?: string;
|
|
27
|
+
tokenAbbr?: string;
|
|
28
|
+
tokenDecimal?: number;
|
|
29
|
+
tokenType?: string;
|
|
30
|
+
};
|
|
31
|
+
trigger_info?: {
|
|
32
|
+
contract_address?: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export interface TronScanTrc20Transfer {
|
|
36
|
+
transaction_id?: string;
|
|
37
|
+
block?: number;
|
|
38
|
+
block_ts?: number;
|
|
39
|
+
from_address?: string;
|
|
40
|
+
to_address?: string;
|
|
41
|
+
contract_address?: string;
|
|
42
|
+
quant?: string;
|
|
43
|
+
confirmed?: boolean;
|
|
44
|
+
contractRet?: string;
|
|
45
|
+
finalResult?: string;
|
|
46
|
+
revert?: boolean;
|
|
47
|
+
tokenInfo?: {
|
|
48
|
+
tokenId?: string;
|
|
49
|
+
tokenAbbr?: string;
|
|
50
|
+
tokenDecimal?: number;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export declare function mapTronScanTx(tx: TronScanTx, address: string): SourceItem | null;
|
|
54
|
+
export declare function mapTronScanTrc20(row: TronScanTrc20Transfer, address: string): SourceItem | null;
|
|
55
|
+
export declare function tronscanProvider(baseUrl: string, address: string): HistoryProvider;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TronScan API (apilist.tronscanapi.com shape), reached through the team's
|
|
3
|
+
* keyless caching proxy at tronscanner.org/api/tron. Two sources:
|
|
4
|
+
* `/transaction` (all transactions of the address, newest first) and
|
|
5
|
+
* `/token_trc20/transfers`. Offset-based (`start` / `limit`), TronScan caps
|
|
6
|
+
* `limit` at 50 — same as the tool's max.
|
|
7
|
+
*/
|
|
8
|
+
import { httpJson } from "../../http.js";
|
|
9
|
+
import { amountOf, asString, clampDecimals, directionOf, exactAddressMatcher, feeOf, timeFrom, tokenAsset, toBigInt, toBlockNumber, } from "../normalize.js";
|
|
10
|
+
/** TRON contract types that move TRX or TRC-10 (protocol.Transaction.Contract.ContractType). */
|
|
11
|
+
const TRANSFER_CONTRACT = 1;
|
|
12
|
+
const TRANSFER_ASSET_CONTRACT = 2;
|
|
13
|
+
const TRIGGER_SMART_CONTRACT = 31;
|
|
14
|
+
/**
|
|
15
|
+
* TronScan's `confirmed:false` means "not yet solid" (~1 minute), the tx is
|
|
16
|
+
* already in a block. Only rows without a block are reported as pending.
|
|
17
|
+
*/
|
|
18
|
+
function tronStatus(block, ret, revert) {
|
|
19
|
+
if (revert || (ret && ret !== "SUCCESS"))
|
|
20
|
+
return "failed";
|
|
21
|
+
return typeof block === "number" && block > 0 ? "confirmed" : "pending";
|
|
22
|
+
}
|
|
23
|
+
export function mapTronScanTx(tx, address) {
|
|
24
|
+
const hash = asString(tx.hash);
|
|
25
|
+
if (!hash)
|
|
26
|
+
return null;
|
|
27
|
+
const time = timeFrom(tx.timestamp);
|
|
28
|
+
const isSelf = exactAddressMatcher(address);
|
|
29
|
+
const from = asString(tx.ownerAddress);
|
|
30
|
+
const to = asString(tx.toAddress) ?? asString(tx.trigger_info?.contract_address);
|
|
31
|
+
const direction = directionOf(from, to, isSelf);
|
|
32
|
+
const status = tronStatus(tx.block, tx.contractRet, tx.revert);
|
|
33
|
+
const feeRaw = toBigInt(tx.cost?.fee ?? 0);
|
|
34
|
+
const amount = toBigInt(tx.amount);
|
|
35
|
+
const contractType = tx.contractType;
|
|
36
|
+
let item;
|
|
37
|
+
if (contractType === TRANSFER_CONTRACT) {
|
|
38
|
+
item = {
|
|
39
|
+
hash,
|
|
40
|
+
timestamp: time?.iso ?? null,
|
|
41
|
+
block: toBlockNumber(tx.block),
|
|
42
|
+
kind: "transfer",
|
|
43
|
+
direction,
|
|
44
|
+
status,
|
|
45
|
+
from,
|
|
46
|
+
to,
|
|
47
|
+
asset: { symbol: "TRX", contractAddress: null, decimals: 6 },
|
|
48
|
+
amount: amountOf(amount, 6),
|
|
49
|
+
fee: direction === "in" ? null : feeOf(feeRaw, 6, "TRX"),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
else if (contractType === TRANSFER_ASSET_CONTRACT) {
|
|
53
|
+
const decimals = clampDecimals(tx.tokenInfo?.tokenDecimal, 6);
|
|
54
|
+
item = {
|
|
55
|
+
hash,
|
|
56
|
+
timestamp: time?.iso ?? null,
|
|
57
|
+
block: toBlockNumber(tx.block),
|
|
58
|
+
kind: "token_transfer",
|
|
59
|
+
direction,
|
|
60
|
+
status,
|
|
61
|
+
from,
|
|
62
|
+
to,
|
|
63
|
+
asset: tokenAsset(tx.tokenInfo?.tokenAbbr, "TRC10", asString(tx.tokenInfo?.tokenId), decimals),
|
|
64
|
+
amount: amountOf(amount, decimals),
|
|
65
|
+
fee: direction === "in" ? null : feeOf(feeRaw, 6, "TRX"),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
// TriggerSmartContract and everything else. TRC-20 amounts come from the
|
|
70
|
+
// dedicated transfers source; here we only record the call (and TRX sent
|
|
71
|
+
// along with it via call_value, which TronScan reports as `amount`).
|
|
72
|
+
item = {
|
|
73
|
+
hash,
|
|
74
|
+
timestamp: time?.iso ?? null,
|
|
75
|
+
block: toBlockNumber(tx.block),
|
|
76
|
+
kind: contractType === TRIGGER_SMART_CONTRACT ? "contract_call" : "other",
|
|
77
|
+
direction,
|
|
78
|
+
status,
|
|
79
|
+
from,
|
|
80
|
+
to,
|
|
81
|
+
asset: { symbol: "TRX", contractAddress: null, decimals: 6 },
|
|
82
|
+
amount: amountOf(amount, 6),
|
|
83
|
+
fee: direction === "in" ? null : feeOf(feeRaw, 6, "TRX"),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return { ts: time?.ts ?? 0, item };
|
|
87
|
+
}
|
|
88
|
+
export function mapTronScanTrc20(row, address) {
|
|
89
|
+
const hash = asString(row.transaction_id);
|
|
90
|
+
const contract = asString(row.contract_address) ?? asString(row.tokenInfo?.tokenId);
|
|
91
|
+
if (!hash || !contract)
|
|
92
|
+
return null;
|
|
93
|
+
const time = timeFrom(row.block_ts);
|
|
94
|
+
const isSelf = exactAddressMatcher(address);
|
|
95
|
+
const from = asString(row.from_address);
|
|
96
|
+
const to = asString(row.to_address);
|
|
97
|
+
const decimals = clampDecimals(row.tokenInfo?.tokenDecimal, 6);
|
|
98
|
+
const item = {
|
|
99
|
+
hash,
|
|
100
|
+
timestamp: time?.iso ?? null,
|
|
101
|
+
block: toBlockNumber(row.block),
|
|
102
|
+
kind: "token_transfer",
|
|
103
|
+
direction: directionOf(from, to, isSelf),
|
|
104
|
+
status: tronStatus(row.block, row.finalResult ?? row.contractRet, row.revert),
|
|
105
|
+
from,
|
|
106
|
+
to,
|
|
107
|
+
asset: tokenAsset(row.tokenInfo?.tokenAbbr, "TRC20", contract, decimals),
|
|
108
|
+
amount: amountOf(toBigInt(row.quant), decimals),
|
|
109
|
+
// The TRX fee sits on the transaction row (same hash) in the "native" source.
|
|
110
|
+
fee: null,
|
|
111
|
+
};
|
|
112
|
+
return { ts: time?.ts ?? 0, item };
|
|
113
|
+
}
|
|
114
|
+
function offsetOf(cursor) {
|
|
115
|
+
if (cursor === null)
|
|
116
|
+
return 0;
|
|
117
|
+
const n = Number.parseInt(cursor, 10);
|
|
118
|
+
if (!Number.isInteger(n) || n < 0)
|
|
119
|
+
throw new Error("Invalid cursor for tronscan source.");
|
|
120
|
+
return n;
|
|
121
|
+
}
|
|
122
|
+
export function tronscanProvider(baseUrl, address) {
|
|
123
|
+
const native = {
|
|
124
|
+
name: "native",
|
|
125
|
+
async fetchPage(cursor, pageSize, ctx) {
|
|
126
|
+
const start = offsetOf(cursor);
|
|
127
|
+
const url = `${baseUrl}/transaction?address=${encodeURIComponent(address)}` +
|
|
128
|
+
`&limit=${pageSize}&start=${start}&sort=-timestamp&count=true`;
|
|
129
|
+
const res = await httpJson(url, { method: "GET" }, { ...ctx.http, label: "history.tronscan.transaction" });
|
|
130
|
+
const rows = Array.isArray(res.data) ? res.data : null;
|
|
131
|
+
if (!rows)
|
|
132
|
+
throw new Error("tronscan transaction: unexpected response");
|
|
133
|
+
const items = rows.map((tx) => mapTronScanTx(tx, address)).filter((x) => x !== null);
|
|
134
|
+
return { items, next: rows.length < pageSize ? null : String(start + rows.length) };
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
const trc20 = {
|
|
138
|
+
name: "trc20",
|
|
139
|
+
async fetchPage(cursor, pageSize, ctx) {
|
|
140
|
+
const start = offsetOf(cursor);
|
|
141
|
+
const url = `${baseUrl}/token_trc20/transfers?relatedAddress=${encodeURIComponent(address)}` +
|
|
142
|
+
`&limit=${pageSize}&start=${start}`;
|
|
143
|
+
const res = await httpJson(url, { method: "GET" }, { ...ctx.http, label: "history.tronscan.trc20" });
|
|
144
|
+
const rows = Array.isArray(res.token_transfers) ? res.token_transfers : null;
|
|
145
|
+
if (!rows)
|
|
146
|
+
throw new Error("tronscan token_trc20/transfers: unexpected response");
|
|
147
|
+
const items = rows.map((row) => mapTronScanTrc20(row, address)).filter((x) => x !== null);
|
|
148
|
+
return { items, next: rows.length < pageSize ? null : String(start + rows.length) };
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
return { label: "tronscan", sources: [native, trc20] };
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=tronscan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tronscan.js","sourceRoot":"","sources":["../../../../src/api/history/providers/tronscan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XRP Ledger `account_tx` (rippled JSON-RPC). Newest first with `forward:false`;
|
|
3
|
+
* the page cursor is the JSON `marker`. Payments in XRP report drops; issued
|
|
4
|
+
* currencies (IOUs) are decimal strings on the ledger, so for them `raw` and
|
|
5
|
+
* `formatted` are the same decimal value with `decimals: 0`. Memos are not
|
|
6
|
+
* surfaced (free-form text from strangers).
|
|
7
|
+
*/
|
|
8
|
+
import type { HistoryProvider, SourceItem } from "../types.js";
|
|
9
|
+
type XrpAmount = string | {
|
|
10
|
+
currency?: string;
|
|
11
|
+
issuer?: string;
|
|
12
|
+
value?: string;
|
|
13
|
+
};
|
|
14
|
+
interface XrpTxJson {
|
|
15
|
+
TransactionType?: string;
|
|
16
|
+
Account?: string;
|
|
17
|
+
Destination?: string;
|
|
18
|
+
Amount?: XrpAmount;
|
|
19
|
+
DeliverMax?: XrpAmount;
|
|
20
|
+
Fee?: string;
|
|
21
|
+
date?: number;
|
|
22
|
+
hash?: string;
|
|
23
|
+
ledger_index?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface XrpAccountTxEntry {
|
|
26
|
+
tx?: XrpTxJson;
|
|
27
|
+
tx_json?: XrpTxJson;
|
|
28
|
+
hash?: string;
|
|
29
|
+
ledger_index?: number;
|
|
30
|
+
close_time_iso?: string;
|
|
31
|
+
validated?: boolean;
|
|
32
|
+
meta?: {
|
|
33
|
+
TransactionResult?: string;
|
|
34
|
+
delivered_amount?: XrpAmount;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export declare function mapXrpEntry(entry: XrpAccountTxEntry, address: string): SourceItem | null;
|
|
38
|
+
export declare function xrpProvider(rpcUrl: string, address: string): HistoryProvider;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XRP Ledger `account_tx` (rippled JSON-RPC). Newest first with `forward:false`;
|
|
3
|
+
* the page cursor is the JSON `marker`. Payments in XRP report drops; issued
|
|
4
|
+
* currencies (IOUs) are decimal strings on the ledger, so for them `raw` and
|
|
5
|
+
* `formatted` are the same decimal value with `decimals: 0`. Memos are not
|
|
6
|
+
* surfaced (free-form text from strangers).
|
|
7
|
+
*/
|
|
8
|
+
import { httpJson } from "../../http.js";
|
|
9
|
+
import { amountOf, asString, feeOf, sanitizeSymbol, toBigInt, tokenAsset } from "../normalize.js";
|
|
10
|
+
/** Seconds between the Unix epoch and the Ripple epoch (2000-01-01). */
|
|
11
|
+
const RIPPLE_EPOCH_OFFSET = 946684800;
|
|
12
|
+
/** 160-bit hex currency codes are ASCII padded with zeros. */
|
|
13
|
+
function currencyCode(code) {
|
|
14
|
+
if (!code)
|
|
15
|
+
return "IOU";
|
|
16
|
+
if (/^[0-9A-F]{40}$/i.test(code)) {
|
|
17
|
+
const ascii = Buffer.from(code, "hex").toString("latin1").replace(/\0+$/, "");
|
|
18
|
+
return sanitizeSymbol(ascii, "IOU");
|
|
19
|
+
}
|
|
20
|
+
return sanitizeSymbol(code, "IOU");
|
|
21
|
+
}
|
|
22
|
+
export function mapXrpEntry(entry, address) {
|
|
23
|
+
const tx = entry.tx ?? entry.tx_json;
|
|
24
|
+
if (!tx)
|
|
25
|
+
return null;
|
|
26
|
+
const hash = asString(tx.hash) ?? asString(entry.hash);
|
|
27
|
+
if (!hash)
|
|
28
|
+
return null;
|
|
29
|
+
let ts = null;
|
|
30
|
+
let iso = null;
|
|
31
|
+
if (typeof tx.date === "number") {
|
|
32
|
+
ts = (tx.date + RIPPLE_EPOCH_OFFSET) * 1000;
|
|
33
|
+
iso = new Date(ts).toISOString();
|
|
34
|
+
}
|
|
35
|
+
else if (entry.close_time_iso) {
|
|
36
|
+
const parsed = Date.parse(entry.close_time_iso);
|
|
37
|
+
if (!Number.isNaN(parsed)) {
|
|
38
|
+
ts = parsed;
|
|
39
|
+
iso = new Date(parsed).toISOString();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const result = entry.meta?.TransactionResult;
|
|
43
|
+
const status = entry.validated === false ? "pending" : result && result !== "tesSUCCESS" ? "failed" : "confirmed";
|
|
44
|
+
const from = asString(tx.Account);
|
|
45
|
+
const to = asString(tx.Destination);
|
|
46
|
+
const fromSelf = from === address;
|
|
47
|
+
const toSelf = to === address;
|
|
48
|
+
const direction = fromSelf && toSelf ? "self" : fromSelf ? "out" : "in";
|
|
49
|
+
const fee = fromSelf ? feeOf(toBigInt(tx.Fee ?? 0), 6, "XRP") : null;
|
|
50
|
+
const ledger = tx.ledger_index ?? entry.ledger_index ?? null;
|
|
51
|
+
let item;
|
|
52
|
+
if (tx.TransactionType === "Payment") {
|
|
53
|
+
const delivered = entry.meta?.delivered_amount ?? tx.Amount ?? tx.DeliverMax;
|
|
54
|
+
if (typeof delivered === "string" || delivered === undefined) {
|
|
55
|
+
item = {
|
|
56
|
+
hash,
|
|
57
|
+
timestamp: iso,
|
|
58
|
+
block: ledger,
|
|
59
|
+
kind: "transfer",
|
|
60
|
+
direction,
|
|
61
|
+
status,
|
|
62
|
+
from,
|
|
63
|
+
to,
|
|
64
|
+
asset: { symbol: "XRP", contractAddress: null, decimals: 6 },
|
|
65
|
+
amount: amountOf(toBigInt(delivered ?? "0"), 6),
|
|
66
|
+
fee,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
const value = typeof delivered.value === "string" && /^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(delivered.value)
|
|
71
|
+
? delivered.value.replace(/^-/, "")
|
|
72
|
+
: "0";
|
|
73
|
+
item = {
|
|
74
|
+
hash,
|
|
75
|
+
timestamp: iso,
|
|
76
|
+
block: ledger,
|
|
77
|
+
kind: "token_transfer",
|
|
78
|
+
direction,
|
|
79
|
+
status,
|
|
80
|
+
from,
|
|
81
|
+
to,
|
|
82
|
+
asset: tokenAsset(currencyCode(delivered.currency), "IOU", asString(delivered.issuer), 0),
|
|
83
|
+
amount: { raw: value, formatted: value },
|
|
84
|
+
fee,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
item = {
|
|
90
|
+
hash,
|
|
91
|
+
timestamp: iso,
|
|
92
|
+
block: ledger,
|
|
93
|
+
kind: "other",
|
|
94
|
+
direction: fromSelf ? "out" : "in",
|
|
95
|
+
status,
|
|
96
|
+
from,
|
|
97
|
+
to: to ?? (fromSelf ? null : address),
|
|
98
|
+
asset: { symbol: "XRP", contractAddress: null, decimals: 6 },
|
|
99
|
+
amount: amountOf(0n, 6),
|
|
100
|
+
fee,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return { ts: ts ?? 0, item };
|
|
104
|
+
}
|
|
105
|
+
export function xrpProvider(rpcUrl, address) {
|
|
106
|
+
const source = {
|
|
107
|
+
name: "xrp",
|
|
108
|
+
async fetchPage(cursor, pageSize, ctx) {
|
|
109
|
+
let marker;
|
|
110
|
+
if (cursor !== null) {
|
|
111
|
+
try {
|
|
112
|
+
marker = JSON.parse(cursor);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
throw new Error("Invalid cursor for xrp source.");
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const res = await httpJson(rpcUrl, {
|
|
119
|
+
method: "POST",
|
|
120
|
+
headers: { "Content-Type": "application/json" },
|
|
121
|
+
body: JSON.stringify({
|
|
122
|
+
method: "account_tx",
|
|
123
|
+
params: [
|
|
124
|
+
{
|
|
125
|
+
account: address,
|
|
126
|
+
limit: pageSize,
|
|
127
|
+
ledger_index_min: -1,
|
|
128
|
+
ledger_index_max: -1,
|
|
129
|
+
forward: false,
|
|
130
|
+
...(marker !== undefined ? { marker } : {}),
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
}),
|
|
134
|
+
}, { ...ctx.http, label: "history.xrp.account_tx", retry: true });
|
|
135
|
+
const result = res.result ?? {};
|
|
136
|
+
if (result.error === "actNotFound")
|
|
137
|
+
return { items: [], next: null };
|
|
138
|
+
if (result.status !== "success" || !Array.isArray(result.transactions)) {
|
|
139
|
+
throw new Error(`xrp account_tx: ${result.error_message ?? result.error ?? "unexpected response"}`);
|
|
140
|
+
}
|
|
141
|
+
const items = result.transactions
|
|
142
|
+
.map((entry) => mapXrpEntry(entry, address))
|
|
143
|
+
.filter((x) => x !== null);
|
|
144
|
+
const next = result.marker !== undefined && result.marker !== null ? JSON.stringify(result.marker) : null;
|
|
145
|
+
return { items, next };
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
return { label: "xrpl", sources: [source] };
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=xrp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xrp.js","sourceRoot":"","sources":["../../../../src/api/history/providers/xrp.ts"],"names":[],"mappings":"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"}
|