Skip to content

Commit

Permalink
completed! (#9)
Browse files Browse the repository at this point in the history
Co-authored-by: Rodrigo Pintos <rpintos@spacedev.io>
  • Loading branch information
RoPB and RoSpaceDev authored Sep 11, 2024
1 parent 0cf0c8b commit a3726ad
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 99 deletions.
139 changes: 75 additions & 64 deletions programs/solana-hub/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,67 +122,82 @@ pub mod solana_hub {
// claim process, ensuring that the creator receives their payment regardless of
// whether the NFT is claimed.
pub fn claim(ctx: Context<Claim>, name: String, nft_id: u16) -> Result<()> {
//TODO: claim only if timestamp_to_close

require!((nft_id as usize) < ctx.accounts.auction.nft_list.len(), ErrorCode::InvalidNftId);

let uri = ctx
.accounts
.auction
.nft_list
.get(nft_id as usize - 1)
.unwrap()
.uri.clone();

let nft_data: DataV2 = DataV2 {
name: name.clone(),
symbol: String::from("PRB"), //TODO: Change this with metadata.name
uri, //TODO: Change this with metadata.symbol
seller_fee_basis_points: 3,
creators: None, //TODO: [ctx.accounts.auction.creator.key()],
collection: None, //TODO: See how to put all the nfts under the same collection
uses: None,
};

let nft_signer_seeds = &[
"nft".as_bytes(),
name.as_bytes(),
"*".as_bytes(),
&nft_id.to_le_bytes(),
&[ctx.bumps.nft],
];
let nft_signer = [&nft_signer_seeds[..]];
let metadata_ctx = CpiContext::new_with_signer(
ctx.accounts.token_metadata_program.to_account_info(),
CreateMetadataAccountsV3 {
payer: ctx.accounts.claimer.to_account_info(),
update_authority: ctx.accounts.nft.to_account_info(),
mint: ctx.accounts.nft.to_account_info(),
metadata: ctx.accounts.metadata.to_account_info(),
mint_authority: ctx.accounts.nft.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
},
&nft_signer,
);
let get_clock = Clock::get();
if let Ok(clock) = get_clock {

create_metadata_accounts_v3(metadata_ctx, nft_data, false, true, None)?;
let current_timestamp = clock.unix_timestamp;
if current_timestamp<=ctx.accounts.auction.timestamp_to_close{
//TODO change for an error, can not claim until the auction is closed
return Ok(());
}

mint_to(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
MintTo {
authority: ctx.accounts.nft.to_account_info(),
to: ctx.accounts.receiver_account.to_account_info(),
require!((nft_id as usize) < ctx.accounts.auction.nft_list.len(), ErrorCode::InvalidNftId);

let metadata = ctx.accounts.auction.nft_list.get(nft_id as usize-1);

let nft_name = metadata.unwrap().name.clone();
let symbol = metadata.unwrap().symbol.clone();
let uri = metadata.unwrap().uri.clone();

let nft_data: DataV2 = DataV2 {
name: nft_name,
symbol,
uri,
seller_fee_basis_points: 3,
creators: None, //TODO: [ctx.accounts.auction.creator.key()],
collection: None, //TODO: See how to put all the nfts under the same collection
uses: None,
};

let nft_signer_seeds = &[
"nft".as_bytes(),
name.as_bytes(),
"*".as_bytes(),
&nft_id.to_le_bytes(),
&[ctx.bumps.nft],
];
let nft_signer = [&nft_signer_seeds[..]];
let metadata_ctx = CpiContext::new_with_signer(
ctx.accounts.token_metadata_program.to_account_info(),
CreateMetadataAccountsV3 {
payer: ctx.accounts.claimer.to_account_info(),
update_authority: ctx.accounts.nft.to_account_info(),
mint: ctx.accounts.nft.to_account_info(),
metadata: ctx.accounts.metadata.to_account_info(),
mint_authority: ctx.accounts.nft.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
},
&nft_signer,
),
1,
)?;
);

create_metadata_accounts_v3(metadata_ctx, nft_data, false, true, None)?;

mint_to(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
MintTo {
authority: ctx.accounts.nft.to_account_info(),
to: ctx.accounts.receiver_account.to_account_info(),
mint: ctx.accounts.nft.to_account_info(),
},
&nft_signer,
),
1,
)?;
ctx.accounts.nft_auction.bidder=Pubkey::default();
}
else{
//TODO: return error
}


Ok(())
}

//TODO: The creator who register the collection needs a method
//to claim all the funds from the nft_auctions pdas
}

