2

How to set royalty while minting a NFT. If I set creators in metadata how can I transfer royalties when someone buys this NFT?

This is my Minting code:

pub fn mint_nft(
    ctx: Context<MintNFT>,
    creator_key: Pubkey,
    name: String,
    symbol: String,
    uri: String,
    ) -> Result<()> {
    msg!("Nft token minting:");
    let cpi_program = ctx.accounts.token_program.to_account_info();
    let cpi_accounts = MintTo {
        mint: ctx.accounts.mint.to_account_info(),
        to: ctx.accounts.token_account.to_account_info(),
        authority: ctx.accounts.payer.to_account_info(),
    };
    let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
    let result = mint_to(cpi_ctx, 1);
    if let Err(_) = result {
        return Err(error!(MintError::MintFailed));
    }
    msg!("Token minted !!!");

    msg!("Metadata account creating:");
    let accounts = vec![
        ctx.accounts.token_metadata_program.to_account_info(),
        ctx.accounts.metadata.to_account_info(),
        ctx.accounts.mint.to_account_info(),
        ctx.accounts.mint_authority.to_account_info(),
        ctx.accounts.payer.to_account_info(),
        ctx.accounts.token_program.to_account_info(),
        ctx.accounts.system_program.to_account_info(),
        ctx.accounts.rent.to_account_info(),
    ];
    let creators = vec![
        mpl_token_metadata::state::Creator {         
            address: creator_key,
            verified: false,
            share: 100,
        },
        mpl_token_metadata::state::Creator {
            address: ctx.accounts.mint_authority.key(),
            verified: false,
            share: 0,
        },
    ];
    let result = invoke(
        &create_metadata_accounts_v2(
            ctx.accounts.token_metadata_program.key(),
            ctx.accounts.metadata.key(),
            ctx.accounts.mint.key(),
            ctx.accounts.mint_authority.key(),
            ctx.accounts.payer.key(),
            ctx.accounts.payer.key(),
            name,
            symbol,
            uri,
            Some(creators),
            1,
            true,
            false,
            None,
            None,
        ),
        &accounts
    );
    if let Err(_) = result {
        return Err(error!(MintError::MetadataCreateFailed));
    }
    msg!("Metadata account created !!!");
    Ok(())
}




#[derive(Accounts)]
pub struct MintNFT<'info> {
    #[account(mut)]
    pub mint_authority: Signer<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub mint: UncheckedAccount<'info>,

    pub token_program: Program<'info, Token>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub metadata: UncheckedAccount<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub token_account: UncheckedAccount<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub token_metadata_program: UncheckedAccount<'info>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    #[account(mut)]
    pub payer: AccountInfo<'info>,

    pub system_program: Program<'info, System>,

    /// CHECK: This is not dangerous because we don't read or write from this account
    pub rent: AccountInfo<'info>,
}

and this is the buy NFT code:

pub fn fill_order(ctx: Context<FillOrder>) -> Result<()> {
    let order = &mut ctx.accounts.order;
    let buyer = &mut ctx.accounts.buyer;
    let creator = &mut ctx.accounts.creator;

    //
    // Check buyer's balance against order's price.
    //
    if buyer.lamports() < order.price {
        return Err(error!(MarketError::InsufficientMoney));
    }

    //
    // Transfer order's money from buyer into creator.
    //
    anchor_lang::solana_program::program::invoke(
        &anchor_lang::solana_program::system_instruction::transfer(
            &buyer.to_account_info().key(),
            &creator.to_account_info().key(),
            order.price
        ),
        &[
            buyer.to_account_info(),
            creator.to_account_info(),
            ctx.accounts.system_program.to_account_info()
        ]
    )?;

    //
    // Transfer order token account's token into buyer token account.
    //
    let seeds = &[
        b"order",
        ctx.accounts.mint_key.key.as_ref(),
        &[order.bump]
    ];
    let signer = &[&seeds[..]];
    let cpi_program = ctx.accounts.token_program.to_account_info();
    let cpi_accounts = Transfer {
        from: ctx.accounts.order_token_account.to_account_info(),
        to: ctx.accounts.buyer_token_account.to_account_info(),
        authority: ctx.accounts.order.to_account_info()
    };
    let cpi_context = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer);
    let result = transfer(cpi_context, 1);
    if let Err(_) = result {
        return Err(error!(MarketError::TokenTransferFailed3));
    }

    //
    // Close order token account.
    //
    let cpi_program = ctx.accounts.token_program.to_account_info();
    let cpi_accounts = CloseAccount {
        account: ctx.accounts.order_token_account.to_account_info(),
        destination: ctx.accounts.creator.to_account_info(),
        authority: ctx.accounts.order.to_account_info(),
    };
    let cpi_context = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer);
    let result = close_account(cpi_context);
    if let Err(_) = result {
        return Err(error!(MarketError::TokenCloseFailed));
    }

    Ok(())
}



pub struct FillOrder<'info> {
    #[account(
        mut,
        seeds = [
            b"order",
            mint_key.key.as_ref(),
        ],
        bump,
        has_one = creator,
        close = creator
    )]
    pub order: Account<'info, Order>,

    #[account(
        mut,
        associated_token::mint = order.mint_key,
        associated_token::authority = order,
    )]
    pub order_token_account: Account<'info, TokenAccount>,

    /// CHECK: This account's address is only used.
    pub mint_key: AccountInfo<'info>,

    /// CHECK: This account's address is only used.
    #[account(mut)]
    pub creator: AccountInfo<'info>,

    #[account(mut)]
    pub buyer: Signer<'info>,

    #[account(
        mut,
        constraint=buyer_token_account.owner == buyer.key(),
        constraint=buyer_token_account.mint == mint_key.key(),
    )]
    pub buyer_token_account: Account<'info, TokenAccount>,

    pub system_program: Program<'info, System>,
    pub token_program: Program<'info, Token>,
    pub associated_token_program: Program<'info, AssociatedToken>,
}
2
  • This is done by modifying the exchange process at a low level. If you share your repository I would gladly help you Oct 9, 2022 at 13:18
  • Hi, I have updated my code for NFT minting and buying. Kindly take a look and help me execute royalty distribution. Thank you.
    – Lobo1897
    Oct 9, 2022 at 13:39

1 Answer 1

1

It is difficult for me to work without having the repository, I cannot give you a specific answer. So broadly speaking I can recommend you use this method:

fn to_f64(amount: u64) -> f64 {return amount as f64}
    fn percent(amount: f64) -> u64 {((amount / 100.0)* 2.0).round() as u64}  
    let owners_amount = percent(to_f64(AccountInfo::lamports(&account.to_account_info()) - 70254250));
    let owners_dividend: u64 = owners_amount / 8; 
    let winner_reward: u64 = AccountInfo::lamports(&solotery.to_account_info()) - 70254250 - owners_amount; 
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.owner1.try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.owner2.try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.owner3.try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.owner4.try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.owner5.try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.owner6.try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.owner7.try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= owners_dividend;
    **ctx.accounts.creator.to_account_info().try_borrow_mut_lamports()? += owners_dividend;
    **account.to_account_info().try_borrow_mut_lamports()? -= winner_reward;
    **winner.to_account_info().try_borrow_mut_lamports()? += winner_reward;
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.