@ironwallet/mcp-server 1.0.3 → 1.2.0

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.
Files changed (82) hide show
  1. package/README.md +6 -2
  2. package/dist/api/balances.d.ts +1 -0
  3. package/dist/api/balances.js +1 -1
  4. package/dist/api/balances.js.map +1 -1
  5. package/dist/api/history/index.d.ts +49 -0
  6. package/dist/api/history/index.js +206 -0
  7. package/dist/api/history/index.js.map +1 -0
  8. package/dist/api/history/merge.d.ts +63 -0
  9. package/dist/api/history/merge.js +208 -0
  10. package/dist/api/history/merge.js.map +1 -0
  11. package/dist/api/history/normalize.d.ts +37 -0
  12. package/dist/api/history/normalize.js +149 -0
  13. package/dist/api/history/normalize.js.map +1 -0
  14. package/dist/api/history/pace.d.ts +8 -0
  15. package/dist/api/history/pace.js +17 -0
  16. package/dist/api/history/pace.js.map +1 -0
  17. package/dist/api/history/providers/blockcypher.d.ts +24 -0
  18. package/dist/api/history/providers/blockcypher.js +70 -0
  19. package/dist/api/history/providers/blockcypher.js.map +1 -0
  20. package/dist/api/history/providers/esplora.d.ts +41 -0
  21. package/dist/api/history/providers/esplora.js +100 -0
  22. package/dist/api/history/providers/esplora.js.map +1 -0
  23. package/dist/api/history/providers/etherscan.d.ts +36 -0
  24. package/dist/api/history/providers/etherscan.js +118 -0
  25. package/dist/api/history/providers/etherscan.js.map +1 -0
  26. package/dist/api/history/providers/nodereal.d.ts +27 -0
  27. package/dist/api/history/providers/nodereal.js +93 -0
  28. package/dist/api/history/providers/nodereal.js.map +1 -0
  29. package/dist/api/history/providers/solana.d.ts +47 -0
  30. package/dist/api/history/providers/solana.js +211 -0
  31. package/dist/api/history/providers/solana.js.map +1 -0
  32. package/dist/api/history/providers/toncenter.d.ts +56 -0
  33. package/dist/api/history/providers/toncenter.js +203 -0
  34. package/dist/api/history/providers/toncenter.js.map +1 -0
  35. package/dist/api/history/providers/trongrid.d.ts +48 -0
  36. package/dist/api/history/providers/trongrid.js +144 -0
  37. package/dist/api/history/providers/trongrid.js.map +1 -0
  38. package/dist/api/history/providers/tronscan.d.ts +55 -0
  39. package/dist/api/history/providers/tronscan.js +153 -0
  40. package/dist/api/history/providers/tronscan.js.map +1 -0
  41. package/dist/api/history/providers/xrp.d.ts +39 -0
  42. package/dist/api/history/providers/xrp.js +150 -0
  43. package/dist/api/history/providers/xrp.js.map +1 -0
  44. package/dist/api/history/types.d.ts +112 -0
  45. package/dist/api/history/types.js +26 -0
  46. package/dist/api/history/types.js.map +1 -0
  47. package/dist/api/swap.d.ts +2 -0
  48. package/dist/api/swap.js +24 -10
  49. package/dist/api/swap.js.map +1 -1
  50. package/dist/config.d.ts +6 -0
  51. package/dist/config.js +66 -0
  52. package/dist/config.js.map +1 -1
  53. package/dist/consent/copy.d.ts +2 -2
  54. package/dist/consent/copy.js +2 -1
  55. package/dist/consent/copy.js.map +1 -1
  56. package/dist/generated/env-config.js +96 -5
  57. package/dist/generated/env-config.js.map +1 -1
  58. package/dist/generated/env-profile.d.ts +7 -0
  59. package/dist/keystore/store.js +33 -4
  60. package/dist/keystore/store.js.map +1 -1
  61. package/dist/npm-registry.d.ts +45 -0
  62. package/dist/npm-registry.js +175 -0
  63. package/dist/npm-registry.js.map +1 -0
  64. package/dist/server.js +3 -0
  65. package/dist/server.js.map +1 -1
  66. package/dist/tools/definitions.d.ts +23 -1
  67. package/dist/tools/definitions.js +72 -20
  68. package/dist/tools/definitions.js.map +1 -1
  69. package/dist/tools/history.d.ts +7 -0
  70. package/dist/tools/history.js +70 -0
  71. package/dist/tools/history.js.map +1 -0
  72. package/dist/tools/index.js +4 -0
  73. package/dist/tools/index.js.map +1 -1
  74. package/dist/tools/runtime.d.ts +8 -0
  75. package/dist/tools/runtime.js +110 -0
  76. package/dist/tools/runtime.js.map +1 -0
  77. package/dist/web/manager.d.ts +6 -0
  78. package/dist/web/manager.js +142 -4
  79. package/dist/web/manager.js.map +1 -1
  80. package/package.json +2 -2
  81. package/server.json +19 -3
  82. package/tools.json +89 -11