#[derive(Accounts)]
Expand Down Expand Up @@ -237,19 +252,15 @@ pub struct Claim<'info> {
bump
)]
pub auction: Account<'info, Auction>,
// #[account(
// //TODO: Remove init_if_needed,payer,space (THE ACCOUNT SHOULD BE ALREADY INITIALIZED)
// init_if_needed,
// seeds = ["nft_auction".as_bytes(),name.as_bytes(),"*".as_bytes(),&nft_id.to_le_bytes()],
// bump,
// payer=claimer,
// space = NftAuction::MAX_SIZE,
// //TODO: Uncomment this
// //constraint = nft_auction.bidder.key() == claimer.key()
// )]
// pub nft_auction: Account<'info, NftAuction>,
#[account(
init_if_needed,
mut,
seeds = ["nft_auction".as_bytes(),name.as_bytes(),"*".as_bytes(),&nft_id.to_le_bytes()],
bump,
constraint = nft_auction.bidder.key() == claimer.key()
)]
pub nft_auction: Account<'info, NftAuction>,
#[account(
init,
constraint = !name.contains("*"),//To avoid collisions name: name, nft_id: 11 and name: name1 nft_id:1
seeds = ["nft".as_bytes(),name.as_bytes(),"*".as_bytes(),&nft_id.to_le_bytes()],
bump,
Expand Down
80 changes: 45 additions & 35 deletions tests/solana-hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const account2WithLamports = anchor.web3.Keypair.fromSecretKey(

const random = new anchor.web3.Keypair();

const COLLECTION_NAME = "La Piedra Filosofal 38";
const COLLECTION_NAME = "La Piedra Filosofal 39";
const NFT_LIST = [
{
name: "Harry Potter",
Expand Down Expand Up @@ -109,17 +109,27 @@ const predictAuctionNft = (
return auctionNft;
};

//PRECONDITION; ADD LAMPORTS TO H9KwD9eQakjKuqanLpqxfEgBHPLniGsZTjpKyA9mXKgz AND 2ijVMniqgVgwyRebdPduJaVSAyqeR5Q9ftLJyAYYB7Qc
function wait(seconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}

//PRECONDITION;
//ADD LAMPORTS TO H9KwD9eQakjKuqanLpqxfEgBHPLniGsZTjpKyA9mXKgz AND 2ijVMniqgVgwyRebdPduJaVSAyqeR5Q9ftLJyAYYB7Qc
//CHANGE COLLECTION_NAME
describe("solana-hub", () => {
// Configure the client to use the local cluster.
anchor.setProvider(anchor.AnchorProvider.env());

const program = anchor.workspace.SolanaHub as Program<SolanaHub>;

const auctionTime = 0.2 * 60;

const nftToBid = 1;

it("Register collection!", async () => {
// Add your test here.
const txInstruction = await program.methods
.registerCollection(COLLECTION_NAME, new anchor.BN(5 * 60), NFT_LIST)
.registerCollection(COLLECTION_NAME, new anchor.BN(auctionTime), NFT_LIST)
.accounts({ creator: accountWithLamports.publicKey })
.instruction();
const transaction = new anchor.web3.Transaction().add(txInstruction);
Expand All @@ -146,8 +156,7 @@ describe("solana-hub", () => {

it("Bid!", async () => {
// Add your test here.
const nftId = 3;
const auctionNft = predictAuctionNft(program, COLLECTION_NAME, nftId);
const auctionNft = predictAuctionNft(program, COLLECTION_NAME, nftToBid);

const bid = async (amountToBid: anchor.BN, bidder: anchor.web3.Keypair) => {
try {
Expand All @@ -167,7 +176,7 @@ describe("solana-hub", () => {
} catch (e) {}

const txInstruction = await program.methods
.bid(COLLECTION_NAME, nftId, amountToBid)
.bid(COLLECTION_NAME, nftToBid, amountToBid)
.accounts({
bidder: bidder.publicKey,
previousBidder: prevBidder,
Expand Down Expand Up @@ -203,33 +212,34 @@ describe("solana-hub", () => {
await bid(new anchor.BN(0.07 * 10 ** 9), account2WithLamports);
});

// it("Claim nft!", async () => {
// // Add your test here.
// const nftId = 1;
// const txInstruction = await program.methods
// .claim(COLLECTION_NAME, nftId)
// .accounts({
// metadata: predictMetadataAccount(program, COLLECTION_NAME, nftId),
// claimer: accountWithLamports.publicKey,
// })
// .instruction();
// const transaction = new anchor.web3.Transaction().add(txInstruction);
// transaction.recentBlockhash = (
// await program.provider.connection.getLatestBlockhash("finalized")
// ).blockhash;
// transaction.sign(accountWithLamports);
// const txHash = await program.provider.connection.sendRawTransaction(
// transaction.serialize(),
// { preflightCommitment: "confirmed" }
// );
// const confirmation = await program.provider.connection.confirmTransaction(
// txHash,
// "confirmed"
// );
// if (!confirmation.value.err) {
// console.log("Your transaction signature", txHash);
// const nft = predictNft(program, COLLECTION_NAME, nftId);
// console.log(nft.toBase58());
// }
// });
it("Claim nft!", async () => {
// Add your test here.
await wait(auctionTime + 5);

const txInstruction = await program.methods
.claim(COLLECTION_NAME, nftToBid)
.accounts({
metadata: predictMetadataAccount(program, COLLECTION_NAME, nftToBid),
claimer: account2WithLamports.publicKey,
})
.instruction();
const transaction = new anchor.web3.Transaction().add(txInstruction);
transaction.recentBlockhash = (
await program.provider.connection.getLatestBlockhash("finalized")
).blockhash;
transaction.sign(account2WithLamports);
const txHash = await program.provider.connection.sendRawTransaction(
transaction.serialize(),
{ preflightCommitment: "confirmed" }
);
const confirmation = await program.provider.connection.confirmTransaction(
txHash,
"confirmed"
);
if (!confirmation.value.err) {
console.log("Your transaction signature", txHash);
const nft = predictNft(program, COLLECTION_NAME, nftToBid);
console.log(nft.toBase58());
}
});
});

0 comments on commit a3726ad

Please sign in to comment.