📝 Tensor Transactions

Introduction

All endpoints that require a Transaction to be sent to the Solana network will return a list of serialized transactions.

Before you're able to send them to the network you will need to deserialize and sign them with the necessary wallets.

🚧

All transaction endpoints have two fields: tx and txV0.

If txV0 is non-null, then you MUST use VersionedTransaction otherwise it will fail due to Solana tx size limits.

If txV0 is null, you may safely send the tx as a legacy Transaction.

Example - Buy the Floor Listing of a Collection

const {
    Connection,
    Transaction,
    VersionedTransaction,
    Keypair
} = require("@solana/web3.js");
const path = require("path");
const fs = require("fs");

// Load Environment Values
const TENSOR_API_KEY = process.env.TENSOR_API_KEY
const COLLECTION_SLUG = process.env.COLLECTION_SLUG
const SOLANA_RPC = process.env.SOLANA_RPC

// Connect to Solana and Load Local Wallet
const connection = new Connection(SOLANA_RPC);
const walletPath = path.join(process.env.HOME, ".config", "solana", "id.json");
const walletData = fs.readFileSync(walletPath, "utf8");
let wallet = Keypair.fromSecretKey(Uint8Array.from(JSON.parse(walletData)));

// Configure Tensor API Fetch Options
const options = {
    method: "GET",
    headers: {
        accept: "application/json",
        "x-tensor-api-key": TENSOR_API_KEY,
    },
};

// API Endpoint for Collection active Listings
const url = "https://api.mainnet.tensordev.io/api/v1/mint/collection";

// Configure Query Parameters and construct API URL
const queryParams = new URLSearchParams();
queryParams.append("slug", COLLECTION_SLUG);
queryParams.append("sortBy", "ListingPriceAsc");
queryParams.append("limit", 1);
queryParams.append("onlyListings", "true");
const fullUrl = `${url}?${queryParams.toString()}`;

// Fetch Listings
fetch(fullUrl, options)
    .then((response) => response.json())
    .then(async (response) => {

        // Fetch Latest Blockhash, needed to send Transaction
        const blockhash = await connection.getLatestBlockhash();
        return {
            response,
            blockhash
        };
    })
    .then(async ({
        response,
        blockhash
    }) => {

        // API Endpoint for NFT BUY, construct request URL
        const buyUrl = "https://api.mainnet.tensordev.io/api/v1/tx/buy";
        const buyParams = new URLSearchParams();

        buyParams.append("buyer", wallet.publicKey.toString());
        buyParams.append("mint", response.mints[0].mint);
        buyParams.append("owner", response.mints[0].listing.seller);
        buyParams.append("maxPrice", response.mints[0].listing.price);
        buyParams.append("blockhash", blockhash.blockhash);

        const fullBuyUrl = `${buyUrl}?${buyParams.toString()}`;

        // Fetch BUY NFT Tr
        const buyResponse = await fetch(fullBuyUrl, options);
        return buyResponse.json();
    })
    .then(async (response) => {
        // Deserialize the transactions
        const txsToSign = response.txs.map((tx) =>
            tx.txV0 ?
            VersionedTransaction.deserialize(response.txs[0].txV0.data) :
            Transaction.from(tx.tx.data)
        );

        // Sign Transactions
        txsToSign.map((tx) =>
            tx instanceof VersionedTransaction ?
            tx.sign([wallet]) :
            tx.sign(wallet)
        );

        // Send Transactions to Network
        for (const tx of txsToSign) {
            const sig = await connection.sendTransaction(tx);
            await connection.confirmTransaction(sig, "confirmed");
            console.log(`Transaction confirmed. https://solscan.io/tx/${sig}`);
        }
    })
    .catch((err) => console.error(err));

Additional Examples

Be sure to check out the recipes page for additional examples on API calls and Transaction deserialization!