Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFT Solana #8

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# NFT_Solana
Створити смартконтракт NFT мовою Rust з логотипом НаУКМА завантаженим в IPFS і задеплоїти його в devnet Solana
Зробити пул реквест коду та вказати Ваше прізвище та хеш транзакції в readme.md

Дмитро Парнак

NFT: https://explorer.solana.com/address/3Qpsf2HpSrG2wKaRJUkj3wvih4hnxiQEk16uBC9xoVJV?cluster=devnet

TRANSACTION: https://explorer.solana.com/tx/39bjaKQ3Zk3GNbGqBZDGaA27HqrbrpbJ7e26E7SWiF2yrsupT2GoGCdUdVydJBd2HrwLPEcxf8FR41hpkytqtqqD?cluster=devnet
72 changes: 72 additions & 0 deletions client/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Client
console.log("Wallet Address:", pg.wallet.publicKey.toString());
const accountBalance = await pg.connection.getBalance(pg.wallet.publicKey);
console.log(`Account Balance: ${accountBalance / web3.LAMPORTS_PER_SOL} SOL`);

const METADATA_PROGRAM_KEY = new anchor.web3.PublicKey(
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
);

const assetMintKeypair: anchor.web3.PublicKey = new anchor.web3.PublicKey(
"3Qpsf2HpSrG2wKaRJUkj3wvih4hnxiQEk16uBC9xoVJV"
);
const assetTokenAddress = await anchor.utils.token.associatedAddress({
mint: assetMintKeypair,
owner: pg.wallet.publicKey,
});
console.log(`Asset Token: ${assetMintKeypair}`);

const assetMetadataAddr = (
await anchor.web3.PublicKey.findProgramAddress(
[
Buffer.from("metadata"),
METADATA_PROGRAM_KEY.toBuffer(),
assetMintKeypair.toBuffer(),
],
METADATA_PROGRAM_KEY
)
)[0];
console.log("Asset Metadata Configured");

const editionMetadataAddr = anchor.web3.PublicKey.findProgramAddressSync(
[
Buffer.from("metadata"),
METADATA_PROGRAM_KEY.toBuffer(),
assetMintKeypair.toBuffer(),
Buffer.from("edition"),
],
METADATA_PROGRAM_KEY
)[0];
console.log("Edition Metadata Configured");

try {
await pg.program.methods
.mintNFT(
new BN(0),
"DMYTRO PARNAK",
"KMA-TOKEN",
"https://amaranth-defiant-damselfly-735.mypinata.cloud/ipfs/QmbnnSkJZmvDR91vme6co3twQtZsNRcJLX3aQS1mYGQ74f",
0.01,
new BN(1)
)
.accounts({
assetAccount: assetTokenAddress,
mintAuthority: new anchor.web3.PublicKey(
"3Qpsf2HpSrG2wKaRJUkj3wvih4hnxiQEk16uBC9xoVJV"
),
systemProgram: pg.wallet.keypair,
tokenHandlingProgram: new anchor.web3.PublicKey(
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
),
tokenAccountsProgram: new anchor.web3.PublicKey(
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
),
metadataProgram: METADATA_PROGRAM_KEY,
masterEdition: editionMetadataAddr,
nftData: assetMetadataAddr,
})
.signers([pg.wallet.keypair])
.rpc();
} catch (error) {
console.log(error);
}
155 changes: 155 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use anchor_lang::prelude::*;
use anchor_spl::associated_token::AssociatedToken;
use anchor_spl::metadata::{
create_master_edition_v3, create_metadata_accounts_v3, CreateMasterEditionV3,
CreateMetadataAccountsV3, Metadata,
};
use anchor_spl::token::{mint_to, Mint, MintTo, Token, TokenAccount};
use mpl_token_metadata::types::{Collection, Creator, DataV2};

declare_id!("7GW6YAjRpGkQsNcftGPZoQiwgCK89YqgsWeQxPGGujqW");

#[program]
pub mod nft_program {
use super::*;
pub fn create_single_nft(
ctx: Context<CreateNFT>,
id: u64,
name: String,
symbol: String,
uri: String,
price: f32,
cant: u64,
) -> Result<()> {
msg!("Creating seeds");
let id_bytes = id.to_le_bytes();
let seeds = &["mint".as_bytes(),id_bytes.as_ref(),&[ctx.bumps.mint],
];

msg!("Run mint_to");

mint_to(
CpiContext::new_with_signer(
ctx.accounts.token_program.to_account_info(),
MintTo {
authority: ctx.accounts.authority.to_account_info(),
to: ctx.accounts.token_account.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
},
&[&seeds[..]],
),
1,
)?;

msg!("Run create metadata accounts v3");

create_metadata_accounts_v3(
CpiContext::new_with_signer(
ctx.accounts.metadata_program.to_account_info(),
CreateMetadataAccountsV3 {
payer: ctx.accounts.payer.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
metadata: ctx.accounts.nft_metadata.to_account_info(),
mint_authority: ctx.accounts.authority.to_account_info(),
update_authority: ctx.accounts.authority.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
},
&[&seeds[..]],
),
DataV2 {
name,
symbol,
uri,
seller_fee_basis_points: 0,
creators: None,
collection: None,
uses: None,
},
true,
true,
None,
)?;

msg!("Run create master edition v3");

create_master_edition_v3(
CpiContext::new_with_signer(
ctx.accounts.metadata_program.to_account_info(),
CreateMasterEditionV3 {
edition: ctx.accounts.master_edition_account.to_account_info(),
payer: ctx.accounts.payer.to_account_info(),
mint: ctx.accounts.mint.to_account_info(),
metadata: ctx.accounts.nft_metadata.to_account_info(),
mint_authority: ctx.accounts.authority.to_account_info(),
update_authority: ctx.accounts.authority.to_account_info(),
system_program: ctx.accounts.system_program.to_account_info(),
token_program: ctx.accounts.token_program.to_account_info(),
rent: ctx.accounts.rent.to_account_info(),
},
&[&seeds[..]],
),
Some(1),
)?;

msg!("Minted NFT successfully");

Ok(())
}
}

#[derive(Accounts)]
#[instruction(id: u64)]
pub struct CreateNFT<'info> {
#[account(mut)]
pub authority: Signer<'info>,
#[account(mut)]
pub payer: Signer<'info>,
#[account(
init,
payer = payer,
mint::decimals = 0,
mint::authority = authority,
mint::freeze_authority = authority,
seeds = ["mint".as_bytes(), id.to_le_bytes().as_ref()],
bump,
)]
pub mint: Account<'info, Mint>,
#[account(
init_if_needed,
payer = payer,
associated_token::mint = mint,
associated_token::authority = payer,
)]
pub token_account: Account<'info, TokenAccount>,
pub associated_token_program: Program<'info, AssociatedToken>,
pub rent: Sysvar<'info, Rent>,
pub system_program: Program<'info, System>,
pub token_program: Program<'info, Token>,
pub metadata_program: Program<'info, Metadata>,
#[account(
mut,
seeds = [
b"metadata".as_ref(),
metadata_program.key().as_ref(),
mint.key().as_ref(),
b"edition".as_ref(),
],
bump,
seeds::program = metadata_program.key()
)]

pub master_edition_account: UncheckedAccount<'info>,
#[account(
mut,
seeds = [
b"metadata".as_ref(),
metadata_program.key().as_ref(),
mint.key().as_ref(),
],
bump,
seeds::program = metadata_program.key()
)]

pub nft_metadata: UncheckedAccount<'info>,
}