tx-indexer 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -3
- package/dist/{classification.types-DlJe6bDZ.d.ts → classification.types-Cn9IGtEC.d.ts} +13 -12
- package/dist/{client-yGDWPKKf.d.ts → client-iLW2_DnL.d.ts} +39 -3
- package/dist/client.d.ts +2 -2
- package/dist/client.js +129 -5
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +130 -6
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { C as ClassifiedTransaction, F as FetchTransactionsConfig, G as GetTransactionsOptions, I as IndexerRpcApi, S as SolanaClient,
|
|
2
|
-
import { T as TxLeg, R as RawTransaction, a as TransactionClassification } from './classification.types-
|
|
3
|
-
export { f as RawTransactionSchema, k as TokenBalance, e as TokenBalanceSchema, n as TransactionClassificationSchema, j as TxCategory, d as TxCategorySchema, h as TxDirection, b as TxDirectionSchema, m as TxLegRole, g as TxLegSchema, l as TxLegSide, i as TxPrimaryType, c as TxPrimaryTypeSchema } from './classification.types-
|
|
1
|
+
export { C as ClassifiedTransaction, F as FetchTransactionsConfig, b as GetTransactionOptions, G as GetTransactionsOptions, I as IndexerRpcApi, N as NftMetadata, S as SolanaClient, m as SpamFilterConfig, g as TokenAccountBalance, T as TxIndexer, a as TxIndexerOptions, W as WalletBalance, c as createIndexer, d as createSolanaClient, n as fetchNftMetadata, o as fetchNftMetadataBatch, i as fetchTransaction, j as fetchTransactionsBatch, f as fetchWalletBalance, h as fetchWalletSignatures, l as filterSpamTransactions, k as isSpamTransaction, p as parseAddress, e as parseSignature, t as transactionToLegs } from './client-iLW2_DnL.js';
|
|
2
|
+
import { T as TxLeg, R as RawTransaction, a as TransactionClassification } from './classification.types-Cn9IGtEC.js';
|
|
3
|
+
export { f as RawTransactionSchema, k as TokenBalance, e as TokenBalanceSchema, n as TransactionClassificationSchema, j as TxCategory, d as TxCategorySchema, h as TxDirection, b as TxDirectionSchema, m as TxLegRole, g as TxLegSchema, l as TxLegSide, i as TxPrimaryType, c as TxPrimaryTypeSchema } from './classification.types-Cn9IGtEC.js';
|
|
4
4
|
import { ProtocolInfo, TokenInfo } from './types.js';
|
|
5
5
|
export { Categorization, CategorizationSchema, Counterparty, CounterpartySchema, FiatValue, MoneyAmount, ProtocolInfoSchema } from './types.js';
|
|
6
6
|
import { z } from 'zod';
|
package/dist/index.js
CHANGED
|
@@ -428,6 +428,7 @@ async function fetchTransaction(rpc, signature2, commitment = "confirmed") {
|
|
|
428
428
|
signature: signature2,
|
|
429
429
|
slot: response.slot,
|
|
430
430
|
blockTime: response.blockTime,
|
|
431
|
+
fee: Number(response.meta?.fee ?? 0),
|
|
431
432
|
err: response.meta?.err ?? null,
|
|
432
433
|
programIds: extractProgramIds(response.transaction),
|
|
433
434
|
protocol: null,
|
|
@@ -1356,8 +1357,81 @@ function filterSpamTransactions(transactions, config) {
|
|
|
1356
1357
|
);
|
|
1357
1358
|
}
|
|
1358
1359
|
|
|
1360
|
+
// src/nft.ts
|
|
1361
|
+
async function fetchNftMetadata(rpcUrl, mintAddress) {
|
|
1362
|
+
const response = await fetch(rpcUrl, {
|
|
1363
|
+
method: "POST",
|
|
1364
|
+
headers: { "Content-Type": "application/json" },
|
|
1365
|
+
body: JSON.stringify({
|
|
1366
|
+
jsonrpc: "2.0",
|
|
1367
|
+
id: "get-asset",
|
|
1368
|
+
method: "getAsset",
|
|
1369
|
+
params: { id: mintAddress }
|
|
1370
|
+
})
|
|
1371
|
+
});
|
|
1372
|
+
const data = await response.json();
|
|
1373
|
+
if (data.error || !data.result?.content?.metadata) {
|
|
1374
|
+
return null;
|
|
1375
|
+
}
|
|
1376
|
+
const { result } = data;
|
|
1377
|
+
const { content, grouping } = result;
|
|
1378
|
+
return {
|
|
1379
|
+
mint: mintAddress,
|
|
1380
|
+
name: content.metadata.name,
|
|
1381
|
+
symbol: content.metadata.symbol,
|
|
1382
|
+
image: content.links.image ?? content.files?.[0]?.uri ?? "",
|
|
1383
|
+
cdnImage: content.files?.[0]?.cdn_uri,
|
|
1384
|
+
description: content.metadata.description,
|
|
1385
|
+
collection: grouping?.find((g) => g.group_key === "collection")?.group_value,
|
|
1386
|
+
attributes: content.metadata.attributes
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
async function fetchNftMetadataBatch(rpcUrl, mintAddresses) {
|
|
1390
|
+
const results = await Promise.all(
|
|
1391
|
+
mintAddresses.map((mint) => fetchNftMetadata(rpcUrl, mint))
|
|
1392
|
+
);
|
|
1393
|
+
const map = /* @__PURE__ */ new Map();
|
|
1394
|
+
results.forEach((metadata, index) => {
|
|
1395
|
+
if (metadata) {
|
|
1396
|
+
map.set(mintAddresses[index], metadata);
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
return map;
|
|
1400
|
+
}
|
|
1401
|
+
|
|
1359
1402
|
// src/client.ts
|
|
1403
|
+
var NFT_TRANSACTION_TYPES = ["nft_mint", "nft_purchase", "nft_sale"];
|
|
1404
|
+
async function enrichNftClassification(rpcUrl, classified) {
|
|
1405
|
+
const { classification } = classified;
|
|
1406
|
+
if (!NFT_TRANSACTION_TYPES.includes(classification.primaryType)) {
|
|
1407
|
+
return classified;
|
|
1408
|
+
}
|
|
1409
|
+
const nftMint = classification.metadata?.nft_mint;
|
|
1410
|
+
if (!nftMint) {
|
|
1411
|
+
return classified;
|
|
1412
|
+
}
|
|
1413
|
+
const nftData = await fetchNftMetadata(rpcUrl, nftMint);
|
|
1414
|
+
if (!nftData) {
|
|
1415
|
+
return classified;
|
|
1416
|
+
}
|
|
1417
|
+
return {
|
|
1418
|
+
...classified,
|
|
1419
|
+
classification: {
|
|
1420
|
+
...classification,
|
|
1421
|
+
metadata: {
|
|
1422
|
+
...classification.metadata,
|
|
1423
|
+
nft_name: nftData.name,
|
|
1424
|
+
nft_image: nftData.image,
|
|
1425
|
+
nft_cdn_image: nftData.cdnImage,
|
|
1426
|
+
nft_collection: nftData.collection,
|
|
1427
|
+
nft_symbol: nftData.symbol,
|
|
1428
|
+
nft_attributes: nftData.attributes
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1360
1433
|
function createIndexer(options) {
|
|
1434
|
+
const rpcUrl = "client" in options ? "" : options.rpcUrl;
|
|
1361
1435
|
const client = "client" in options ? options.client : createSolanaClient(options.rpcUrl, options.wsUrl);
|
|
1362
1436
|
return {
|
|
1363
1437
|
rpc: client.rpc,
|
|
@@ -1365,7 +1439,39 @@ function createIndexer(options) {
|
|
|
1365
1439
|
return fetchWalletBalance(client.rpc, walletAddress, tokenMints);
|
|
1366
1440
|
},
|
|
1367
1441
|
async getTransactions(walletAddress, options2 = {}) {
|
|
1368
|
-
const { limit = 10, before, until, filterSpam = true, spamConfig } = options2;
|
|
1442
|
+
const { limit = 10, before, until, filterSpam = true, spamConfig, enrichNftMetadata = true } = options2;
|
|
1443
|
+
async function enrichBatch(transactions) {
|
|
1444
|
+
if (!enrichNftMetadata || !rpcUrl) {
|
|
1445
|
+
return transactions;
|
|
1446
|
+
}
|
|
1447
|
+
const nftMints = transactions.filter((t) => NFT_TRANSACTION_TYPES.includes(t.classification.primaryType)).map((t) => t.classification.metadata?.nft_mint).filter(Boolean);
|
|
1448
|
+
if (nftMints.length === 0) {
|
|
1449
|
+
return transactions;
|
|
1450
|
+
}
|
|
1451
|
+
const nftMetadataMap = await fetchNftMetadataBatch(rpcUrl, nftMints);
|
|
1452
|
+
return transactions.map((t) => {
|
|
1453
|
+
const nftMint = t.classification.metadata?.nft_mint;
|
|
1454
|
+
if (!nftMint || !nftMetadataMap.has(nftMint)) {
|
|
1455
|
+
return t;
|
|
1456
|
+
}
|
|
1457
|
+
const nftData = nftMetadataMap.get(nftMint);
|
|
1458
|
+
return {
|
|
1459
|
+
...t,
|
|
1460
|
+
classification: {
|
|
1461
|
+
...t.classification,
|
|
1462
|
+
metadata: {
|
|
1463
|
+
...t.classification.metadata,
|
|
1464
|
+
nft_name: nftData.name,
|
|
1465
|
+
nft_image: nftData.image,
|
|
1466
|
+
nft_cdn_image: nftData.cdnImage,
|
|
1467
|
+
nft_collection: nftData.collection,
|
|
1468
|
+
nft_symbol: nftData.symbol,
|
|
1469
|
+
nft_attributes: nftData.attributes
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
});
|
|
1474
|
+
}
|
|
1369
1475
|
if (!filterSpam) {
|
|
1370
1476
|
const signatures = await fetchWalletSignatures(client.rpc, walletAddress, {
|
|
1371
1477
|
limit,
|
|
@@ -1388,7 +1494,7 @@ function createIndexer(options) {
|
|
|
1388
1494
|
const classification = classifyTransaction(legs, tx);
|
|
1389
1495
|
return { tx, classification, legs };
|
|
1390
1496
|
});
|
|
1391
|
-
return classified;
|
|
1497
|
+
return enrichBatch(classified);
|
|
1392
1498
|
}
|
|
1393
1499
|
const accumulated = [];
|
|
1394
1500
|
let currentBefore = before;
|
|
@@ -1427,9 +1533,11 @@ function createIndexer(options) {
|
|
|
1427
1533
|
break;
|
|
1428
1534
|
}
|
|
1429
1535
|
}
|
|
1430
|
-
|
|
1536
|
+
const result = accumulated.slice(0, limit);
|
|
1537
|
+
return enrichBatch(result);
|
|
1431
1538
|
},
|
|
1432
|
-
async getTransaction(signature2) {
|
|
1539
|
+
async getTransaction(signature2, options2 = {}) {
|
|
1540
|
+
const { enrichNftMetadata = true } = options2;
|
|
1433
1541
|
const tx = await fetchTransaction(client.rpc, signature2);
|
|
1434
1542
|
if (!tx) {
|
|
1435
1543
|
return null;
|
|
@@ -1437,10 +1545,26 @@ function createIndexer(options) {
|
|
|
1437
1545
|
tx.protocol = detectProtocol(tx.programIds);
|
|
1438
1546
|
const legs = transactionToLegs(tx);
|
|
1439
1547
|
const classification = classifyTransaction(legs, tx);
|
|
1440
|
-
|
|
1548
|
+
let classified = { tx, classification, legs };
|
|
1549
|
+
if (enrichNftMetadata && rpcUrl) {
|
|
1550
|
+
classified = await enrichNftClassification(rpcUrl, classified);
|
|
1551
|
+
}
|
|
1552
|
+
return classified;
|
|
1441
1553
|
},
|
|
1442
1554
|
async getRawTransaction(signature2) {
|
|
1443
1555
|
return fetchTransaction(client.rpc, signature2);
|
|
1556
|
+
},
|
|
1557
|
+
async getNftMetadata(mintAddress) {
|
|
1558
|
+
if (!rpcUrl) {
|
|
1559
|
+
throw new Error("getNftMetadata requires rpcUrl to be set");
|
|
1560
|
+
}
|
|
1561
|
+
return fetchNftMetadata(rpcUrl, mintAddress);
|
|
1562
|
+
},
|
|
1563
|
+
async getNftMetadataBatch(mintAddresses) {
|
|
1564
|
+
if (!rpcUrl) {
|
|
1565
|
+
throw new Error("getNftMetadataBatch requires rpcUrl to be set");
|
|
1566
|
+
}
|
|
1567
|
+
return fetchNftMetadataBatch(rpcUrl, mintAddresses);
|
|
1444
1568
|
}
|
|
1445
1569
|
};
|
|
1446
1570
|
}
|
|
@@ -1492,6 +1616,6 @@ function groupLegsByToken(legs) {
|
|
|
1492
1616
|
return grouped;
|
|
1493
1617
|
}
|
|
1494
1618
|
|
|
1495
|
-
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, fetchTransaction, fetchTransactionsBatch, fetchWalletBalance, fetchWalletSignatures, filterSpamTransactions, getTokenInfo, groupLegsByAccount, groupLegsByToken, isSolanaPayTransaction, isSpamTransaction, parseAccountId, parseAddress, parseSignature, parseSolanaPayMemo, transactionToLegs, validateLegsBalance };
|
|
1619
|
+
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 };
|
|
1496
1620
|
//# sourceMappingURL=index.js.map
|
|
1497
1621
|
//# sourceMappingURL=index.js.map
|