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/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
- USDG: "2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH"
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.USDC_BRIDGED]: {
39
- mint: KNOWN_TOKENS.USDC_BRIDGED,
40
- symbol: "USDCet",
41
- name: "USDC (Bridged)",
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.USDG
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 { limit = 10, before, until, filterSpam = true, spamConfig, enrichNftMetadata = true } = options2;
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
- if (!enrichNftMetadata || !rpcUrl) {
1827
- return transactions;
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
- const nftMetadataMap = await fetchNftMetadataBatch(rpcUrl, nftMints);
1834
- return transactions.map((t) => {
1835
- const nftMint = t.classification.metadata?.nft_mint;
1836
- if (!nftMint || !nftMetadataMap.has(nftMint)) {
1837
- return t;
1838
- }
1839
- const nftData = nftMetadataMap.get(nftMint);
1840
- return {
1841
- ...t,
1842
- classification: {
1843
- ...t.classification,
1844
- metadata: {
1845
- ...t.classification.metadata,
1846
- nft_name: nftData.name,
1847
- nft_image: nftData.image,
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(client.rpc, walletAddress, {
1859
- limit,
1860
- before,
1861
- until
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(legs, tx, walletAddressStr2);
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(client.rpc, walletAddress, {
1891
- limit: batchSize,
1892
- before: currentBefore,
1893
- until
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(legs, tx, walletAddressStr);
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 { enrichNftMetadata = true } = options2;
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