You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import{AnchorProvider,Wallet}from"@coral-xyz/anchor";import{Connection,Keypair,PublicKey}from"@solana/web3.js";import{getLeafAssetId}from"@tensor-hq/tensor-common";import{findListStatePda,findTreeAuthorityPda,TCompSDK,}from"@tensor-oss/tcomp-sdk";importBNfrom"bn.js";constconn=newConnection("https://api.mainnet-beta.solana.com");constprovider=newAnchorProvider(conn,newWallet(Keypair.generate()),AnchorProvider.defaultOptions());consttcompSdk=newTCompSDK({ provider });// Listing cNFTconst{tx: { ixs },}=awaittcompSdk.list({// Retrieve these fields from DAS API
merkleTree,
root,
canopyDepth,
index,
proof,
dataHash,
creatorsHash,delegate: delegatePk,owner: ownerPk,rentPayer: rentPayerPk,// optional: payer and recipient of listing rentamount: newBN(priceLamports),// in lamportscurrency: null,// optional: list for SOL or SPL tokensexpireInSec: expireIn ? newBN(expireIn) : null,// seconds until listing expiresprivateTaker: takerPk,// optional: only this wallet can buy this listing});// Fetching the listingconstnonce=newBN(index);const[treeAuthority]=findTreeAuthorityPda({ merkleTree });constassetId=getLeafAssetId(merkleTree,nonce);constlistState=findListStatePda({ assetId });const{assetId: listStateAssetId,
owner,
amount,
currency,
expiry,
privateTaker,
makerBroker,
rentPayer,}=awaittcompSdk.fetchListState(listState);// Buying cNFTconst{tx: { ixs },}=awaittcompSdk.buy({// Retrieve these fields from DAS API
merkleTree,
root,
canopyDepth,
index,
proof,
sellerFeeBasisPoints,// For constructing metaHash, see example below
metaHash,
creators,payer: payerPk,buyer: buyerPk,owner: ownerPk,
makerBroker,
rentDest,maxAmount: newBN(priceLamports),optionalRoyaltyPct: 100,// currently required to be 100% (enforced)});// Bidding on a single cNFTconst{tx: { ixs },}=awaittcompSdk.bid({owner: ownerPk,rentPayer: rentPayerPK,// optional: payer and recipient of bid rentamount: newBN(priceLamports),expireInSec: expireIn ? newBN(expireIn) : null,// seconds until listing expiresprivateTaker: takerPk,// optional: only this wallet can sell into this bidbidId: newPublicKey(assetId),// asset ID of nft to bid ontargetId: newPublicKey(assetId),// asset ID of nft to bid ontarget: Target.AssetId,quantity: 1,// Ignore these for now (advanced usage)margin: null,field: null,fieldId: null,});
Constructing metaHash
constaxios=require('axios');constBN=require('bn.js');const{ PublicKey }=require("@solana/web3.js");const{ keccak_256 }=require('js-sha3');const{ computeMetadataArgsHash }=require("@tensor-hq/tensor-common");const{ TokenStandard }=require('@metaplex-foundation/mpl-bubblegum');consturl=`https://mainnet.helius-rpc.com/?api-key=<YOUR_HELIUS_API_KEY>`constconstructMetaHash=async(mint)=>{// query DAS API for asset infoconstassetRes=awaitaxios.post(url,{jsonrpc: '2.0',id: '0',method: 'getAsset',params: {id: mint}});const{
compression,
content,
royalty,
creators,
uses,
grouping,
supply,ownership: { owner, delegate },
mutable,}=assetRes.data.result;constcoll=grouping.find((group)=>group.group_key==="collection")?.group_value;consttokenStandard=content.metadata.token_standardconstdataHashBuffer=newPublicKey(compression.data_hash).toBuffer();// construct metadataArgs to hash later// ordering follows https://docs.metaplex.com/programs/token-metadata/accountsvarmetadataArgs={name: content?.metadata?.name??"",symbol: content?.metadata?.symbol??" ",uri: content?.json_uri??"",sellerFeeBasisPoints: royalty.basis_points,creators: creators.map((creator)=>({address: newPublicKey(creator.address),share: creator.share,verified: creator.verified,})),primarySaleHappened: royalty.primary_sale_happened,isMutable: mutable,editionNonce: supply?.edition_nonce!=null ? supply!.edition_nonce : null,tokenStandard: tokenStandard==="Fungible" ? TokenStandard.Fungible :
tokenStandard==="NonFungibleEdition" ? TokenStandard.NonFungibleEdition :
tokenStandard==="FungibleAsset" ? TokenStandard.FungibleAsset :
TokenStandard.NonFungible,// if Helius shows a collection in groupings for a cNFT then it's verifiedcollection: coll ? {key: newPublicKey(coll),verified: true} : null,uses: uses
? {useMethod: uses.use_method==="Burn" ? 0 : uses.use_method==="Multiple" ? 1 : 2,remaining: uses.remaining,total: uses.total,}
: null,// currently always Original (Token2022 not supported yet)tokenProgramVersion: 0,};constoriginalMetadata={ ...metadataArgs};constsellerFeeBasisPointsBuffer=newBN(royalty.basis_points).toBuffer("le",2);// hash function on top of candidate metaHash to compare against data_hashconstmakeDataHash=(metadataArgs)=>Buffer.from(keccak_256.digest(Buffer.concat([newPublicKey(computeMetadataArgsHash(metadataArgs)).toBuffer(),sellerFeeBasisPointsBuffer,])));// try original metadataArgsvarhash=makeDataHash(metadataArgs);if(hash.equals(dataHashBuffer))returncomputeMetadataArgsHash(metadataArgs);// try tokenStandard = nullmetadataArgs.tokenStandard=null;hash=makeDataHash(metadataArgs);if(hash.equals(dataHashBuffer))returncomputeMetadataArgsHash(metadataArgs);// try name + uri = "", tokenStandard = nullmetadataArgs.name="";metadataArgs.uri="";hash=makeDataHash(metadataArgs);if(hash.equals(dataHashBuffer))returncomputeMetadataArgsHash(metadataArgs);// try name + uri = "", tokenStandard = 0metadataArgs.tokenStandard=0;hash=makeDataHash(metadataArgs);if(hash.equals(dataHashBuffer))returncomputeMetadataArgsHash(metadataArgs);// try reversing creatorsmetadataArgs.creators.reverse();metadataArgs.name=originalMetadata.name;metadataArgs.uri=originalMetadata.uri;metadataArgs.tokenStandard=originalMetadata.tokenStandard;hash=makeDataHash(metadataArgs);if(hash.equals(dataHashBuffer))returncomputeMetadataArgsHash(metadataArgs);// can't match - return nullreturnnull;};constructMetaHash("8H6C2tGh5Yu5jGXUbFtZ17FQTDyBAEQ4LfGA527QLXYQ");