@persistenceone/bridgekitty 0.3.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.
- package/LICENSE +21 -0
- package/README.md +232 -0
- package/dist/backends/across.d.ts +10 -0
- package/dist/backends/across.js +285 -0
- package/dist/backends/debridge.d.ts +11 -0
- package/dist/backends/debridge.js +380 -0
- package/dist/backends/lifi.d.ts +19 -0
- package/dist/backends/lifi.js +295 -0
- package/dist/backends/persistence.d.ts +86 -0
- package/dist/backends/persistence.js +642 -0
- package/dist/backends/relay.d.ts +11 -0
- package/dist/backends/relay.js +292 -0
- package/dist/backends/squid.d.ts +31 -0
- package/dist/backends/squid.js +476 -0
- package/dist/backends/types.d.ts +125 -0
- package/dist/backends/types.js +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +154 -0
- package/dist/routing/engine.d.ts +49 -0
- package/dist/routing/engine.js +336 -0
- package/dist/tools/check-status.d.ts +3 -0
- package/dist/tools/check-status.js +93 -0
- package/dist/tools/execute-bridge.d.ts +3 -0
- package/dist/tools/execute-bridge.js +428 -0
- package/dist/tools/get-chains.d.ts +3 -0
- package/dist/tools/get-chains.js +162 -0
- package/dist/tools/get-quote.d.ts +3 -0
- package/dist/tools/get-quote.js +534 -0
- package/dist/tools/get-tokens.d.ts +3 -0
- package/dist/tools/get-tokens.js +128 -0
- package/dist/tools/help.d.ts +2 -0
- package/dist/tools/help.js +204 -0
- package/dist/tools/multi-quote.d.ts +3 -0
- package/dist/tools/multi-quote.js +310 -0
- package/dist/tools/onboard.d.ts +3 -0
- package/dist/tools/onboard.js +218 -0
- package/dist/tools/wallet.d.ts +14 -0
- package/dist/tools/wallet.js +744 -0
- package/dist/tools/xprt-farm.d.ts +3 -0
- package/dist/tools/xprt-farm.js +1308 -0
- package/dist/tools/xprt-rewards.d.ts +2 -0
- package/dist/tools/xprt-rewards.js +177 -0
- package/dist/tools/xprt-staking.d.ts +2 -0
- package/dist/tools/xprt-staking.js +565 -0
- package/dist/utils/chains.d.ts +22 -0
- package/dist/utils/chains.js +154 -0
- package/dist/utils/circuit-breaker.d.ts +64 -0
- package/dist/utils/circuit-breaker.js +160 -0
- package/dist/utils/evm.d.ts +18 -0
- package/dist/utils/evm.js +46 -0
- package/dist/utils/fill-detector.d.ts +70 -0
- package/dist/utils/fill-detector.js +298 -0
- package/dist/utils/gas-estimator.d.ts +67 -0
- package/dist/utils/gas-estimator.js +340 -0
- package/dist/utils/sanitize-error.d.ts +23 -0
- package/dist/utils/sanitize-error.js +101 -0
- package/dist/utils/token-registry.d.ts +70 -0
- package/dist/utils/token-registry.js +669 -0
- package/dist/utils/tokens.d.ts +17 -0
- package/dist/utils/tokens.js +37 -0
- package/dist/utils/tx-simulator.d.ts +27 -0
- package/dist/utils/tx-simulator.js +105 -0
- package/package.json +75 -0
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verified Token Registry
|
|
3
|
+
*
|
|
4
|
+
* Security-first token symbol resolution. Only resolves to verified, canonical
|
|
5
|
+
* token addresses from official deployments. NEVER falls back to unverified tokens.
|
|
6
|
+
*
|
|
7
|
+
* Sources:
|
|
8
|
+
* - Circle's official USDC deployments
|
|
9
|
+
* - Tether's official USDT deployments
|
|
10
|
+
* - LI.FI's verified token list
|
|
11
|
+
* - CoinGecko verified contracts
|
|
12
|
+
* - Official bridge/wrapper contracts per chain
|
|
13
|
+
*
|
|
14
|
+
* If a token is not in this registry, resolution fails with a clear error.
|
|
15
|
+
* Agents can always pass raw 0x addresses to bypass the registry.
|
|
16
|
+
*/
|
|
17
|
+
import { getChainName, PERSISTENCE_CHAIN_ID, COSMOSHUB_CHAIN_ID, SOLANA_CHAIN_ID } from "./chains.js";
|
|
18
|
+
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
19
|
+
const NATIVE = "0x0000000000000000000000000000000000000000";
|
|
20
|
+
// ─── Chain IDs ──────────────────────────────────────────────────────────────
|
|
21
|
+
// Documented here for reference:
|
|
22
|
+
// 1 = Ethereum
|
|
23
|
+
// 10 = Optimism
|
|
24
|
+
// 56 = BNB Chain (BSC)
|
|
25
|
+
// 137 = Polygon
|
|
26
|
+
// 324 = zkSync Era
|
|
27
|
+
// 5000 = Mantle
|
|
28
|
+
// 8453 = Base
|
|
29
|
+
// 34443 = Mode
|
|
30
|
+
// 42161 = Arbitrum
|
|
31
|
+
// 43114 = Avalanche
|
|
32
|
+
// 59144 = Linea
|
|
33
|
+
// 81457 = Blast
|
|
34
|
+
// 534352 = Scroll
|
|
35
|
+
// 7777777 = Zora
|
|
36
|
+
// ─── Verified Token Registry ────────────────────────────────────────────────
|
|
37
|
+
export const VERIFIED_TOKENS = [
|
|
38
|
+
// ── Native Tokens ──────────────────────────────────────────────────────
|
|
39
|
+
{
|
|
40
|
+
symbol: "ETH",
|
|
41
|
+
name: "Ethereum",
|
|
42
|
+
decimals: 18,
|
|
43
|
+
addresses: {
|
|
44
|
+
1: NATIVE,
|
|
45
|
+
10: NATIVE,
|
|
46
|
+
42161: NATIVE,
|
|
47
|
+
8453: NATIVE,
|
|
48
|
+
59144: NATIVE,
|
|
49
|
+
534352: NATIVE,
|
|
50
|
+
324: NATIVE,
|
|
51
|
+
81457: NATIVE,
|
|
52
|
+
7777777: NATIVE,
|
|
53
|
+
34443: NATIVE,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
symbol: "BNB",
|
|
58
|
+
name: "BNB",
|
|
59
|
+
decimals: 18,
|
|
60
|
+
addresses: {
|
|
61
|
+
56: NATIVE,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
symbol: "MATIC",
|
|
66
|
+
name: "Polygon",
|
|
67
|
+
decimals: 18,
|
|
68
|
+
addresses: {
|
|
69
|
+
137: NATIVE,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
// POL is the rebranded MATIC — same native token on Polygon
|
|
74
|
+
symbol: "POL",
|
|
75
|
+
name: "Polygon (POL)",
|
|
76
|
+
decimals: 18,
|
|
77
|
+
addresses: {
|
|
78
|
+
137: NATIVE,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
symbol: "AVAX",
|
|
83
|
+
name: "Avalanche",
|
|
84
|
+
decimals: 18,
|
|
85
|
+
addresses: {
|
|
86
|
+
43114: NATIVE,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
symbol: "MNT",
|
|
91
|
+
name: "Mantle",
|
|
92
|
+
decimals: 18,
|
|
93
|
+
addresses: {
|
|
94
|
+
5000: NATIVE,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
// ── Stablecoins ────────────────────────────────────────────────────────
|
|
98
|
+
{
|
|
99
|
+
// Circle's official native USDC deployments
|
|
100
|
+
symbol: "USDC",
|
|
101
|
+
name: "USD Coin",
|
|
102
|
+
decimals: 6,
|
|
103
|
+
decimalOverrides: { 56: 18 }, // BSC Binance-Peg uses 18 decimals
|
|
104
|
+
addresses: {
|
|
105
|
+
1: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // Ethereum
|
|
106
|
+
10: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", // Optimism (native)
|
|
107
|
+
56: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d", // BSC (Binance-Peg, 18 decimals!)
|
|
108
|
+
137: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", // Polygon (native)
|
|
109
|
+
42161: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // Arbitrum (native)
|
|
110
|
+
8453: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base (native)
|
|
111
|
+
43114: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E", // Avalanche (native)
|
|
112
|
+
[SOLANA_CHAIN_ID]: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // Solana (native)
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
// Bridged USDC.e (older, being deprecated in favor of native USDC)
|
|
117
|
+
symbol: "USDC.E",
|
|
118
|
+
name: "Bridged USD Coin",
|
|
119
|
+
decimals: 6,
|
|
120
|
+
addresses: {
|
|
121
|
+
10: "0x7F5c764cBc14f9669B88837ca1490cCa17c31607", // Optimism
|
|
122
|
+
137: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // Polygon
|
|
123
|
+
42161: "0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8", // Arbitrum
|
|
124
|
+
43114: "0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664", // Avalanche
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
symbol: "USDT",
|
|
129
|
+
name: "Tether USD",
|
|
130
|
+
decimals: 6,
|
|
131
|
+
decimalOverrides: { 56: 18 }, // BSC Binance-Peg uses 18 decimals
|
|
132
|
+
addresses: {
|
|
133
|
+
1: "0xdAC17F958D2ee523a2206206994597C13D831ec7", // Ethereum
|
|
134
|
+
10: "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58", // Optimism
|
|
135
|
+
56: "0x55d398326f99059fF775485246999027B3197955", // BSC (Binance-Peg, 18 decimals!)
|
|
136
|
+
137: "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", // Polygon
|
|
137
|
+
42161: "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9", // Arbitrum
|
|
138
|
+
43114: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7", // Avalanche
|
|
139
|
+
8453: "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2", // Base
|
|
140
|
+
[SOLANA_CHAIN_ID]: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB", // Solana
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
symbol: "DAI",
|
|
145
|
+
name: "Dai Stablecoin",
|
|
146
|
+
decimals: 18,
|
|
147
|
+
addresses: {
|
|
148
|
+
1: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // Ethereum
|
|
149
|
+
10: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", // Optimism
|
|
150
|
+
137: "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", // Polygon
|
|
151
|
+
42161: "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1", // Arbitrum
|
|
152
|
+
43114: "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70", // Avalanche
|
|
153
|
+
8453: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", // Base
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
symbol: "USDS",
|
|
158
|
+
name: "USDS (Sky Dollar)",
|
|
159
|
+
decimals: 18,
|
|
160
|
+
addresses: {
|
|
161
|
+
1: "0xdC035D45d973E3EC169d2276DDab16f1e407384F", // Ethereum
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
symbol: "FRAX",
|
|
166
|
+
name: "Frax",
|
|
167
|
+
decimals: 18,
|
|
168
|
+
addresses: {
|
|
169
|
+
1: "0x853d955aCEf822Db058eb8505911ED77F175b99e", // Ethereum
|
|
170
|
+
10: "0x2E3D870790dC77A83DD1d22184567a97112523ab", // Optimism
|
|
171
|
+
137: "0x45c32fA6DF82ead1e2EF74d17b76547EDdFaFF89", // Polygon
|
|
172
|
+
42161: "0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F", // Arbitrum
|
|
173
|
+
43114: "0xD24C2Ad096400B6FBcd2ad8B24E7acBc21A1da64", // Avalanche
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
symbol: "GHO",
|
|
178
|
+
name: "GHO (Aave)",
|
|
179
|
+
decimals: 18,
|
|
180
|
+
addresses: {
|
|
181
|
+
1: "0x40D16FC0246aD3160Ccc09B8D0D3A2cD28aE6C2f", // Ethereum
|
|
182
|
+
42161: "0x7dfF72693f6A4149b17e7C6314655f6A9F7c8B33", // Arbitrum
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
// ── Wrapped ETH ────────────────────────────────────────────────────────
|
|
186
|
+
{
|
|
187
|
+
symbol: "WETH",
|
|
188
|
+
name: "Wrapped Ether",
|
|
189
|
+
decimals: 18,
|
|
190
|
+
addresses: {
|
|
191
|
+
1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // Ethereum
|
|
192
|
+
10: "0x4200000000000000000000000000000000000006", // Optimism
|
|
193
|
+
56: "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", // BSC (Binance-Peg ETH)
|
|
194
|
+
137: "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", // Polygon
|
|
195
|
+
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", // Arbitrum
|
|
196
|
+
8453: "0x4200000000000000000000000000000000000006", // Base
|
|
197
|
+
43114: "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB", // Avalanche (WETH.e)
|
|
198
|
+
59144: "0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f", // Linea
|
|
199
|
+
534352: "0x5300000000000000000000000000000000000004", // Scroll
|
|
200
|
+
324: "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", // zkSync
|
|
201
|
+
81457: "0x4300000000000000000000000000000000000004", // Blast
|
|
202
|
+
5000: "0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111", // Mantle (WETH)
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
// ── BTC Variants ───────────────────────────────────────────────────────
|
|
206
|
+
{
|
|
207
|
+
symbol: "WBTC",
|
|
208
|
+
name: "Wrapped Bitcoin",
|
|
209
|
+
decimals: 8,
|
|
210
|
+
addresses: {
|
|
211
|
+
1: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599", // Ethereum
|
|
212
|
+
10: "0x68f180fcCe6836688e9084f035309E29Bf0A2095", // Optimism
|
|
213
|
+
137: "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", // Polygon
|
|
214
|
+
42161: "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f", // Arbitrum
|
|
215
|
+
43114: "0x50b7545627a5162F82A992c33b87aDc75187B218", // Avalanche
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
symbol: "BTCB",
|
|
220
|
+
name: "Binance-Peg BTCB",
|
|
221
|
+
decimals: 18,
|
|
222
|
+
addresses: {
|
|
223
|
+
56: "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c", // BSC
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
symbol: "CBBTC",
|
|
228
|
+
name: "Coinbase Wrapped BTC",
|
|
229
|
+
decimals: 8,
|
|
230
|
+
addresses: {
|
|
231
|
+
1: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", // Ethereum
|
|
232
|
+
8453: "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf", // Base
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
symbol: "TBTC",
|
|
237
|
+
name: "Threshold BTC",
|
|
238
|
+
decimals: 18,
|
|
239
|
+
addresses: {
|
|
240
|
+
1: "0x18084fbA666a33d37592fA2633fD49a74DD93a88", // Ethereum
|
|
241
|
+
10: "0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40", // Optimism
|
|
242
|
+
137: "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", // Polygon
|
|
243
|
+
42161: "0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40", // Arbitrum
|
|
244
|
+
8453: "0x236aa50979D5f3De3Bd1Eeb40E81137F22ab794b", // Base
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
// ── Liquid Staking Tokens ──────────────────────────────────────────────
|
|
248
|
+
{
|
|
249
|
+
symbol: "STETH",
|
|
250
|
+
name: "Lido Staked ETH",
|
|
251
|
+
decimals: 18,
|
|
252
|
+
addresses: {
|
|
253
|
+
1: "0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84", // Ethereum
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
symbol: "WSTETH",
|
|
258
|
+
name: "Lido Wrapped Staked ETH",
|
|
259
|
+
decimals: 18,
|
|
260
|
+
addresses: {
|
|
261
|
+
1: "0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0", // Ethereum
|
|
262
|
+
10: "0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb", // Optimism
|
|
263
|
+
137: "0x03b54A6e9a984069379fae1a4fC4dBAE93B3bCCD", // Polygon
|
|
264
|
+
42161: "0x5979D7b546E38E9Ab8a45CfA782CAa3c8539b40C", // Arbitrum
|
|
265
|
+
8453: "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452", // Base
|
|
266
|
+
534352: "0xf610A9dfB7C89644979b4A0f27063E9e7d7Cda32", // Scroll
|
|
267
|
+
59144: "0xB5beDd42000b71FddE22D3eE8a79Bd49A568fC8F", // Linea
|
|
268
|
+
5000: "0x636D4073738C071326Aa70fB30dB8e8F21aFabca", // Mantle
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
symbol: "RETH",
|
|
273
|
+
name: "Rocket Pool ETH",
|
|
274
|
+
decimals: 18,
|
|
275
|
+
addresses: {
|
|
276
|
+
1: "0xae78736Cd615f374D3085123A210448E74Fc6393", // Ethereum
|
|
277
|
+
10: "0x9Bcef72be871e61ED4fBbc7630889beE758eb81D", // Optimism
|
|
278
|
+
42161: "0xEC70Dcb4A1EFa46b8F2D97C310C9c4790ba5ffA8", // Arbitrum
|
|
279
|
+
8453: "0xB6fe221Fe9EeF5aBa221c348bA20A1Bf5e73624c", // Base
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
symbol: "CBETH",
|
|
284
|
+
name: "Coinbase Staked ETH",
|
|
285
|
+
decimals: 18,
|
|
286
|
+
addresses: {
|
|
287
|
+
1: "0xBe9895146f7AF43049ca1c1AE358B0541Ea49704", // Ethereum
|
|
288
|
+
10: "0xadDb6A0412DE1BA0F936DCaeb8Aaa24578dcF3B2", // Optimism
|
|
289
|
+
8453: "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22", // Base
|
|
290
|
+
42161: "0x1DEBd73E752bEaF79865Fd6446b0c970EaE7732f", // Arbitrum
|
|
291
|
+
},
|
|
292
|
+
},
|
|
293
|
+
// ── Wrapped Native Tokens (non-ETH) ───────────────────────────────────
|
|
294
|
+
{
|
|
295
|
+
symbol: "WBNB",
|
|
296
|
+
name: "Wrapped BNB",
|
|
297
|
+
decimals: 18,
|
|
298
|
+
addresses: {
|
|
299
|
+
56: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", // BSC
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
symbol: "WMATIC",
|
|
304
|
+
name: "Wrapped MATIC",
|
|
305
|
+
decimals: 18,
|
|
306
|
+
addresses: {
|
|
307
|
+
137: "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", // Polygon
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
symbol: "WAVAX",
|
|
312
|
+
name: "Wrapped AVAX",
|
|
313
|
+
decimals: 18,
|
|
314
|
+
addresses: {
|
|
315
|
+
43114: "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", // Avalanche
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
// ── L2 Governance Tokens ───────────────────────────────────────────────
|
|
319
|
+
{
|
|
320
|
+
symbol: "ARB",
|
|
321
|
+
name: "Arbitrum",
|
|
322
|
+
decimals: 18,
|
|
323
|
+
addresses: {
|
|
324
|
+
42161: "0x912CE59144191C1204E64559FE8253a0e49E6548", // Arbitrum
|
|
325
|
+
1: "0xB50721BCf8d664c30412Cfbc6cf7a15145234ad1", // Ethereum
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
symbol: "OP",
|
|
330
|
+
name: "Optimism",
|
|
331
|
+
decimals: 18,
|
|
332
|
+
addresses: {
|
|
333
|
+
10: "0x4200000000000000000000000000000000000042", // Optimism
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
// ── DeFi Blue Chips ────────────────────────────────────────────────────
|
|
337
|
+
{
|
|
338
|
+
symbol: "LINK",
|
|
339
|
+
name: "Chainlink",
|
|
340
|
+
decimals: 18,
|
|
341
|
+
addresses: {
|
|
342
|
+
1: "0x514910771AF9Ca656af840dff83E8264EcF986CA", // Ethereum
|
|
343
|
+
10: "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6", // Optimism
|
|
344
|
+
56: "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", // BSC
|
|
345
|
+
137: "0x53E0bca35eC356BD5ddDFebbD1Fc0fD03FaBad39", // Polygon
|
|
346
|
+
42161: "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", // Arbitrum
|
|
347
|
+
43114: "0x5947BB275c521040051D82396192181b413227A3", // Avalanche
|
|
348
|
+
8453: "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196", // Base
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
symbol: "UNI",
|
|
353
|
+
name: "Uniswap",
|
|
354
|
+
decimals: 18,
|
|
355
|
+
addresses: {
|
|
356
|
+
1: "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984", // Ethereum
|
|
357
|
+
10: "0x6fd9d7AD17242c41f7131d257212c54A0e816691", // Optimism
|
|
358
|
+
137: "0xb33EaAd8d922B1083446DC23f610c2567fB5180f", // Polygon
|
|
359
|
+
42161: "0xFa7F8980b0f1E64A2062791cc3b0871572f1F7f0", // Arbitrum
|
|
360
|
+
56: "0xBf5140A22578168FD562DCcF235E5D43A02ce9B1", // BSC
|
|
361
|
+
43114: "0x8eBAf22B6F053dFFeaf46f4Dd9eFA95D89ba8580", // Avalanche
|
|
362
|
+
8453: "0xc3De830EA07524a0761646a6a4e4be0e114a3C83", // Base
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
symbol: "AAVE",
|
|
367
|
+
name: "Aave",
|
|
368
|
+
decimals: 18,
|
|
369
|
+
addresses: {
|
|
370
|
+
1: "0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9", // Ethereum
|
|
371
|
+
10: "0x76FB31fb4af56892A25e32cFC43De717950c9278", // Optimism
|
|
372
|
+
137: "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", // Polygon
|
|
373
|
+
42161: "0xba5DdD1f9d7F570dc94a51479a000E3BCE967196", // Arbitrum
|
|
374
|
+
43114: "0x63a72806098Bd3D9520cC43356dD78afe5D386D9", // Avalanche
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
symbol: "MKR",
|
|
379
|
+
name: "Maker",
|
|
380
|
+
decimals: 18,
|
|
381
|
+
addresses: {
|
|
382
|
+
1: "0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2", // Ethereum
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
symbol: "CRV",
|
|
387
|
+
name: "Curve DAO Token",
|
|
388
|
+
decimals: 18,
|
|
389
|
+
addresses: {
|
|
390
|
+
1: "0xD533a949740bb3306d119CC777fa900bA034cd52", // Ethereum
|
|
391
|
+
10: "0x0994206dfE8De6Ec6920FF4D779B0d950605Fb53", // Optimism
|
|
392
|
+
137: "0x172370d5Cd63279eFa6d502DAB29171933a610AF", // Polygon
|
|
393
|
+
42161: "0x11cDb42B0EB46D95f990BeDD4695A6e3fA034978", // Arbitrum
|
|
394
|
+
43114: "0x249848BeCA43aC405b8102Ec90Dd5F22CA513c06", // Avalanche
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
symbol: "LDO",
|
|
399
|
+
name: "Lido DAO",
|
|
400
|
+
decimals: 18,
|
|
401
|
+
addresses: {
|
|
402
|
+
1: "0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32", // Ethereum
|
|
403
|
+
10: "0xFdb794692724153d1488CcdBE0C56c0C1EE1fabf", // Optimism
|
|
404
|
+
137: "0xC3C7d422809852031b44ab29EEC9F1EfF2A58756", // Polygon
|
|
405
|
+
42161: "0x13Ad51ed4F1B7e9Dc168d8a00cB3f4dDD85EfA60", // Arbitrum
|
|
406
|
+
},
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
symbol: "SNX",
|
|
410
|
+
name: "Synthetix",
|
|
411
|
+
decimals: 18,
|
|
412
|
+
addresses: {
|
|
413
|
+
1: "0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F", // Ethereum
|
|
414
|
+
10: "0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4", // Optimism
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
symbol: "COMP",
|
|
419
|
+
name: "Compound",
|
|
420
|
+
decimals: 18,
|
|
421
|
+
addresses: {
|
|
422
|
+
1: "0xc00e94Cb662C3520282E6f5717214004A7f26888", // Ethereum
|
|
423
|
+
137: "0x8505b9d2254A7Ae468c0E9dd10Ccea3A837aef5c", // Polygon
|
|
424
|
+
42161: "0x354A6dA3fcde098F8389cad84b0182725c6C91dE", // Arbitrum
|
|
425
|
+
8453: "0x9e1028F5F1D5eDE59748FFceE5532509976840E0", // Base
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
// ── Meme / High Cap ────────────────────────────────────────────────────
|
|
429
|
+
{
|
|
430
|
+
symbol: "PEPE",
|
|
431
|
+
name: "Pepe",
|
|
432
|
+
decimals: 18,
|
|
433
|
+
addresses: {
|
|
434
|
+
1: "0x6982508145454Ce325dDbE47a25d4ec3d2311933", // Ethereum
|
|
435
|
+
42161: "0x25d887Ce7a35172C62FeBFD67a1856F20FaEbB00", // Arbitrum
|
|
436
|
+
},
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
symbol: "SHIB",
|
|
440
|
+
name: "Shiba Inu",
|
|
441
|
+
decimals: 18,
|
|
442
|
+
addresses: {
|
|
443
|
+
1: "0x95aD61b0a150d79219dCF64E1E6Cc01f0B64C4cE", // Ethereum
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
symbol: "DOGE",
|
|
448
|
+
name: "Dogecoin (Bridged)",
|
|
449
|
+
decimals: 8,
|
|
450
|
+
addresses: {
|
|
451
|
+
56: "0xbA2aE424d960c26247Dd6c32edC70B295c744C43", // BSC (Binance-Peg)
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
// ── Wrapped / Misc ─────────────────────────────────────────────────────
|
|
455
|
+
{
|
|
456
|
+
symbol: "SUSHI",
|
|
457
|
+
name: "SushiSwap",
|
|
458
|
+
decimals: 18,
|
|
459
|
+
addresses: {
|
|
460
|
+
1: "0x6B3595068778DD592e39A122f4f5a5cF09C90fE2", // Ethereum
|
|
461
|
+
137: "0x0b3F868E0BE5597D5DB7fEB59E1CADBb0fdDa50a", // Polygon
|
|
462
|
+
42161: "0xd4d42F0b6DEF4CE0383636770eF773390d85c61A", // Arbitrum
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
symbol: "RPL",
|
|
467
|
+
name: "Rocket Pool",
|
|
468
|
+
decimals: 18,
|
|
469
|
+
addresses: {
|
|
470
|
+
1: "0xD33526068D116cE69F19A9ee46F0bd304F21A51f", // Ethereum
|
|
471
|
+
42161: "0xB766039cc6DB368759C1E56B79AFfE831545A950", // Arbitrum
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
symbol: "PENDLE",
|
|
476
|
+
name: "Pendle",
|
|
477
|
+
decimals: 18,
|
|
478
|
+
addresses: {
|
|
479
|
+
1: "0x808507121B80c02388fAd14726482e061B8da827", // Ethereum
|
|
480
|
+
42161: "0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8", // Arbitrum
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
symbol: "ENA",
|
|
485
|
+
name: "Ethena",
|
|
486
|
+
decimals: 18,
|
|
487
|
+
addresses: {
|
|
488
|
+
1: "0x57e114B691Db790C35207b2e685D4A43181e6061", // Ethereum
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
symbol: "USDE",
|
|
493
|
+
name: "USDe (Ethena)",
|
|
494
|
+
decimals: 18,
|
|
495
|
+
addresses: {
|
|
496
|
+
1: "0x4c9EDD5852cd905f086C759E8383e09bff1E68B3", // Ethereum
|
|
497
|
+
42161: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34", // Arbitrum
|
|
498
|
+
8453: "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34", // Base
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
// ── Cosmos Ecosystem Tokens ──────────────────────────────────────────
|
|
502
|
+
{
|
|
503
|
+
symbol: "XPRT",
|
|
504
|
+
name: "Persistence",
|
|
505
|
+
decimals: 6,
|
|
506
|
+
addresses: {
|
|
507
|
+
// Persistence chain uses uxprt denom (micro-XPRT, 6 decimals)
|
|
508
|
+
[PERSISTENCE_CHAIN_ID]: "uxprt",
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
symbol: "ATOM",
|
|
513
|
+
name: "Cosmos Hub",
|
|
514
|
+
decimals: 6,
|
|
515
|
+
addresses: {
|
|
516
|
+
// Cosmos Hub uses uatom denom
|
|
517
|
+
[COSMOSHUB_CHAIN_ID]: "uatom",
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
// ── Solana Tokens ──────────────────────────────────────────────────────
|
|
521
|
+
{
|
|
522
|
+
symbol: "SOL",
|
|
523
|
+
name: "Solana",
|
|
524
|
+
decimals: 9,
|
|
525
|
+
addresses: {
|
|
526
|
+
[SOLANA_CHAIN_ID]: "So11111111111111111111111111111111111111112", // Wrapped SOL mint
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
];
|
|
530
|
+
// ─── Indexes (built once at module load) ────────────────────────────────────
|
|
531
|
+
/** Map of UPPERCASE symbol → array of VerifiedToken entries */
|
|
532
|
+
const symbolIndex = new Map();
|
|
533
|
+
/** Map of lowercase(address):chainId → VerifiedToken */
|
|
534
|
+
const addressIndex = new Map();
|
|
535
|
+
function buildIndexes() {
|
|
536
|
+
for (const token of VERIFIED_TOKENS) {
|
|
537
|
+
const key = token.symbol.toUpperCase();
|
|
538
|
+
const existing = symbolIndex.get(key) ?? [];
|
|
539
|
+
existing.push(token);
|
|
540
|
+
symbolIndex.set(key, existing);
|
|
541
|
+
for (const [chainIdStr, address] of Object.entries(token.addresses)) {
|
|
542
|
+
const addrKey = `${address.toLowerCase()}:${chainIdStr}`;
|
|
543
|
+
addressIndex.set(addrKey, token);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
buildIndexes();
|
|
548
|
+
// ─── Resolution Functions ───────────────────────────────────────────────────
|
|
549
|
+
/**
|
|
550
|
+
* Resolve a token input (symbol or 0x address) to a verified address.
|
|
551
|
+
*
|
|
552
|
+
* Security rules:
|
|
553
|
+
* - If input is a 0x address: pass through unchanged (with known decimals if available)
|
|
554
|
+
* - If input is a symbol: ONLY resolve to verified canonical addresses
|
|
555
|
+
* - If symbol is unknown: return error with guidance
|
|
556
|
+
* - If symbol is ambiguous (multiple tokens): return error listing options
|
|
557
|
+
* - NEVER falls back to unverified tokens
|
|
558
|
+
*/
|
|
559
|
+
export function resolveToken(input, chainId) {
|
|
560
|
+
const trimmed = input.trim();
|
|
561
|
+
// 0x address passthrough — agent knows what they're doing
|
|
562
|
+
if (trimmed.startsWith("0x") && trimmed.length === 42) {
|
|
563
|
+
// Normalize alternative native token address (0xEeEe...) to canonical zero address
|
|
564
|
+
let normalizedAddr = trimmed;
|
|
565
|
+
if (trimmed.toLowerCase() === "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee") {
|
|
566
|
+
normalizedAddr = NATIVE;
|
|
567
|
+
}
|
|
568
|
+
const known = addressIndex.get(`${normalizedAddr.toLowerCase()}:${chainId}`);
|
|
569
|
+
const decimals = known
|
|
570
|
+
? (known.decimalOverrides?.[chainId] ?? known.decimals)
|
|
571
|
+
: 18;
|
|
572
|
+
return {
|
|
573
|
+
ok: true,
|
|
574
|
+
address: normalizedAddr,
|
|
575
|
+
decimals,
|
|
576
|
+
symbol: known?.symbol ?? "UNKNOWN",
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
// Symbol resolution — security-critical path
|
|
580
|
+
const upper = trimmed.toUpperCase();
|
|
581
|
+
const candidates = symbolIndex.get(upper);
|
|
582
|
+
if (!candidates || candidates.length === 0) {
|
|
583
|
+
const chainName = getChainName(chainId);
|
|
584
|
+
return {
|
|
585
|
+
ok: false,
|
|
586
|
+
error: `Unknown token symbol '${trimmed}' on ${chainName} (chain ${chainId}). Use bridge_tokens to search, or provide the contract address directly.`,
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
// Find all candidates that have an address on this chain
|
|
590
|
+
const matches = [];
|
|
591
|
+
for (const token of candidates) {
|
|
592
|
+
const address = token.addresses[chainId];
|
|
593
|
+
if (address) {
|
|
594
|
+
matches.push({ token, address });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (matches.length === 0) {
|
|
598
|
+
const chainName = getChainName(chainId);
|
|
599
|
+
const availableChains = candidates
|
|
600
|
+
.flatMap((t) => Object.keys(t.addresses).map(Number))
|
|
601
|
+
.filter((id, i, arr) => arr.indexOf(id) === i)
|
|
602
|
+
.map((id) => `${getChainName(id)} (${id})`)
|
|
603
|
+
.join(", ");
|
|
604
|
+
return {
|
|
605
|
+
ok: false,
|
|
606
|
+
error: `Token '${trimmed}' is not available on ${chainName} (chain ${chainId}). Available on: ${availableChains}. Use bridge_tokens to search for alternatives, or provide a contract address directly.`,
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
if (matches.length > 1) {
|
|
610
|
+
const chainName = getChainName(chainId);
|
|
611
|
+
const options = matches
|
|
612
|
+
.map((m) => ` • ${m.token.symbol} (${m.token.name}): ${m.address}`)
|
|
613
|
+
.join("\n");
|
|
614
|
+
return {
|
|
615
|
+
ok: false,
|
|
616
|
+
error: `Ambiguous token symbol '${trimmed}' on ${chainName} (chain ${chainId}). Multiple verified tokens found:\n${options}\nSpecify the contract address directly to disambiguate.`,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
// Exactly one match — verified resolution
|
|
620
|
+
const match = matches[0];
|
|
621
|
+
const decimals = match.token.decimalOverrides?.[chainId] ?? match.token.decimals;
|
|
622
|
+
return {
|
|
623
|
+
ok: true,
|
|
624
|
+
address: match.address,
|
|
625
|
+
decimals,
|
|
626
|
+
symbol: match.token.symbol,
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Look up a verified token by address on a specific chain.
|
|
631
|
+
* Returns null if not in the registry (the token may still be valid, just not curated).
|
|
632
|
+
*/
|
|
633
|
+
export function lookupByAddress(address, chainId) {
|
|
634
|
+
return addressIndex.get(`${address.toLowerCase()}:${chainId}`) ?? null;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Get all verified tokens available on a specific chain.
|
|
638
|
+
*/
|
|
639
|
+
export function getVerifiedTokensForChain(chainId) {
|
|
640
|
+
const results = [];
|
|
641
|
+
for (const token of VERIFIED_TOKENS) {
|
|
642
|
+
const address = token.addresses[chainId];
|
|
643
|
+
if (address) {
|
|
644
|
+
const decimals = token.decimalOverrides?.[chainId] ?? token.decimals;
|
|
645
|
+
results.push({
|
|
646
|
+
symbol: token.symbol,
|
|
647
|
+
name: token.name,
|
|
648
|
+
address,
|
|
649
|
+
decimals,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return results;
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
* Get the total number of unique tokens in the registry.
|
|
657
|
+
*/
|
|
658
|
+
export function getRegistryStats() {
|
|
659
|
+
const chains = new Set();
|
|
660
|
+
for (const token of VERIFIED_TOKENS) {
|
|
661
|
+
for (const chainId of Object.keys(token.addresses)) {
|
|
662
|
+
chains.add(Number(chainId));
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
tokenCount: VERIFIED_TOKENS.length,
|
|
667
|
+
chainCount: chains.size,
|
|
668
|
+
};
|
|
669
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { resolveToken, lookupByAddress, type TokenResolveResult } from "./token-registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a token symbol or address to { address, decimals }.
|
|
4
|
+
*
|
|
5
|
+
* Returns null if:
|
|
6
|
+
* - Symbol is unknown in the verified registry for this chain
|
|
7
|
+
* - Address is already a 0x address (still returns result with known/default decimals)
|
|
8
|
+
*
|
|
9
|
+
* @deprecated Use `resolveToken()` for better error messages.
|
|
10
|
+
* This function is kept for backward compatibility.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveTokenAddress(symbol: string, chainId: number): {
|
|
13
|
+
address: string;
|
|
14
|
+
decimals: number;
|
|
15
|
+
} | null;
|
|
16
|
+
export declare function formatTokenAmount(amountRaw: string, decimals: number): string;
|
|
17
|
+
export declare function parseTokenAmount(amount: string, decimals: number): string;
|