Ari
Ari

Reputation: 6199

Get NFT transfers only in transaction data on Solana

Given a wallet address I want to find all transactions for NFTs that were sent to it. I have some code but not 100% certain its just doing NFTs. What is the identifier to determine if a transaction or parsed instruction is NFT related (SPL-Token??)

import {
    clusterApiUrl,
    ConfirmedSignaturesForAddress2Options,
    Connection,
    PublicKey,
} from '@solana/web3.js';
import fs from 'fs';
import path from 'path';

const WALLET = "<WALLET>"; // receiving NFTs
const LIMIT = 100;

(async () => {
    // Connect to the Solana cluster
    const c = new Connection(clusterApiUrl('mainnet-beta'));

    // The wallet receiving NFTs
    const p = new PublicKey(WALLET);

    // Query for signitures
    const opts: ConfirmedSignaturesForAddress2Options = {
        limit: 10,
    }
    const cs = await c.getConfirmedSignaturesForAddress2(p, opts);

    // Parse the signiture transaction data
    const td = [];
    for (let i = 0; i < cs.length; i++) {

        const s = cs[i];
        const d = await c.getParsedTransaction(s.signature, 'finalized');

        if (!d) continue;
        td.push(d);

    }

    // Build a map of mint source and destinations
    const tm: any = {};
    for (let i = 0; i < td.length; i++) {
        const d = td[i];

        d.meta?.postTokenBalances?.forEach(({ mint, owner }) => {

            if (!tm[mint]) tm[mint] = { destination: "", source: "" };
            if (owner === p.toString()) tm[mint].destination = owner;
            else tm[mint].source = owner;

        });
    }

    fs.writeFileSync(path.join(process.cwd(), 'nft-transfers.json'), JSON.stringify(tm, null, 2));

})();

Upvotes: 0

Views: 784

Answers (1)

Jon C
Jon C

Reputation: 8472

You're almost there! If you want to filter for NFTs, you need to check against the mint for the token that was transferred, and check that the supply for the mint is 1, e.g.:

// Parse the signiture transaction data
    const td = [];
    for (let i = 0; i < cs.length; i++) {

        const s = cs[i];
        const d = await c.getParsedTransaction(s.signature, 'finalized');

        if (!d) continue;
        if (d.meta.preTokenBalances.includes(1) &&
            d.meta.preTokenBalances.includes(0) &&
            d.meta.postTokenBalances.includes(1) &&
            d.meta.postTokenBalances.includes(0)) {
            td.push(d);
        }
    }

This is pretty janky, since it's just checking some accounts had 1 and 0 tokens, before and after. You can probably do something smarter with find to make sure that the account index with 1 and 0 changed.

Upvotes: 1

Related Questions