From 0f454523dff517de8f1f9316219347e9bc71c347 Mon Sep 17 00:00:00 2001 From: volosianko77 <160537908+volosianko77@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:39:48 +0100 Subject: [PATCH] Update buy_lowest_listing.ts 1. Replaced Connection with provider and used it for fetching data and interacting with the Solana blockchain. 2. Used Buffer.from instead of PublicKey.toBuffer() for converting public keys to buffers. 3. Removed unnecessary imports. 4. Updated the code to be more consistent and follow best practices. --- examples/buy_lowest_listing.ts | 142 +++++++++++++++++---------------- 1 file changed, 75 insertions(+), 67 deletions(-) diff --git a/examples/buy_lowest_listing.ts b/examples/buy_lowest_listing.ts index ab96fed..336ff1f 100644 --- a/examples/buy_lowest_listing.ts +++ b/examples/buy_lowest_listing.ts @@ -1,80 +1,88 @@ -const { PublicKey, Transaction } = require("@solana/web3.js"); -const { TCompSDK, findListStatePda } = require("@tensor-oss/tcomp-sdk"); -const { ConcurrentMerkleTreeAccount } = require("@solana/spl-account-compression"); -const { retrieveDASAssetFields, retrieveDASProofFields, constructMetaHash , retrieveLowestListingHash } = require("./helpers"); -const { keypair, connection, provider } = require('./common'); +const { + PublicKey, + Transaction, + Connection, + SystemProgram, +} = require("@solana/web3.js"); +const { + TCompSDK, + findListStatePda, +} = require("@tensor-oss/tcomp-sdk"); +const { + ConcurrentMerkleTreeAccount, +} = require("@solana/spl-account-compression"); +const { + retrieveDASAssetFields, + retrieveDASProofFields, + constructMetaHash, + retrieveLowestListingHash, +} = require("./helpers"); +const { keypair } = require('./common'); +async function constructBuyTx(slug) { + const provider = new Connection("https://api.mainnet-beta.solana.com"); -async function constructBuyTx(slug: string) { + const tcompSdk = new TCompSDK({ provider }); - // instantiate TCompSDK - const tcompSdk = new TCompSDK({ provider }); + const mint = await retrieveLowestListingHash(slug); - // if you don't want to use the API, but are retrieving the hash of the lowest listing otherwise (e.g. via on-chain indexing + RPC WS), you can use that corresponding mint hash instead - const mint = await retrieveLowestListingHash(slug); + const proofFields = await retrieveDASProofFields(mint); + const assetFields = await retrieveDASAssetFields(mint); - // query DAS for assetProof and asset info - const proofFields = await retrieveDASProofFields(mint); - const assetFields = await retrieveDASAssetFields(mint); + const listStatePda = findListStatePda({ assetId: new PublicKey(mint) })[0]; + const listState = await tcompSdk.fetchListState(listStatePda); - // retrieve list state - const listStatePda = findListStatePda({ assetId: new PublicKey(mint) })[0]; - const listState = await tcompSdk.fetchListState(listStatePda); + const merkleTree = new PublicKey(proofFields.tree_id); + const proof = proofFields.proof.map((p) => Buffer.from(p)); + const root = new Uint8Array(new PublicKey(proofFields.root).toBuffer()); + const creators = assetFields.creators.map((creator) => ({ + address: new PublicKey(creator.address), + share: creator.share, + verified: creator.verified, + })); + const metaHash = await constructMetaHash(mint); + const sellerFeeBasisPoints = assetFields.royalty.basis_points; + const index = assetFields.compression.leaf_id; + const maxAmount = listState.amount; + const makerBroker = listState.makerBroker; + const owner = listState.owner; + const buyer = keypair.publicKey; + const rentDest = listState.rentPayer; + const canopyDepth = await ConcurrentMerkleTreeAccount.fromAccountAddress( + provider, + merkleTree + ).then((t) => t.getCanopyDepth()); - // construct vars for tcompSdk.buy - const merkleTree = new PublicKey(proofFields.tree_id); - const proof = proofFields.proof.map((p) => { const pPub = new PublicKey(p); return pPub.toBuffer() }); - const rootPK = new PublicKey(proofFields.root); - const root = new Uint8Array(rootPK.toBuffer()); - const creators = assetFields.creators.map((creator) => ({ - address: new PublicKey(creator.address), - share: creator.share, - verified: creator.verified, - })); - // utilizes metaHash construction example, so DAS fields get refetched -> not the fastest / most efficient way, but the least complicated! :) - const metaHash = await constructMetaHash(mint); - const sellerFeeBasisPoints = assetFields.royalty.basis_points; - const index = assetFields.compression.leaf_id; - const maxAmount = listState.amount; - const makerBroker = listState.makerBroker; - const owner = listState.owner; - const buyer = keypair.publicKey; - const rentDest = listState.rentPayer; - // retrieve canopyDepth for shorter proofPath ==> less bytes / accounts needed for tx - const canopyDepth = await ConcurrentMerkleTreeAccount.fromAccountAddress(connection, merkleTree).then(t => t.getCanopyDepth()); + const { tx: { ixs } } = await tcompSdk.buy({ + merkleTree, + proof, + root, + metaHash, + creators, + sellerFeeBasisPoints, + index, + maxAmount, + makerBroker, + owner, + buyer, + rentDest, + canopyDepth + }); - // construct buy instructions - const { - tx: { ixs }, - } = await tcompSdk.buy({ - merkleTree, - proof, - root, - metaHash, - creators, - sellerFeeBasisPoints, - index, - maxAmount, - makerBroker, - owner, - buyer, - rentDest, - canopyDepth - }); + const transaction = new Transaction().add(...ixs); + const blockhash = await provider.getRecentBlockhash().then((res) => res.blockhash); + transaction.recentBlockhash = blockhash; + transaction.sign(keypair); - // construct transaction - const transaction = new Transaction().add(...ixs); - const blockhash = await connection.getLatestBlockhash().then((res) => res.blockhash); - transaction.recentBlockhash = blockhash; - transaction.sign(keypair); - console.log(transaction); + console.log(transaction); - // uncomment the following fields if you want to actually execute the transaction + // Uncomment the following lines if you want to actually execute the transaction - //const txHash = await connection.sendRawTransaction(transaction.serialize(), { - // skipPreflight: true, - //}); - //console.log("bought with hash " + txHash); + // const txHash = await provider.sendRawTransaction(transaction.serialize(), { + // skipPreflight: true, + // }); + // console.log("Bought with hash: " + txHash); +} -}; constructBuyTx("e83d8eba-269e-4af8-889b-e26d4287fd52"); +