tx-indexer 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/dist/{client-DdzTiKZ4.d.ts → client-xmDVjOy4.d.ts} +13 -1
- package/dist/client.d.ts +2 -2
- package/dist/client.js +499 -49
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +109 -5
- package/dist/index.js +521 -52
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +4 -4
- package/package.json +1 -1
- package/dist/{classification.types-Cn9IGtEC.d.ts → classification.types-h046WjuF.d.ts} +7 -7
package/dist/index.js
CHANGED
|
@@ -15,12 +15,43 @@ function parseSignature(sig) {
|
|
|
15
15
|
|
|
16
16
|
// ../domain/src/money/token-registry.ts
|
|
17
17
|
var KNOWN_TOKENS = {
|
|
18
|
+
// Native
|
|
18
19
|
SOL: "So11111111111111111111111111111111111111112",
|
|
20
|
+
// Stablecoins
|
|
19
21
|
USDC: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
|
|
22
|
+
USDT: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
|
|
23
|
+
PYUSD: "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
|
|
24
|
+
USDG: "2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH",
|
|
20
25
|
USDC_BRIDGED: "A9mUU4qviSctJVPJdBJWkb28deg915LYJKrzQ19ji3FM",
|
|
21
|
-
|
|
26
|
+
DAI: "EjmyN6qEC1Tf1JxiG1ae7UTJhUxSwk1TCCi3Z4dPuFhh",
|
|
27
|
+
// Major tokens
|
|
28
|
+
JUP: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN",
|
|
29
|
+
JTO: "jtojtomepa8beP8AuQc6eXt5FriJwfFMwQx2v2f9mCL",
|
|
30
|
+
PYTH: "HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3",
|
|
31
|
+
BONK: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
|
|
32
|
+
WIF: "EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm",
|
|
33
|
+
RENDER: "rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof",
|
|
34
|
+
HNT: "hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux",
|
|
35
|
+
RAY: "4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R",
|
|
36
|
+
ORCA: "orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE",
|
|
37
|
+
MNGO: "MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac",
|
|
38
|
+
MSOL: "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
|
|
39
|
+
JITOSOL: "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
|
|
40
|
+
BSOL: "bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1",
|
|
41
|
+
// Memecoins
|
|
42
|
+
POPCAT: "7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr",
|
|
43
|
+
MEW: "MEW1gQWJ3nEXg2qgERiKu7FAFj79PHvQVREQUzScPP5",
|
|
44
|
+
PNUT: "2qEHjDLDLbuBgRYvsxhc5D6uDWAivNFZGan56P1tpump",
|
|
45
|
+
FARTCOIN: "9BB6NFEcjBCtnNLFko2FqVQBq8HHM13kCyYcdQbgpump",
|
|
46
|
+
AI16Z: "HeLp6NuQkmYB4pYWo2zYs22mESHXPQYzXbB8n4V98jwC",
|
|
47
|
+
// Wrapped tokens
|
|
48
|
+
WBTC: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh",
|
|
49
|
+
WETH: "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
|
|
50
|
+
WSOL: "So11111111111111111111111111111111111111112"
|
|
51
|
+
// Same as SOL (wrapped)
|
|
22
52
|
};
|
|
23
53
|
var TOKEN_INFO = {
|
|
54
|
+
// Native SOL
|
|
24
55
|
[KNOWN_TOKENS.SOL]: {
|
|
25
56
|
mint: KNOWN_TOKENS.SOL,
|
|
26
57
|
symbol: "SOL",
|
|
@@ -28,6 +59,7 @@ var TOKEN_INFO = {
|
|
|
28
59
|
decimals: 9,
|
|
29
60
|
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png"
|
|
30
61
|
},
|
|
62
|
+
// Stablecoins
|
|
31
63
|
[KNOWN_TOKENS.USDC]: {
|
|
32
64
|
mint: KNOWN_TOKENS.USDC,
|
|
33
65
|
symbol: "USDC",
|
|
@@ -35,30 +67,211 @@ var TOKEN_INFO = {
|
|
|
35
67
|
decimals: 6,
|
|
36
68
|
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v/logo.png"
|
|
37
69
|
},
|
|
38
|
-
[KNOWN_TOKENS.
|
|
39
|
-
mint: KNOWN_TOKENS.
|
|
40
|
-
symbol: "
|
|
41
|
-
name: "
|
|
42
|
-
decimals: 6
|
|
70
|
+
[KNOWN_TOKENS.USDT]: {
|
|
71
|
+
mint: KNOWN_TOKENS.USDT,
|
|
72
|
+
symbol: "USDT",
|
|
73
|
+
name: "Tether USD",
|
|
74
|
+
decimals: 6,
|
|
75
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB/logo.svg"
|
|
76
|
+
},
|
|
77
|
+
[KNOWN_TOKENS.PYUSD]: {
|
|
78
|
+
mint: KNOWN_TOKENS.PYUSD,
|
|
79
|
+
symbol: "PYUSD",
|
|
80
|
+
name: "PayPal USD",
|
|
81
|
+
decimals: 6,
|
|
82
|
+
logoURI: "https://img.fotofolio.xyz/?url=https%3A%2F%2Fraw.githubusercontent.com%2Fsolana-labs%2Ftoken-list%2Fmain%2Fassets%2Fmainnet%2F2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo%2Flogo.png"
|
|
43
83
|
},
|
|
44
84
|
[KNOWN_TOKENS.USDG]: {
|
|
45
85
|
mint: KNOWN_TOKENS.USDG,
|
|
46
86
|
symbol: "USDG",
|
|
47
87
|
name: "USD Glitter",
|
|
48
88
|
decimals: 6
|
|
89
|
+
},
|
|
90
|
+
[KNOWN_TOKENS.USDC_BRIDGED]: {
|
|
91
|
+
mint: KNOWN_TOKENS.USDC_BRIDGED,
|
|
92
|
+
symbol: "USDCet",
|
|
93
|
+
name: "USDC (Wormhole)",
|
|
94
|
+
decimals: 6
|
|
95
|
+
},
|
|
96
|
+
[KNOWN_TOKENS.DAI]: {
|
|
97
|
+
mint: KNOWN_TOKENS.DAI,
|
|
98
|
+
symbol: "DAI",
|
|
99
|
+
name: "DAI (Wormhole)",
|
|
100
|
+
decimals: 8
|
|
101
|
+
},
|
|
102
|
+
// Major tokens
|
|
103
|
+
[KNOWN_TOKENS.JUP]: {
|
|
104
|
+
mint: KNOWN_TOKENS.JUP,
|
|
105
|
+
symbol: "JUP",
|
|
106
|
+
name: "Jupiter",
|
|
107
|
+
decimals: 6,
|
|
108
|
+
logoURI: "https://static.jup.ag/jup/icon.png"
|
|
109
|
+
},
|
|
110
|
+
[KNOWN_TOKENS.JTO]: {
|
|
111
|
+
mint: KNOWN_TOKENS.JTO,
|
|
112
|
+
symbol: "JTO",
|
|
113
|
+
name: "Jito",
|
|
114
|
+
decimals: 9,
|
|
115
|
+
logoURI: "https://metadata.jito.network/token/jto/image"
|
|
116
|
+
},
|
|
117
|
+
[KNOWN_TOKENS.PYTH]: {
|
|
118
|
+
mint: KNOWN_TOKENS.PYTH,
|
|
119
|
+
symbol: "PYTH",
|
|
120
|
+
name: "Pyth Network",
|
|
121
|
+
decimals: 6,
|
|
122
|
+
logoURI: "https://pyth.network/token.svg"
|
|
123
|
+
},
|
|
124
|
+
[KNOWN_TOKENS.BONK]: {
|
|
125
|
+
mint: KNOWN_TOKENS.BONK,
|
|
126
|
+
symbol: "BONK",
|
|
127
|
+
name: "Bonk",
|
|
128
|
+
decimals: 5,
|
|
129
|
+
logoURI: "https://arweave.net/hQiPZOsRZXGXBJd_82PhVdlM_hACsT_q6wqwf5cSY7I"
|
|
130
|
+
},
|
|
131
|
+
[KNOWN_TOKENS.WIF]: {
|
|
132
|
+
mint: KNOWN_TOKENS.WIF,
|
|
133
|
+
symbol: "WIF",
|
|
134
|
+
name: "dogwifhat",
|
|
135
|
+
decimals: 6,
|
|
136
|
+
logoURI: "https://bafkreibk3covs5ltyqxa272uodhber6kcclnlgrbwjee4kyqhstwmjqpfa.ipfs.nftstorage.link/"
|
|
137
|
+
},
|
|
138
|
+
[KNOWN_TOKENS.RENDER]: {
|
|
139
|
+
mint: KNOWN_TOKENS.RENDER,
|
|
140
|
+
symbol: "RENDER",
|
|
141
|
+
name: "Render Token",
|
|
142
|
+
decimals: 8,
|
|
143
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/rndrizKT3MK1iimdxRdWabcF7Zg7AR5T4nud4EkHBof/logo.png"
|
|
144
|
+
},
|
|
145
|
+
[KNOWN_TOKENS.HNT]: {
|
|
146
|
+
mint: KNOWN_TOKENS.HNT,
|
|
147
|
+
symbol: "HNT",
|
|
148
|
+
name: "Helium",
|
|
149
|
+
decimals: 8,
|
|
150
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/hntyVP6YFm1Hg25TN9WGLqM12b8TQmcknKrdu1oxWux/logo.png"
|
|
151
|
+
},
|
|
152
|
+
[KNOWN_TOKENS.RAY]: {
|
|
153
|
+
mint: KNOWN_TOKENS.RAY,
|
|
154
|
+
symbol: "RAY",
|
|
155
|
+
name: "Raydium",
|
|
156
|
+
decimals: 6,
|
|
157
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R/logo.png"
|
|
158
|
+
},
|
|
159
|
+
[KNOWN_TOKENS.ORCA]: {
|
|
160
|
+
mint: KNOWN_TOKENS.ORCA,
|
|
161
|
+
symbol: "ORCA",
|
|
162
|
+
name: "Orca",
|
|
163
|
+
decimals: 6,
|
|
164
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/orcaEKTdK7LKz57vaAYr9QeNsVEPfiu6QeMU1kektZE/logo.png"
|
|
165
|
+
},
|
|
166
|
+
[KNOWN_TOKENS.MNGO]: {
|
|
167
|
+
mint: KNOWN_TOKENS.MNGO,
|
|
168
|
+
symbol: "MNGO",
|
|
169
|
+
name: "Mango",
|
|
170
|
+
decimals: 6,
|
|
171
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/MangoCzJ36AjZyKwVj3VnYU4GTonjfVEnJmvvWaxLac/logo.png"
|
|
172
|
+
},
|
|
173
|
+
// Liquid staking tokens
|
|
174
|
+
[KNOWN_TOKENS.MSOL]: {
|
|
175
|
+
mint: KNOWN_TOKENS.MSOL,
|
|
176
|
+
symbol: "mSOL",
|
|
177
|
+
name: "Marinade Staked SOL",
|
|
178
|
+
decimals: 9,
|
|
179
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So/logo.png"
|
|
180
|
+
},
|
|
181
|
+
[KNOWN_TOKENS.JITOSOL]: {
|
|
182
|
+
mint: KNOWN_TOKENS.JITOSOL,
|
|
183
|
+
symbol: "JitoSOL",
|
|
184
|
+
name: "Jito Staked SOL",
|
|
185
|
+
decimals: 9,
|
|
186
|
+
logoURI: "https://storage.googleapis.com/token-metadata/JitoSOL-256.png"
|
|
187
|
+
},
|
|
188
|
+
[KNOWN_TOKENS.BSOL]: {
|
|
189
|
+
mint: KNOWN_TOKENS.BSOL,
|
|
190
|
+
symbol: "bSOL",
|
|
191
|
+
name: "BlazeStake Staked SOL",
|
|
192
|
+
decimals: 9,
|
|
193
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1/logo.png"
|
|
194
|
+
},
|
|
195
|
+
// Memecoins
|
|
196
|
+
[KNOWN_TOKENS.POPCAT]: {
|
|
197
|
+
mint: KNOWN_TOKENS.POPCAT,
|
|
198
|
+
symbol: "POPCAT",
|
|
199
|
+
name: "Popcat",
|
|
200
|
+
decimals: 9,
|
|
201
|
+
logoURI: "https://bafkreidvkvuzyslw5jh5z242lgzwzhbi2kxxnpkm73fkuqzasyr34jj2o4.ipfs.nftstorage.link/"
|
|
202
|
+
},
|
|
203
|
+
[KNOWN_TOKENS.MEW]: {
|
|
204
|
+
mint: KNOWN_TOKENS.MEW,
|
|
205
|
+
symbol: "MEW",
|
|
206
|
+
name: "cat in a dogs world",
|
|
207
|
+
decimals: 5,
|
|
208
|
+
logoURI: "https://bafkreidlwyr565dxtao2ipsze6bmzpszqzybz7sqi2zaet5fs7k53henju.ipfs.nftstorage.link/"
|
|
209
|
+
},
|
|
210
|
+
[KNOWN_TOKENS.PNUT]: {
|
|
211
|
+
mint: KNOWN_TOKENS.PNUT,
|
|
212
|
+
symbol: "Peanut",
|
|
213
|
+
name: "Peanut the Squirrel",
|
|
214
|
+
decimals: 6,
|
|
215
|
+
logoURI: "https://ipfs.io/ipfs/QmNS3Hdb6pMheFzRdwXr3PPCrXcBohzhLrKHqEUV1n3HnJ"
|
|
216
|
+
},
|
|
217
|
+
[KNOWN_TOKENS.FARTCOIN]: {
|
|
218
|
+
mint: KNOWN_TOKENS.FARTCOIN,
|
|
219
|
+
symbol: "FARTCOIN",
|
|
220
|
+
name: "Fartcoin",
|
|
221
|
+
decimals: 6,
|
|
222
|
+
logoURI: "https://ipfs.io/ipfs/QmQHY6t8TxucH3F9LGPBBqqRLbyWx7NxWvrnoZKcq9ErrR"
|
|
223
|
+
},
|
|
224
|
+
[KNOWN_TOKENS.AI16Z]: {
|
|
225
|
+
mint: KNOWN_TOKENS.AI16Z,
|
|
226
|
+
symbol: "ai16z",
|
|
227
|
+
name: "ai16z",
|
|
228
|
+
decimals: 9,
|
|
229
|
+
logoURI: "https://ipfs.io/ipfs/QmRbm1mprqHmJ7PvCTrSNydkquLi5r41wq8kWbHvoRm3FX"
|
|
230
|
+
},
|
|
231
|
+
// Wrapped tokens
|
|
232
|
+
[KNOWN_TOKENS.WBTC]: {
|
|
233
|
+
mint: KNOWN_TOKENS.WBTC,
|
|
234
|
+
symbol: "WBTC",
|
|
235
|
+
name: "Wrapped BTC (Wormhole)",
|
|
236
|
+
decimals: 8,
|
|
237
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh/logo.png"
|
|
238
|
+
},
|
|
239
|
+
[KNOWN_TOKENS.WETH]: {
|
|
240
|
+
mint: KNOWN_TOKENS.WETH,
|
|
241
|
+
symbol: "WETH",
|
|
242
|
+
name: "Wrapped ETH (Wormhole)",
|
|
243
|
+
decimals: 8,
|
|
244
|
+
logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs/logo.png"
|
|
49
245
|
}
|
|
50
246
|
};
|
|
51
247
|
function getTokenInfo(mint) {
|
|
52
248
|
return TOKEN_INFO[mint];
|
|
53
249
|
}
|
|
54
|
-
|
|
250
|
+
function createUnknownToken(mint, decimals) {
|
|
251
|
+
return {
|
|
252
|
+
mint,
|
|
253
|
+
symbol: mint.slice(0, 8),
|
|
254
|
+
name: `Unknown Token (${mint.slice(0, 8)}...)`,
|
|
255
|
+
decimals
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
var SUPPORTED_STABLECOINS = [
|
|
55
259
|
KNOWN_TOKENS.USDC,
|
|
260
|
+
KNOWN_TOKENS.USDT,
|
|
261
|
+
KNOWN_TOKENS.PYUSD,
|
|
262
|
+
KNOWN_TOKENS.USDG,
|
|
56
263
|
KNOWN_TOKENS.USDC_BRIDGED,
|
|
57
|
-
KNOWN_TOKENS.
|
|
264
|
+
KNOWN_TOKENS.DAI
|
|
58
265
|
];
|
|
59
266
|
[
|
|
60
267
|
KNOWN_TOKENS.SOL,
|
|
61
|
-
KNOWN_TOKENS.USDC
|
|
268
|
+
KNOWN_TOKENS.USDC,
|
|
269
|
+
KNOWN_TOKENS.USDT
|
|
270
|
+
];
|
|
271
|
+
var LIQUID_STAKING_TOKENS = [
|
|
272
|
+
KNOWN_TOKENS.MSOL,
|
|
273
|
+
KNOWN_TOKENS.JITOSOL,
|
|
274
|
+
KNOWN_TOKENS.BSOL
|
|
62
275
|
];
|
|
63
276
|
|
|
64
277
|
// ../solana/src/constants/program-ids.ts
|
|
@@ -1739,6 +1952,125 @@ function filterSpamTransactions(transactions, config) {
|
|
|
1739
1952
|
);
|
|
1740
1953
|
}
|
|
1741
1954
|
|
|
1955
|
+
// ../domain/src/money/token-fetcher.ts
|
|
1956
|
+
var DEFAULT_JUPITER_API_URL = "https://tokens.jup.ag/tokens?tags=verified";
|
|
1957
|
+
var DEFAULT_CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
1958
|
+
function createTokenFetcher(options = {}) {
|
|
1959
|
+
const {
|
|
1960
|
+
jupiterApiUrl = DEFAULT_JUPITER_API_URL,
|
|
1961
|
+
cacheTtlMs = DEFAULT_CACHE_TTL_MS,
|
|
1962
|
+
prefetch = false
|
|
1963
|
+
} = options;
|
|
1964
|
+
const jupiterCache = /* @__PURE__ */ new Map();
|
|
1965
|
+
let lastFetchTime = 0;
|
|
1966
|
+
let fetchPromise = null;
|
|
1967
|
+
async function fetchJupiterTokens() {
|
|
1968
|
+
if (fetchPromise) {
|
|
1969
|
+
return fetchPromise;
|
|
1970
|
+
}
|
|
1971
|
+
if (Date.now() - lastFetchTime < cacheTtlMs && jupiterCache.size > 0) {
|
|
1972
|
+
return;
|
|
1973
|
+
}
|
|
1974
|
+
fetchPromise = (async () => {
|
|
1975
|
+
try {
|
|
1976
|
+
const response = await fetch(jupiterApiUrl);
|
|
1977
|
+
if (!response.ok) {
|
|
1978
|
+
console.warn(
|
|
1979
|
+
`Jupiter API returned ${response.status}: ${response.statusText}`
|
|
1980
|
+
);
|
|
1981
|
+
return;
|
|
1982
|
+
}
|
|
1983
|
+
const tokens = await response.json();
|
|
1984
|
+
jupiterCache.clear();
|
|
1985
|
+
for (const token of tokens) {
|
|
1986
|
+
jupiterCache.set(token.address, {
|
|
1987
|
+
mint: token.address,
|
|
1988
|
+
symbol: token.symbol,
|
|
1989
|
+
name: token.name,
|
|
1990
|
+
decimals: token.decimals,
|
|
1991
|
+
logoURI: token.logoURI
|
|
1992
|
+
});
|
|
1993
|
+
}
|
|
1994
|
+
lastFetchTime = Date.now();
|
|
1995
|
+
} catch (error) {
|
|
1996
|
+
console.warn("Failed to fetch Jupiter tokens:", error);
|
|
1997
|
+
} finally {
|
|
1998
|
+
fetchPromise = null;
|
|
1999
|
+
}
|
|
2000
|
+
})();
|
|
2001
|
+
return fetchPromise;
|
|
2002
|
+
}
|
|
2003
|
+
async function getToken(mint, decimals = 9) {
|
|
2004
|
+
const staticToken = TOKEN_INFO[mint];
|
|
2005
|
+
if (staticToken) {
|
|
2006
|
+
return staticToken;
|
|
2007
|
+
}
|
|
2008
|
+
const cachedToken = jupiterCache.get(mint);
|
|
2009
|
+
if (cachedToken) {
|
|
2010
|
+
return cachedToken;
|
|
2011
|
+
}
|
|
2012
|
+
await fetchJupiterTokens();
|
|
2013
|
+
const fetchedToken = jupiterCache.get(mint);
|
|
2014
|
+
if (fetchedToken) {
|
|
2015
|
+
return fetchedToken;
|
|
2016
|
+
}
|
|
2017
|
+
return createUnknownToken(mint, decimals);
|
|
2018
|
+
}
|
|
2019
|
+
async function getTokens(mints, defaultDecimals = 9) {
|
|
2020
|
+
const result = /* @__PURE__ */ new Map();
|
|
2021
|
+
const missingMints = [];
|
|
2022
|
+
for (const mint of mints) {
|
|
2023
|
+
const staticToken = TOKEN_INFO[mint];
|
|
2024
|
+
if (staticToken) {
|
|
2025
|
+
result.set(mint, staticToken);
|
|
2026
|
+
continue;
|
|
2027
|
+
}
|
|
2028
|
+
const cachedToken = jupiterCache.get(mint);
|
|
2029
|
+
if (cachedToken) {
|
|
2030
|
+
result.set(mint, cachedToken);
|
|
2031
|
+
continue;
|
|
2032
|
+
}
|
|
2033
|
+
missingMints.push(mint);
|
|
2034
|
+
}
|
|
2035
|
+
if (missingMints.length > 0) {
|
|
2036
|
+
await fetchJupiterTokens();
|
|
2037
|
+
for (const mint of missingMints) {
|
|
2038
|
+
const fetchedToken = jupiterCache.get(mint);
|
|
2039
|
+
if (fetchedToken) {
|
|
2040
|
+
result.set(mint, fetchedToken);
|
|
2041
|
+
} else {
|
|
2042
|
+
result.set(mint, createUnknownToken(mint, defaultDecimals));
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
return result;
|
|
2047
|
+
}
|
|
2048
|
+
async function refresh() {
|
|
2049
|
+
lastFetchTime = 0;
|
|
2050
|
+
await fetchJupiterTokens();
|
|
2051
|
+
}
|
|
2052
|
+
function getCacheSize() {
|
|
2053
|
+
return jupiterCache.size;
|
|
2054
|
+
}
|
|
2055
|
+
if (prefetch) {
|
|
2056
|
+
fetchJupiterTokens().catch(() => {
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
return {
|
|
2060
|
+
getToken,
|
|
2061
|
+
getTokens,
|
|
2062
|
+
refresh,
|
|
2063
|
+
getCacheSize
|
|
2064
|
+
};
|
|
2065
|
+
}
|
|
2066
|
+
var defaultFetcher = null;
|
|
2067
|
+
function getDefaultTokenFetcher() {
|
|
2068
|
+
if (!defaultFetcher) {
|
|
2069
|
+
defaultFetcher = createTokenFetcher();
|
|
2070
|
+
}
|
|
2071
|
+
return defaultFetcher;
|
|
2072
|
+
}
|
|
2073
|
+
|
|
1742
2074
|
// src/nft.ts
|
|
1743
2075
|
async function fetchNftMetadata(rpcUrl, mintAddress) {
|
|
1744
2076
|
const response = await fetch(rpcUrl, {
|
|
@@ -1783,6 +2115,102 @@ async function fetchNftMetadataBatch(rpcUrl, mintAddresses) {
|
|
|
1783
2115
|
|
|
1784
2116
|
// src/client.ts
|
|
1785
2117
|
var NFT_TRANSACTION_TYPES = ["nft_mint", "nft_purchase", "nft_sale"];
|
|
2118
|
+
async function enrichTokenMetadata(tokenFetcher, classified) {
|
|
2119
|
+
const mints = /* @__PURE__ */ new Set();
|
|
2120
|
+
const decimalsMap = /* @__PURE__ */ new Map();
|
|
2121
|
+
for (const leg of classified.legs) {
|
|
2122
|
+
const mint = leg.amount.token.mint;
|
|
2123
|
+
mints.add(mint);
|
|
2124
|
+
decimalsMap.set(mint, leg.amount.token.decimals);
|
|
2125
|
+
}
|
|
2126
|
+
if (classified.classification.primaryAmount?.token.mint) {
|
|
2127
|
+
const mint = classified.classification.primaryAmount.token.mint;
|
|
2128
|
+
mints.add(mint);
|
|
2129
|
+
decimalsMap.set(
|
|
2130
|
+
mint,
|
|
2131
|
+
classified.classification.primaryAmount.token.decimals
|
|
2132
|
+
);
|
|
2133
|
+
}
|
|
2134
|
+
if (classified.classification.secondaryAmount?.token.mint) {
|
|
2135
|
+
const mint = classified.classification.secondaryAmount.token.mint;
|
|
2136
|
+
mints.add(mint);
|
|
2137
|
+
decimalsMap.set(
|
|
2138
|
+
mint,
|
|
2139
|
+
classified.classification.secondaryAmount.token.decimals
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
if (mints.size === 0) {
|
|
2143
|
+
return classified;
|
|
2144
|
+
}
|
|
2145
|
+
const tokenInfoMap = await tokenFetcher.getTokens(
|
|
2146
|
+
Array.from(mints),
|
|
2147
|
+
9
|
|
2148
|
+
// default decimals
|
|
2149
|
+
);
|
|
2150
|
+
function enrichAmount(amount) {
|
|
2151
|
+
if (!amount) return amount;
|
|
2152
|
+
const enrichedToken = tokenInfoMap.get(amount.token.mint);
|
|
2153
|
+
if (!enrichedToken || enrichedToken.symbol === amount.token.symbol) {
|
|
2154
|
+
return amount;
|
|
2155
|
+
}
|
|
2156
|
+
return {
|
|
2157
|
+
...amount,
|
|
2158
|
+
token: {
|
|
2159
|
+
...enrichedToken,
|
|
2160
|
+
// Keep the decimals from the original (from RPC) as they're authoritative
|
|
2161
|
+
decimals: amount.token.decimals
|
|
2162
|
+
}
|
|
2163
|
+
};
|
|
2164
|
+
}
|
|
2165
|
+
function enrichLeg(leg) {
|
|
2166
|
+
const enrichedToken = tokenInfoMap.get(leg.amount.token.mint);
|
|
2167
|
+
if (!enrichedToken || enrichedToken.symbol === leg.amount.token.symbol) {
|
|
2168
|
+
return leg;
|
|
2169
|
+
}
|
|
2170
|
+
return {
|
|
2171
|
+
...leg,
|
|
2172
|
+
amount: {
|
|
2173
|
+
...leg.amount,
|
|
2174
|
+
token: {
|
|
2175
|
+
...enrichedToken,
|
|
2176
|
+
decimals: leg.amount.token.decimals
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
const enrichedLegs = classified.legs.map(enrichLeg);
|
|
2182
|
+
const enrichedClassification = {
|
|
2183
|
+
...classified.classification,
|
|
2184
|
+
primaryAmount: enrichAmount(classified.classification.primaryAmount) ?? null,
|
|
2185
|
+
secondaryAmount: enrichAmount(classified.classification.secondaryAmount)
|
|
2186
|
+
};
|
|
2187
|
+
return {
|
|
2188
|
+
tx: classified.tx,
|
|
2189
|
+
legs: enrichedLegs,
|
|
2190
|
+
classification: enrichedClassification
|
|
2191
|
+
};
|
|
2192
|
+
}
|
|
2193
|
+
async function enrichTokenMetadataBatch(tokenFetcher, transactions) {
|
|
2194
|
+
const mints = /* @__PURE__ */ new Set();
|
|
2195
|
+
for (const classified of transactions) {
|
|
2196
|
+
for (const leg of classified.legs) {
|
|
2197
|
+
mints.add(leg.amount.token.mint);
|
|
2198
|
+
}
|
|
2199
|
+
if (classified.classification.primaryAmount?.token.mint) {
|
|
2200
|
+
mints.add(classified.classification.primaryAmount.token.mint);
|
|
2201
|
+
}
|
|
2202
|
+
if (classified.classification.secondaryAmount?.token.mint) {
|
|
2203
|
+
mints.add(classified.classification.secondaryAmount.token.mint);
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
if (mints.size === 0) {
|
|
2207
|
+
return transactions;
|
|
2208
|
+
}
|
|
2209
|
+
await tokenFetcher.getTokens(Array.from(mints));
|
|
2210
|
+
return Promise.all(
|
|
2211
|
+
transactions.map((tx) => enrichTokenMetadata(tokenFetcher, tx))
|
|
2212
|
+
);
|
|
2213
|
+
}
|
|
1786
2214
|
async function enrichNftClassification(rpcUrl, classified) {
|
|
1787
2215
|
const { classification } = classified;
|
|
1788
2216
|
if (!NFT_TRANSACTION_TYPES.includes(classification.primaryType)) {
|
|
@@ -1815,51 +2243,74 @@ async function enrichNftClassification(rpcUrl, classified) {
|
|
|
1815
2243
|
function createIndexer(options) {
|
|
1816
2244
|
const rpcUrl = "client" in options ? "" : options.rpcUrl;
|
|
1817
2245
|
const client = "client" in options ? options.client : createSolanaClient(options.rpcUrl, options.wsUrl);
|
|
2246
|
+
const tokenFetcher = createTokenFetcher();
|
|
1818
2247
|
return {
|
|
1819
2248
|
rpc: client.rpc,
|
|
1820
2249
|
async getBalance(walletAddress, tokenMints) {
|
|
1821
2250
|
return fetchWalletBalance(client.rpc, walletAddress, tokenMints);
|
|
1822
2251
|
},
|
|
1823
2252
|
async getTransactions(walletAddress, options2 = {}) {
|
|
1824
|
-
const {
|
|
2253
|
+
const {
|
|
2254
|
+
limit = 10,
|
|
2255
|
+
before,
|
|
2256
|
+
until,
|
|
2257
|
+
filterSpam = true,
|
|
2258
|
+
spamConfig,
|
|
2259
|
+
enrichNftMetadata = true,
|
|
2260
|
+
enrichTokenMetadata: enrichTokens = true
|
|
2261
|
+
} = options2;
|
|
1825
2262
|
async function enrichBatch(transactions) {
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
const nftMints = transactions.filter((t) => NFT_TRANSACTION_TYPES.includes(t.classification.primaryType)).map((t) => t.classification.metadata?.nft_mint).filter(Boolean);
|
|
1830
|
-
if (nftMints.length === 0) {
|
|
1831
|
-
return transactions;
|
|
2263
|
+
let result2 = transactions;
|
|
2264
|
+
if (enrichTokens) {
|
|
2265
|
+
result2 = await enrichTokenMetadataBatch(tokenFetcher, result2);
|
|
1832
2266
|
}
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
nft_cdn_image: nftData.cdnImage,
|
|
1849
|
-
nft_collection: nftData.collection,
|
|
1850
|
-
nft_symbol: nftData.symbol,
|
|
1851
|
-
nft_attributes: nftData.attributes
|
|
2267
|
+
if (enrichNftMetadata && rpcUrl) {
|
|
2268
|
+
const nftMints = result2.filter(
|
|
2269
|
+
(t) => NFT_TRANSACTION_TYPES.includes(
|
|
2270
|
+
t.classification.primaryType
|
|
2271
|
+
)
|
|
2272
|
+
).map((t) => t.classification.metadata?.nft_mint).filter(Boolean);
|
|
2273
|
+
if (nftMints.length > 0) {
|
|
2274
|
+
const nftMetadataMap = await fetchNftMetadataBatch(
|
|
2275
|
+
rpcUrl,
|
|
2276
|
+
nftMints
|
|
2277
|
+
);
|
|
2278
|
+
result2 = result2.map((t) => {
|
|
2279
|
+
const nftMint = t.classification.metadata?.nft_mint;
|
|
2280
|
+
if (!nftMint || !nftMetadataMap.has(nftMint)) {
|
|
2281
|
+
return t;
|
|
1852
2282
|
}
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
2283
|
+
const nftData = nftMetadataMap.get(nftMint);
|
|
2284
|
+
return {
|
|
2285
|
+
...t,
|
|
2286
|
+
classification: {
|
|
2287
|
+
...t.classification,
|
|
2288
|
+
metadata: {
|
|
2289
|
+
...t.classification.metadata,
|
|
2290
|
+
nft_name: nftData.name,
|
|
2291
|
+
nft_image: nftData.image,
|
|
2292
|
+
nft_cdn_image: nftData.cdnImage,
|
|
2293
|
+
nft_collection: nftData.collection,
|
|
2294
|
+
nft_symbol: nftData.symbol,
|
|
2295
|
+
nft_attributes: nftData.attributes
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
};
|
|
2299
|
+
});
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
return result2;
|
|
1856
2303
|
}
|
|
1857
2304
|
if (!filterSpam) {
|
|
1858
|
-
const signatures = await fetchWalletSignatures(
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
2305
|
+
const signatures = await fetchWalletSignatures(
|
|
2306
|
+
client.rpc,
|
|
2307
|
+
walletAddress,
|
|
2308
|
+
{
|
|
2309
|
+
limit,
|
|
2310
|
+
before,
|
|
2311
|
+
until
|
|
2312
|
+
}
|
|
2313
|
+
);
|
|
1863
2314
|
if (signatures.length === 0) {
|
|
1864
2315
|
return [];
|
|
1865
2316
|
}
|
|
@@ -1874,7 +2325,11 @@ function createIndexer(options) {
|
|
|
1874
2325
|
const classified = transactions.map((tx) => {
|
|
1875
2326
|
tx.protocol = detectProtocol(tx.programIds);
|
|
1876
2327
|
const legs = transactionToLegs(tx);
|
|
1877
|
-
const classification = classifyTransaction(
|
|
2328
|
+
const classification = classifyTransaction(
|
|
2329
|
+
legs,
|
|
2330
|
+
tx,
|
|
2331
|
+
walletAddressStr2
|
|
2332
|
+
);
|
|
1878
2333
|
return { tx, classification, legs };
|
|
1879
2334
|
});
|
|
1880
2335
|
return enrichBatch(classified);
|
|
@@ -1887,11 +2342,15 @@ function createIndexer(options) {
|
|
|
1887
2342
|
while (accumulated.length < limit && iteration < MAX_ITERATIONS) {
|
|
1888
2343
|
iteration++;
|
|
1889
2344
|
const batchSize = iteration === 1 ? limit : limit * 2;
|
|
1890
|
-
const signatures = await fetchWalletSignatures(
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
2345
|
+
const signatures = await fetchWalletSignatures(
|
|
2346
|
+
client.rpc,
|
|
2347
|
+
walletAddress,
|
|
2348
|
+
{
|
|
2349
|
+
limit: batchSize,
|
|
2350
|
+
before: currentBefore,
|
|
2351
|
+
until
|
|
2352
|
+
}
|
|
2353
|
+
);
|
|
1895
2354
|
if (signatures.length === 0) {
|
|
1896
2355
|
break;
|
|
1897
2356
|
}
|
|
@@ -1905,7 +2364,11 @@ function createIndexer(options) {
|
|
|
1905
2364
|
const classified = transactions.map((tx) => {
|
|
1906
2365
|
tx.protocol = detectProtocol(tx.programIds);
|
|
1907
2366
|
const legs = transactionToLegs(tx);
|
|
1908
|
-
const classification = classifyTransaction(
|
|
2367
|
+
const classification = classifyTransaction(
|
|
2368
|
+
legs,
|
|
2369
|
+
tx,
|
|
2370
|
+
walletAddressStr
|
|
2371
|
+
);
|
|
1909
2372
|
return { tx, classification, legs };
|
|
1910
2373
|
});
|
|
1911
2374
|
const nonSpam = filterSpamTransactions(classified, spamConfig);
|
|
@@ -1921,7 +2384,10 @@ function createIndexer(options) {
|
|
|
1921
2384
|
return enrichBatch(result);
|
|
1922
2385
|
},
|
|
1923
2386
|
async getTransaction(signature2, options2 = {}) {
|
|
1924
|
-
const {
|
|
2387
|
+
const {
|
|
2388
|
+
enrichNftMetadata = true,
|
|
2389
|
+
enrichTokenMetadata: enrichTokens = true
|
|
2390
|
+
} = options2;
|
|
1925
2391
|
const tx = await fetchTransaction(client.rpc, signature2);
|
|
1926
2392
|
if (!tx) {
|
|
1927
2393
|
return null;
|
|
@@ -1930,6 +2396,9 @@ function createIndexer(options) {
|
|
|
1930
2396
|
const legs = transactionToLegs(tx);
|
|
1931
2397
|
const classification = classifyTransaction(legs, tx);
|
|
1932
2398
|
let classified = { tx, classification, legs };
|
|
2399
|
+
if (enrichTokens) {
|
|
2400
|
+
classified = await enrichTokenMetadata(tokenFetcher, classified);
|
|
2401
|
+
}
|
|
1933
2402
|
if (enrichNftMetadata && rpcUrl) {
|
|
1934
2403
|
classified = await enrichNftClassification(rpcUrl, classified);
|
|
1935
2404
|
}
|
|
@@ -2000,6 +2469,6 @@ function groupLegsByToken(legs) {
|
|
|
2000
2469
|
return grouped;
|
|
2001
2470
|
}
|
|
2002
2471
|
|
|
2003
|
-
export { JUPITER_V4_PROGRAM_ID, JUPITER_V6_PROGRAM_ID, KNOWN_TOKENS, SPL_MEMO_PROGRAM_ID, SYSTEM_PROGRAM_ID, TOKEN_INFO, TOKEN_PROGRAM_ID, buildAccountId, classifyTransaction, createIndexer, createSolanaClient, detectFacilitator, detectProtocol, extractMemo, fetchNftMetadata, fetchNftMetadataBatch, fetchTransaction, fetchTransactionsBatch, fetchWalletBalance, fetchWalletSignatures, filterSpamTransactions, getTokenInfo, groupLegsByAccount, groupLegsByToken, isSolanaPayTransaction, isSpamTransaction, parseAccountId, parseAddress, parseSignature, parseSolanaPayMemo, transactionToLegs, validateLegsBalance };
|
|
2472
|
+
export { JUPITER_V4_PROGRAM_ID, JUPITER_V6_PROGRAM_ID, KNOWN_TOKENS, LIQUID_STAKING_TOKENS, SPL_MEMO_PROGRAM_ID, SUPPORTED_STABLECOINS, SYSTEM_PROGRAM_ID, TOKEN_INFO, TOKEN_PROGRAM_ID, buildAccountId, classifyTransaction, createIndexer, createSolanaClient, createTokenFetcher, createUnknownToken, detectFacilitator, detectProtocol, extractMemo, fetchNftMetadata, fetchNftMetadataBatch, fetchTransaction, fetchTransactionsBatch, fetchWalletBalance, fetchWalletSignatures, filterSpamTransactions, getDefaultTokenFetcher, getTokenInfo, groupLegsByAccount, groupLegsByToken, isSolanaPayTransaction, isSpamTransaction, parseAccountId, parseAddress, parseSignature, parseSolanaPayMemo, transactionToLegs, validateLegsBalance };
|
|
2004
2473
|
//# sourceMappingURL=index.js.map
|
|
2005
2474
|
//# sourceMappingURL=index.js.map
|