@@ -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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"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Transaction history: one normalized shape for every chain.
3
+ *
4
+ * Every provider (Blockscout, NodeReal, TronScan, Esplora, …) is exposed as one
5
+ * or more `HistorySource`s — newest-first paged streams of `SourceItem`s. The
6
+ * merge engine (merge.ts) interleaves the sources of a network by timestamp and
7
+ * keeps an opaque cursor so the agent can page further without duplicates.
8
+ *
9
+ * Strings copied from indexers (token symbols, addresses) are untrusted input;
10
+ * providers must pass them through normalize.ts before they reach the agent.
11
+ */
12
+ import type { NetworkId } from "../../networks.js";
13
+ export type HistoryDirection = "in" | "out" | "self";
14
+ /**
15
+ * transfer — native coin moved (ETH, BNB, TRX, BTC, …)
16
+ * token_transfer — fungible token moved (ERC-20 / TRC-20 / SPL / jetton / IOU)
17
+ * contract_call — the wallet called a contract; no recognised value transfer
18
+ * other — anything else the indexer returned for this address
19
+ */
20
+ export type HistoryKind = "transfer" | "token_transfer" | "contract_call" | "other";
21
+ export type HistoryStatus = "confirmed" | "failed" | "pending";
22
+ export interface HistoryAsset {
23
+ symbol: string;
24
+ /** Token contract / mint / jetton master. Null for the native coin. */
25
+ contractAddress: string | null;
26
+ decimals: number;
27
+ /**
28
+ * Set when the symbol looks like an unsolicited / spam token (contains a
29
+ * link, unusual characters, or mimics another ticker). Indexer data only —
30
+ * never a guarantee either way.
31
+ */
32
+ warning?: string;
33
+ }
34
+ export interface HistoryAmount {
35
+ /** Smallest unit as a decimal string (wei, sun, satoshi, lamports, …). */
36
+ raw: string;
37
+ /** Human readable, formatted with `asset.decimals`. */
38
+ formatted: string;
39
+ }
40
+ export interface HistoryFee extends HistoryAmount {
41
+ /** Native coin symbol the fee was paid in. */
42
+ symbol: string;
43
+ }
44
+ export interface HistoryItem {
45
+ /** Transaction hash / signature. */
46
+ hash: string;
47
+ /** ISO 8601 timestamp; null when the indexer did not return one (pending). */
48
+ timestamp: string | null;
49
+ /** Block height / slot / ledger index; null when pending or unknown. */
50
+ block: number | null;
51
+ kind: HistoryKind;
52
+ direction: HistoryDirection;
53
+ status: HistoryStatus;
54
+ from: string | null;
55
+ to: string | null;
56
+ asset: HistoryAsset;
57
+ amount: HistoryAmount;
58
+ /** Fee paid by this wallet; null when the counterparty paid it or it is unknown. */
59
+ fee: HistoryFee | null;
60
+ }
61
+ /** A normalized item plus the millisecond sort key the merge engine orders by. */
62
+ export interface SourceItem {
63
+ /** Milliseconds since epoch. Pending items use Date.now() so they sort first. */
64
+ ts: number;
65
+ item: HistoryItem;
66
+ }
67
+ export interface SourcePage {
68
+ /** Newest first. */
69
+ items: SourceItem[];
70
+ /** Opaque cursor for the following page; null when this was the last page. */
71
+ next: string | null;
72
+ }
73
+ export interface SourceContext {
74
+ correlationId: string;
75
+ /**
76
+ * Base options for every indexer call: correlation id plus a tighter
77
+ * timeout / retry budget than the general HTTP defaults, so a dead primary
78
+ * hands over to the fallback provider quickly.
79
+ */
80
+ http: {
81
+ correlationId: string;
82
+ timeoutMs: number;
83
+ retries: number;
84
+ };
85
+ }
86
+ /** One newest-first paged stream for a wallet address. */
87
+ export interface HistorySource {
88
+ /** Stable id used inside cursors, e.g. "native", "erc20". */
89
+ name: string;
90
+ fetchPage(pageCursor: string | null, pageSize: number, ctx: SourceContext): Promise<SourcePage>;
91
+ }
92
+ /** A provider bundles the sources of one indexer for one network/address. */
93
+ export interface HistoryProvider {
94
+ /** Label reported to the agent, e.g. "blockscout", "tronscan", "trongrid". */
95
+ label: string;
96
+ sources: HistorySource[];
97
+ }
98
+ export type HistoryApiKind = "etherscan" | "nodereal" | "tronscan" | "trongrid" | "esplora" | "blockcypher" | "solana-rpc" | "toncenter" | "xrp-rpc";
99
+ /** One entry of the per-network provider chain in the baked profile. */
100
+ export interface HistoryApiSpec {
101
+ kind: HistoryApiKind;
102
+ /**
103
+ * API base URL. Omit to reuse the network's existing endpoint from the
104
+ * profile (tronApiUrl, bitcoinApiUrl, solanaRpcUrl, tonApiUrl, xrpRpcUrl, …).
105
+ */
106
+ url?: string;
107
+ }
108
+ export type HistoryApis = Partial<Record<NetworkId, HistoryApiSpec[]>>;
109
+ /** Rows per page: the default is also the cap — one page is one screen of history. */
110
+ export declare const HISTORY_MAX_LIMIT = 20;
111
+ export declare const HISTORY_DEFAULT_LIMIT = 20;
112
+ export declare const HISTORY_API_KINDS: readonly HistoryApiKind[];
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Transaction history: one normalized shape for every chain.
3
+ *
4
+ * Every provider (Blockscout, NodeReal, TronScan, Esplora, …) is exposed as one
5
+ * or more `HistorySource`s — newest-first paged streams of `SourceItem`s. The
6
+ * merge engine (merge.ts) interleaves the sources of a network by timestamp and
7
+ * keeps an opaque cursor so the agent can page further without duplicates.
8
+ *
9
+ * Strings copied from indexers (token symbols, addresses) are untrusted input;
10
+ * providers must pass them through normalize.ts before they reach the agent.
11
+ */
12
+ /** Rows per page: the default is also the cap — one page is one screen of history. */
13
+ export const HISTORY_MAX_LIMIT = 20;
14
+ export const HISTORY_DEFAULT_LIMIT = 20;
15
+ export const HISTORY_API_KINDS = [
16
+ "etherscan",
17
+ "nodereal",
18
+ "tronscan",
19
+ "trongrid",
20
+ "esplora",
21
+ "blockcypher",
22
+ "solana-rpc",
23
+ "toncenter",
24
+ "xrp-rpc",
25
+ ];
26
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/api/history/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwHH,sFAAsF;AACtF,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AACpC,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAExC,MAAM,CAAC,MAAM,iBAAiB,GAA8B;IAC1D,WAAW;IACX,UAAU;IACV,UAAU;IACV,UAAU;IACV,SAAS;IACT,aAAa;IACb,YAAY;IACZ,WAAW;IACX,SAAS;CACV,CAAC"}
@@ -75,6 +75,8 @@ export declare function estimateSwap(token: string, params: {
75
75
  to: SwapSide;
76
76
  maxMode?: boolean;
77
77
  }, opts?: SwapCallOpts): Promise<SwapEstimateResult>;
