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"); +