spl data fetch fixed
This commit is contained in:
parent
7f8a87cfa2
commit
3d31c1efaa
15
src/index.ts
15
src/index.ts
|
|
@ -3,13 +3,14 @@ import { config } from './config';
|
||||||
import { logger } from './utils/logger';
|
import { logger } from './utils/logger';
|
||||||
import transactionRoutes from './routes/transactionRoutes';
|
import transactionRoutes from './routes/transactionRoutes';
|
||||||
import { getConnection } from './utils/database';
|
import { getConnection } from './utils/database';
|
||||||
import { getTransaction } from './utils/explorer';
|
import { getTransaction, getTransactionRaw } from './utils/explorer';
|
||||||
import { TransactionValidationService } from './services/transactionValidationService';
|
import { TransactionValidationService } from './services/transactionValidationService';
|
||||||
|
import { CLUSTER_API } from './data';
|
||||||
logger.info("Starting server...");
|
logger.info("Starting server...");
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = config.port;
|
const PORT = config.port;
|
||||||
logger.info(`port: ${PORT}`);
|
logger.info(`port: ${PORT}`);
|
||||||
logger.info(`nodeEnv: ${config.nodeEnv}`);
|
logger.info(`nodeEnv: ${config.nodeEnv} : ${CLUSTER_API}`);
|
||||||
logger.info(`logLevel: ${config.logLevel}`);
|
logger.info(`logLevel: ${config.logLevel}`);
|
||||||
|
|
||||||
getConnection().then(() => {
|
getConnection().then(() => {
|
||||||
|
|
@ -42,9 +43,19 @@ app.get('/health', (_req: Request, res: Response) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/solana/tx/:txHash', async (req: Request, res: Response) => {
|
app.get('/solana/tx/:txHash', async (req: Request, res: Response) => {
|
||||||
|
|
||||||
|
const {raw} = req.query;
|
||||||
|
|
||||||
|
if(raw=="true"){
|
||||||
|
const tx = await getTransactionRaw(req.params.txHash);
|
||||||
|
res.json(tx);
|
||||||
|
}else{
|
||||||
const txHash = req.params.txHash;
|
const txHash = req.params.txHash;
|
||||||
const transaction = await getTransaction(txHash);
|
const transaction = await getTransaction(txHash);
|
||||||
res.json(transaction);
|
res.json(transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Validation service control endpoints
|
// Validation service control endpoints
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,27 @@
|
||||||
import { CLUSTER_API } from "../data";
|
import { CLUSTER_API } from "../data";
|
||||||
import { Connection } from "@solana/web3.js";
|
import { Connection, ParsedTransactionWithMeta, PublicKey } from "@solana/web3.js";
|
||||||
import { TransferData } from "../types";
|
import { TransferData } from "../types";
|
||||||
|
import { logger } from "./logger";
|
||||||
|
|
||||||
export async function getTransaction(txHash: string) {
|
export async function getTransactionRaw(txHash: string) {
|
||||||
const connection = new Connection(CLUSTER_API, { commitment: 'finalized' });
|
const connection = new Connection(CLUSTER_API, { commitment: 'confirmed' });
|
||||||
|
|
||||||
const transaction = await connection.getParsedTransaction(txHash, {
|
const transaction = await connection.getParsedTransaction(txHash, {
|
||||||
maxSupportedTransactionVersion: 0,
|
maxSupportedTransactionVersion: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
const transaction_formatted = extractTokenTransferData(transaction);
|
return transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTransaction(txHash: string) {
|
||||||
|
const transaction = await getTransactionRaw(txHash);
|
||||||
|
|
||||||
|
if (!transaction) {
|
||||||
|
logger.error(`Blockchain couldn't find transaction: ${txHash}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transaction_formatted = await extractTokenTransferData(transaction);
|
||||||
return transaction_formatted;
|
return transaction_formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,12 +53,38 @@ export function extractNativeSolTransferData(transaction: any): TransferData | n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractSplTokenTransferData(transaction: any): TransferData | null {
|
async function getAtaOwner(ataAddress: string): Promise<string> {
|
||||||
|
try {
|
||||||
|
const connection = new Connection(CLUSTER_API, { commitment: 'confirmed' });
|
||||||
|
const ataPublicKey = new PublicKey(ataAddress);
|
||||||
|
const accountInfo = await connection.getAccountInfo(ataPublicKey);
|
||||||
|
|
||||||
|
if (!accountInfo) {
|
||||||
|
logger.warn(`Could not find account info for ATA: ${ataAddress}`);
|
||||||
|
return ataAddress; // Fallback to ATA address if we can't get owner
|
||||||
|
}
|
||||||
|
|
||||||
|
// The owner is stored in the account data at a specific offset
|
||||||
|
// For token accounts, the owner is at offset 32
|
||||||
|
const ownerBytes = accountInfo.data.slice(32, 64);
|
||||||
|
const owner = new PublicKey(ownerBytes);
|
||||||
|
|
||||||
|
return owner.toString();
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`Error getting ATA owner: ${error}`);
|
||||||
|
return ataAddress; // Fallback to ATA address if there's an error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function extractSplTokenTransferData(transaction: any): Promise<TransferData | null> {
|
||||||
try {
|
try {
|
||||||
// Check if this is an SPL token transfer
|
// Check if this is an SPL token transfer
|
||||||
const instructions = transaction.transaction.message.instructions;
|
const instructions = transaction.transaction.message.instructions;
|
||||||
|
|
||||||
|
// Try to find either transferChecked or transfer instruction
|
||||||
const tokenTransferInstruction = instructions.find((instruction: any) =>
|
const tokenTransferInstruction = instructions.find((instruction: any) =>
|
||||||
instruction.program === "spl-token" && instruction.parsed?.type === "transferChecked"
|
instruction.program === "spl-token" &&
|
||||||
|
(instruction.parsed?.type === "transferChecked" || instruction.parsed?.type === "transfer")
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!tokenTransferInstruction) {
|
if (!tokenTransferInstruction) {
|
||||||
|
|
@ -55,21 +93,47 @@ export function extractSplTokenTransferData(transaction: any): TransferData | nu
|
||||||
|
|
||||||
const transferInfo = tokenTransferInstruction.parsed.info;
|
const transferInfo = tokenTransferInstruction.parsed.info;
|
||||||
|
|
||||||
|
// For transferChecked type
|
||||||
|
if (tokenTransferInstruction.parsed.type === "transferChecked") {
|
||||||
|
const receiverOwner = await getAtaOwner(transferInfo.destination);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sender: transferInfo.source,
|
sender: transferInfo.authority,
|
||||||
receiver: transferInfo.destination,
|
receiver: receiverOwner,
|
||||||
amount: parseInt(transferInfo.tokenAmount.amount),
|
amount: parseInt(transferInfo.tokenAmount.amount),
|
||||||
mint: transferInfo.mint,
|
mint: transferInfo.mint,
|
||||||
time: transaction.blockTime,
|
time: transaction.blockTime,
|
||||||
blockhash: transaction.transaction.message.recentBlockhash
|
blockhash: transaction.transaction.message.recentBlockhash
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`It's not a transferChecked`);
|
||||||
|
|
||||||
|
// For transfer type
|
||||||
|
const tokenBalances = transaction.meta.preTokenBalances;
|
||||||
|
const mint = tokenBalances[0]?.mint;
|
||||||
|
|
||||||
|
if (!mint) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const receiverOwner = await getAtaOwner(transferInfo.destination);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sender: transferInfo.authority,
|
||||||
|
receiver: receiverOwner,
|
||||||
|
amount: parseInt(transferInfo.amount),
|
||||||
|
mint: mint,
|
||||||
|
time: transaction.blockTime,
|
||||||
|
blockhash: transaction.transaction.message.recentBlockhash
|
||||||
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error extracting SPL token transfer data:", error);
|
console.error("Error extracting SPL token transfer data:", error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractTokenTransferData(transaction: any): TransferData | null {
|
export async function extractTokenTransferData(transaction: ParsedTransactionWithMeta): Promise<TransferData | null> {
|
||||||
// Try to extract native SOL transfer first
|
// Try to extract native SOL transfer first
|
||||||
const nativeSolData = extractNativeSolTransferData(transaction);
|
const nativeSolData = extractNativeSolTransferData(transaction);
|
||||||
if (nativeSolData) {
|
if (nativeSolData) {
|
||||||
|
|
@ -77,10 +141,12 @@ export function extractTokenTransferData(transaction: any): TransferData | null
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to extract SPL token transfer
|
// Try to extract SPL token transfer
|
||||||
const splTokenData = extractSplTokenTransferData(transaction);
|
const splTokenData = await extractSplTokenTransferData(transaction);
|
||||||
if (splTokenData) {
|
if (splTokenData) {
|
||||||
return splTokenData;
|
return splTokenData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.error(`Error extracting token transfer data: ${transaction}`);
|
||||||
|
|
||||||
return null; // Not a recognized token transfer
|
return null; // Not a recognized token transfer
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user