The recipe to develop NFT auction program on Solana chain.
solana-auction
This is the recipe to develop auction program on solana chain.
Prerequisite knowledge for this recipe
Specifications of this auction system
An auction system in which bidders pay FT and make a successful bid for the listed NFT.sequenceDiagram
participant Exhibitor
participant Bidder1
participant Bidder2
participant Escrow
Exhibitor ->>+ Escrow: send 1 NFT with the initial price 200 FT
Note over Escrow: hold 1 NFT
Escrow -->>- Exhibitor: result
Bidder1 ->>+ Escrow: bid with 201 FT (send 201 FT as deposit)
Note over Escrow: hold 201 FT
Escrow -->>- Bidder1: result
Bidder2 ->>+ Escrow: bid with 202 FT (send 202 FT as deposit)
Escrow ->>+ Bidder1: send the deposited 201 FT
Note over Escrow: hold 202 FT
Escrow -->>- Bidder2: result
Note over Bidder2: wait for the auction end <br/> (default 3600 sec)
Bidder2 ->>+ Escrow: receive 1 NFT
Escrow ->>+ Exhibitor: send 202 FT
Note over Bidder2: hold 1 NFT
Note over Exhibitor: hold 202 FT
Escrow -->>- Bidder2: result
- The exhibitor exhibits any NFT
- The bidder decides the bid amount and bids
- The exhibitor can cancel the auction
- The highest bidder after the auction deadline is the winning bidder.
Run
Build the solana program
cd program
cargo build-bpf
Run validator on the localnet
cd scripts
npm run setup-validator ../program/target/deploy/solana_auction.so
Setup
Create the wallets of exhibitor and bidders and token accounts for FT and NFT.npm run setup
โโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ Wallet Pubkey โ FT โ FT(NAO) Account PubKey โ NFT โ NFT(X) Account PubKey โ โโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ exhibitor โ '56soKhmhDDx9A4BUqVZmr7ENqBxroFZmtrNTzw47S5Dr' โ 500 โ '82eyhAL5iWqFaF2SEvWBA4TpB1NxVqdRsbEgJvjWUH6Y' โ 1 โ '7RjpXpBXHbkmXSyNnRDB3riscRS4GPGAyR9gWr2SvEsZ' โ โ bidder1 โ 'V7GoneZRCwqZCRNPo7q7saqXo5WgaZD5aBcgzUSQuP1' โ 500 โ 'CiagdjQ6hyt7iGKBLufdnBr5qPdntEMz2dyxNyFFXkpx' โ 0 โ '' โ โ bidder2 โ 'HBSLiE4KGxjgUz4ddB7cKKSeNGig8oNnYeCVEAs5VHq7' โ 500 โ 'DKYdBKm9jq8D3ogw9L89zRT1XXK4JDLp9zQhrNaQiCDG' โ 0 โ '' โ โโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
The account relationship is as follows flowchart LR ExhibitorWallet[Exhibitor Account] ExhibitorNFTAccount[Exhibitor NFT Token Account <br/> amount 1] ExhibitorFTAccount[Exhibitor FT Token Account <br/> amount 500] Bidder1Wallet[Bidder1 Account] Bidder1FTAccount[Bidder1 FT Token Account <br/> amount 500] Bidder2Wallet[Bidder2 Account] Bidder2FTAccount[Bidder2 FT Token Account <br/> amount 500] TokenMintNFT[NFT Token Mint] TokenMintFT[FT Token Mint] PDA[PDA] ExhibitorWallet -- owns -->ExhibitorNFTAccount ExhibitorWallet -- owns -->ExhibitorFTAccount Bidder1Wallet -- owns -->Bidder1FTAccount Bidder2Wallet -- owns -->Bidder2FTAccount ExhibitorNFTAccount -- belongs to -->TokenMintNFT ExhibitorFTAccount -- belongs to -->TokenMintFT Bidder1FTAccount -- belongs to -->TokenMintFT Bidder2FTAccount -- belongs to -->TokenMintFT
Exhibit
Start auction with the duration 3600 seconds and the initial price of NFT is 200npm run exhibitor 200 3600
Auction data (Held by Escrow Account) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ value โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ isInitialized โ 1 โ โ exhibitorPubkey โ '56soKhmhDDx9A4BUqVZmr7ENqBxroFZmtrNTzw47S5Dr' โ โ exhibitingNftTempPubkey โ '2whKYwM683zVirVitGW6UYugxdqbipMouMiFg3Ye8Vgb' โ โ exhibitorFtReceivingPubkey โ '82eyhAL5iWqFaF2SEvWBA4TpB1NxVqdRsbEgJvjWUH6Y' โ โ price โ 200 โ โ endAt โ '2022-06-18T01:28:40.000Z' โ โ highestBidderPubkey โ '11111111111111111111111111111111' โ โ highestBidderFtTempPubkey โ '11111111111111111111111111111111' โ โ highestBidderFtReturningPubkey โ '11111111111111111111111111111111' โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Token Amount โโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ exhibitor โ Exhibitor Token Account โ escrow โ Escrow Token Account โ โโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ NFT โ 0 โ '7RjpXpBXHbkmXSyNnRDB3riscRS4GPGAyR9gWr2SvEsZ' โ 1 โ '2whKYwM683zVirVitGW6UYugxdqbipMouMiFg3Ye8Vgb' โ โ FT โ 500 โ '82eyhAL5iWqFaF2SEvWBA4TpB1NxVqdRsbEgJvjWUH6Y' โ 0 โ '-' โ โโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- The exhibitor's NFT has moved to the deposit account that runs the auction.
- Layout of auction data
- The account relationship is as follows.
flowchart LR ExhibitorWallet[Exhibitor Account] ExhibitorNFTAccount[Exhibitor NFT Token Account <br/> amount 0] ExhibitorFTAccount[Exhibitor FT Token Account<br/> amount 500] Bidder1Wallet[Bidder1 Account] Bidder1FTAccount[Bidder1 FT Token Account <br/> amount 500] Bidder2Wallet[Bidder2 Account] Bidder2FTAccount[Bidder2 FT Token Account <br/> amount 500] TokenMintNFT[NFT Token Mint] TokenMintFT[FT Token Mint] PDA[PDA] Escrow[Escrow Account <br/> holding auction data] TempNFTAccount[Temp NFT Token Account <br/> amount 1] ExhibitorWallet -- owns -->ExhibitorNFTAccount ExhibitorWallet -- owns -->ExhibitorFTAccount Bidder1Wallet -- owns -->Bidder1FTAccount Bidder2Wallet -- owns -->Bidder2FTAccount PDA -- owns --> TempNFTAccount ExhibitorNFTAccount -- belongs to -->TokenMintNFT ExhibitorFTAccount -- belongs to -->TokenMintFT Bidder1FTAccount -- belongs to -->TokenMintFT Bidder2FTAccount -- belongs to -->TokenMintFT TempNFTAccount -- belongs to -->TokenMintNFT
Bid
Bidder1 bids for 201 FT on the listed NFTnpm run bidder1 201
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ value โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ isInitialized โ 1 โ โ exhibitorPubkey โ '56soKhmhDDx9A4BUqVZmr7ENqBxroFZmtrNTzw47S5Dr' โ โ exhibitingNftTempPubkey โ '2whKYwM683zVirVitGW6UYugxdqbipMouMiFg3Ye8Vgb' โ โ exhibitorFtReceivingPubkey โ '82eyhAL5iWqFaF2SEvWBA4TpB1NxVqdRsbEgJvjWUH6Y' โ โ price โ 201 โ โ endAt โ '2022-06-18T01:28:40.000Z' โ โ highestBidderPubkey โ 'V7GoneZRCwqZCRNPo7q7saqXo5WgaZD5aBcgzUSQuP1' โ โ highestBidderFtTempPubkey โ '6NQMmsbFEATnzUMue86BqywPd6UCpa5hbNhkyd4gJyqf' โ โ highestBidderFtReturningPubkey โ 'CiagdjQ6hyt7iGKBLufdnBr5qPdntEMz2dyxNyFFXkpx' โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ own โ Bidder Token Account โ escrow โ Temp Token Account โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ Bidder's FT โ 299 โ 'CiagdjQ6hyt7iGKBLufdnBr5qPdntEMz2dyxNyFFXkpx' โ 201 โ '6NQMmsbFEATnzUMue86BqywPd6UCpa5hbNhkyd4gJyqf' โ โ Previous Highest Bidder's FT โ NaN โ '11111111111111111111111111111111' โ NaN โ '11111111111111111111111111111111' โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- The bid amount 201 FT specified by Bidder2 has been moved to the temporary token account.
- The account relationship is as follows.
flowchart LR ExhibitorWallet[Exhibitor Account] ExhibitorNFTAccount[Exhibitor NFT Token Account <br/> amount 0] ExhibitorFTAccount[Exhibitor FT Token Account <br/> amount 500] Bidder1Wallet[Bidder1 Account] Bidder1FTAccount[Bidder1 FT Token Account <br/> amount 299] Bidder1TempFTAccount[Temp Bidder1 FT Token Account <br/> amount 201] Bidder2Wallet[Bidder2 Account] Bidder2FTAccount[Bidder2 FT Token Account <br/> amount 500] TokenMintNFT[NFT Token Mint] TokenMintFT[FT Token Mint] PDA[PDA] Escrow[Escrow Account <br/> holding auction data] TempNFTAccount[Temp NFT Token Account <br/> amount 1] ExhibitorWallet -- owns -->ExhibitorNFTAccount ExhibitorWallet -- owns -->ExhibitorFTAccount Bidder1Wallet -- owns -->Bidder1FTAccount Bidder2Wallet -- owns -->Bidder2FTAccount PDA -- owns --> TempNFTAccount PDA -- owns --> Bidder1TempFTAccount ExhibitorNFTAccount -- belongs to -->TokenMintNFT ExhibitorFTAccount -- belongs to -->TokenMintFT Bidder1FTAccount -- belongs to -->TokenMintFT Bidder2FTAccount -- belongs to -->TokenMintFT TempNFTAccount -- belongs to -->TokenMintNFT Bidder1TempFTAccount -- belongs to -->TokenMintFT
Another one bid
Bidder2 bids for 201 FT on the listed NFT. If it is 201 FT or less, an error will occur.npm run bidder2 202
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ value โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ isInitialized โ 1 โ โ exhibitorPubkey โ '56soKhmhDDx9A4BUqVZmr7ENqBxroFZmtrNTzw47S5Dr' โ โ exhibitingNftTempPubkey โ '2whKYwM683zVirVitGW6UYugxdqbipMouMiFg3Ye8Vgb' โ โ exhibitorFtReceivingPubkey โ '82eyhAL5iWqFaF2SEvWBA4TpB1NxVqdRsbEgJvjWUH6Y' โ โ price โ 202 โ โ endAt โ '2022-06-18T01:28:40.000Z' โ โ highestBidderPubkey โ 'HBSLiE4KGxjgUz4ddB7cKKSeNGig8oNnYeCVEAs5VHq7' โ โ highestBidderFtTempPubkey โ '7ywDWiZhU8GHPXpU6Wihqzvk8QFB2cMeAvqgzNBzYSjv' โ โ highestBidderFtReturningPubkey โ 'DKYdBKm9jq8D3ogw9L89zRT1XXK4JDLp9zQhrNaQiCDG' โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ own โ Bidder Token Account โ escrow โ Temp Token Account โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ Bidder's FT โ 298 โ 'DKYdBKm9jq8D3ogw9L89zRT1XXK4JDLp9zQhrNaQiCDG' โ 202 โ '7ywDWiZhU8GHPXpU6Wihqzvk8QFB2cMeAvqgzNBzYSjv' โ โ Previous Highest Bidder's FT โ 500 โ 'CiagdjQ6hyt7iGKBLufdnBr5qPdntEMz2dyxNyFFXkpx' โ NaN โ '6NQMmsbFEATnzUMue86BqywPd6UCpa5hbNhkyd4gJyqf' โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- The bid amount 202 FT specified by Bidder2 has been moved to the temporary token account.
- The FT deposited by Bidder1 has been returned to Bidder1 and the temporary token account is closed.
- The account relationship is as follows.
flowchart LR ExhibitorWallet[Exhibitor Account] ExhibitorNFTAccount[Exhibitor NFT Token Account ] ExhibitorFTAccount[Exhibitor FT Token Account ] Bidder1Wallet[Bidder1 Account] Bidder1FTAccount[Bidder1 FT Token Account <br/> amount 500] Bidder2Wallet[Bidder2 Account] Bidder2FTAccount[Bidder2 FT Token Account <br/> amount 298] Bidder2TempFTAccount[Temp Bidder2 FT Token Account <br/> amount 202] TokenMintNFT[NFT Token Mint] TokenMintFT[FT Token Mint] PDA[PDA] Escrow[Escrow Account <br/> holding auction data] TempNFTAccount[Temp NFT Token Account <br/> amount 1] ExhibitorWallet -- owns -->ExhibitorNFTAccount ExhibitorWallet -- owns -->ExhibitorFTAccount Bidder1Wallet -- owns -->Bidder1FTAccount Bidder2Wallet -- owns -->Bidder2FTAccount PDA -- owns --> TempNFTAccount PDA -- owns --> Bidder2TempFTAccount ExhibitorNFTAccount -- belongs to -->TokenMintNFT ExhibitorFTAccount -- belongs to -->TokenMintFT Bidder1FTAccount -- belongs to -->TokenMintFT Bidder2FTAccount -- belongs to -->TokenMintFT TempNFTAccount -- belongs to -->TokenMintNFT Bidder2TempFTAccount -- belongs to -->TokenMintFT
Receive NFT when the auction duration expires.
After 3600 seconds, the winning bidder will be confirmed, FT will move to the exhibitor, and NFT will move to the winning bidder.npm run receive2
โโโโโโโโโโโฌโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ (index) โ exhibitor โ Exhibitor Token Account โ bidder โ Bidder Token Account โ โโโโโโโโโโโผโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ NFT โ 0 โ '7RjpXpBXHbkmXSyNnRDB3riscRS4GPGAyR9gWr2SvEsZ' โ 1 โ 'Hc8ivcAFQysW9HNpjQLwzbqjqYA3kG8idLK1i9V5oZ9H' โ โ FT โ 702 โ '82eyhAL5iWqFaF2SEvWBA4TpB1NxVqdRsbEgJvjWUH6Y' โ 298 โ 'DKYdBKm9jq8D3ogw9L89zRT1XXK4JDLp9zQhrNaQiCDG' โ โโโโโโโโโโโดโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- The 202 NAO specified by Bidder2 has been moved to the exhibitor.
- The exhibitor's NFT has moved to Bidder2.
- The account relationship is as follows.
flowchart LR ExhibitorWallet[Exhibitor Account] ExhibitorNFTAccount[Exhibitor NFT Token Account <br/> amount 0] ExhibitorFTAccount[Exhibitor FT Token Account <br/> amount 702] Bidder1Wallet[Bidder1 Account] Bidder1FTAccount[Bidder1 FT Token Account <br/> amount 500] Bidder2Wallet[Bidder2 Account] Bidder2FTAccount[Bidder2 FT Token Account <br/> amount 298] Bidder2NFTAccount[Bidder2 NFT Token Account <br/> amount 1] TokenMintNFT[NFT Token Mint] TokenMintFT[FT Token Mint] PDA[PDA] ExhibitorWallet -- owns -->ExhibitorNFTAccount ExhibitorWallet -- owns -->ExhibitorFTAccount Bidder1Wallet -- owns -->Bidder1FTAccount Bidder2Wallet -- owns -->Bidder2FTAccount Bidder2Wallet -- owns -->Bidder2NFTAccount ExhibitorNFTAccount -- belongs to -->TokenMintNFT ExhibitorFTAccount -- belongs to -->TokenMintFT Bidder1FTAccount -- belongs to -->TokenMintFT Bidder2FTAccount -- belongs to -->TokenMintFT Bidder2NFTAccount -- belongs to -->TokenMintNFT