78
+ export declare function slimSwapDetails(details: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
79
+ export declare function slimSwapPayload(json: Record<string, unknown>): Record<string, unknown>;
78
80
  export interface SwapTxToSign {
79
81
  txId?: string;
80
82
  txData?: string;
package/dist/api/swap.js CHANGED
@@ -255,8 +255,19 @@ function mapEstimate(json) {
255
255
  raw: json,
256
256
  };
257
257
  }
258
- /** Agent-facing swap fees: network / tokenFee / coinFee only. */
259
- const SWAP_FEE_KEYS = ["network", "tokenFee", "coinFee"];
258
+ /** Agent-facing swap fees: tokenFee / coinFee only (no network fee). */
259
+ const SWAP_FEE_KEYS = ["tokenFee", "coinFee"];
260
+ /** Provider extras that confuse agents and are not needed to execute a swap. */
261
+ const SWAP_DROP_KEYS = ["slippage", "slippagePercent", "slippageBps", "networkFee"];
262
+ function omitDroppedKeys(src) {
263
+ const out = {};
264
+ for (const [k, v] of Object.entries(src)) {
265
+ if (SWAP_DROP_KEYS.includes(k))
266
+ continue;
267
+ out[k] = v;
268
+ }
269
+ return out;
270
+ }
260
271
  function pickSwapFees(fees) {
261
272
  if (!fees || typeof fees !== "object" || Array.isArray(fees))
262
273
  return undefined;
@@ -268,17 +279,16 @@ function pickSwapFees(fees) {
268
279
  }
269
280
  return Object.keys(out).length > 0 ? out : undefined;
270
281
  }
271
- function slimSwapDetails(details) {
282
+ export function slimSwapDetails(details) {
272
283
  if (!details)
273
284
  return undefined;
274
- if (!("fees" in details))
275
- return details;
276
- const { fees, ...rest } = details;
285
+ const { fees, ...rest } = omitDroppedKeys(details);
277
286
  const slim = pickSwapFees(fees);
278
- return slim ? { ...rest, fees: slim } : rest;
287
+ const next = slim ? { ...rest, fees: slim } : rest;
288
+ return Object.keys(next).length > 0 ? next : undefined;
279
289
  }
280
- function slimSwapPayload(json) {
281
- const next = { ...json };
290
+ export function slimSwapPayload(json) {
291
+ const next = omitDroppedKeys(json);
282
292
  if ("fees" in next) {
283
293
  const slim = pickSwapFees(next.fees);
284
294
  if (slim)
@@ -287,7 +297,11 @@ function slimSwapPayload(json) {
287
297
  delete next.fees;
288
298
  }
289
299
  if (next.details && typeof next.details === "object" && !Array.isArray(next.details)) {
290
- next.details = slimSwapDetails(next.details);
300
+ const slim = slimSwapDetails(next.details);
301
+ if (slim)
302
+ next.details = slim;
303
+ else
304
+ delete next.details;
291
305
  }
292
306
  return next;
293
307
  }