Reputation: 77
I am trying to develop a program on the Solana network, I have had experiences for EVM before but Solana looks very different.
If we give an example on EVM, it is enough to authorize spending with "approve" to the contract address for transfer from wallet A to B.
However, this seems to be different in the Solana program. Because I still haven't succeeded yet.
What I want is that when wallet B interacts with the program, the program will transfer SPL tokens from wallet A to wallet B as much as the SOL amount paid.
Of course, for this, the token account of wallet A must first be authorized to spend with "approve". I did this for the program id. Then I sent the program id as account info and tested the process and it did not work.
Then I saw the so called PDA and I am trying to create a PDA but you can see the codes below and you can look at it on Solscan. An account is being created but it still appears in the curve. So there is a false value.
What should I do in this case? I think I haven't even created a real PDA yet. But I don't understand.
https://solscan.io/account/HgtVDBozNRq4hbAhhsGBa4SJ7ttLoSWK7XLsp9w7MQ1x?cluster=devnet
use anchor_lang::prelude::*;
use anchor_spl::token::{self, Token, TokenAccount, Transfer as SplTransfer};
declare_id!("73r6t8WnAeQCdksfFr7aJWfM2yZ1HeK6ZfnNXDeWhAGD");
#[program]
mod pda_test {
use super::*;
pub fn create_pda(ctx: Context<PdaTest>, _pda_key: String) -> Result<()> {
let pda_account = &mut ctx.accounts.pda_account;
pda_account.owner = *ctx.accounts.signer.key;
pda_account.sent = false;
Ok(())
}
pub fn transfer(ctx: Context<TransferTest>, _amount: u64) -> Result<()> {
let token_program = &ctx.accounts.token_program;
let pda_account = &mut ctx.accounts.pda_account;
let owner_token_account = &ctx.accounts.owner_token_account;
let buyer_token_account = &ctx.accounts.buyer_token_account;
let sol_format = 10u64.pow(9);
let token_format = 10u64.pow(6);
let amount = ((_amount * 500) / sol_format) * token_format;
token::transfer(CpiContext::new(token_program.to_account_info(), SplTransfer {
from: owner_token_account.to_account_info(),
to: buyer_token_account.to_account_info(),
authority: pda_account.to_account_info(),
}), amount)?;
pda_account.sent = true;
Ok(())
}
}
#[derive(Accounts)]
#[instruction(_pda_key: String)]
pub struct PdaTest<'info> {
#[account(
init,
seeds = [_pda_key.as_bytes().as_ref(), signer.key().as_ref()],
bump,
payer = signer,
space = 10240
)]
pda_account: Account<'info, PdaAccount>,
#[account(mut)]
signer: Signer<'info>,
system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct TransferTest<'info> {
#[account(mut)]
buyer: Signer<'info>,
#[account(mut)]
pda_account: Account<'info, PdaAccount>,
#[account(mut)]
owner_token_account: Account<'info, TokenAccount>,
#[account(mut)]
buyer_token_account: Account<'info, TokenAccount>,
token_program: Program<'info, Token>,
system_program: Program<'info, System>,
}
#[account]
pub struct PdaAccount {
pub owner: Pubkey,
pub sent: bool,
}
Upvotes: 0
Views: 856
Reputation: 77
you need use PDAs like that. There is showing false but stil works.
use anchor_lang::prelude::*;
use anchor_spl::token::{self, Token, TokenAccount, Transfer as SplTransfer};
declare_id!("73r6t8WnAeQCdksfFr7aJWfM2yZ1HeK6ZfnNXDeWhAGD");
#[program]
mod pda_test {
use super::*;
pub fn create_pda(ctx: Context<PdaTest>, _pda_key: String) -> Result<()> {
let pda_account = &mut ctx.accounts.pda_account;
pda_account.owner = *ctx.accounts.owner.key;
pda_account.sent = false;
Ok(())
}
pub fn transfer(ctx: Context<TransferTest>, _pda_key: String, _amount: u64) -> Result<()> {
let _buyer = &ctx.accounts.buyer;
let owner = &ctx.accounts.owner;
let token_program = &ctx.accounts.token_program;
let pda_account = &mut ctx.accounts.pda_account;
let owner_token_account = &ctx.accounts.owner_token_account;
let buyer_token_account = &ctx.accounts.buyer_token_account;
let bump = &[ctx.bumps.pda_account];
let seeds: &[&[u8]] = &[
_pda_key.as_bytes().as_ref(), owner.key.as_ref(),
bump
];
let signer_seeds = &[&seeds[..]];
let sol_format = 10u64.pow(9);
let token_format = 10u64.pow(8);
let amount = ((_amount * 500) / sol_format) * token_format;
token::transfer(CpiContext::new_with_signer(
token_program.to_account_info(),
SplTransfer {
from: owner_token_account.to_account_info(),
to: buyer_token_account.to_account_info(),
authority: pda_account.to_account_info(),
},
signer_seeds,
), amount)?;
Ok(())
}
}
#[derive(Accounts)]
#[instruction(_pda_key: String)]
pub struct PdaTest<'info> {
#[account(mut)]
pub owner: Signer<'info>,
#[account(
init,
payer = owner,
space = 10240,
seeds = [
_pda_key.as_bytes().as_ref(),
owner.key().as_ref()
],
bump
)]
pda_account: Account<'info, PdaAccount>,
system_program: Program<'info, System>,
}
#[derive(Accounts)]
#[instruction(_pda_key: String)]
pub struct TransferTest<'info> {
#[account(mut)]
buyer: Signer<'info>,
#[account(mut)]
owner: AccountInfo<'info>,
#[account(
mut,
seeds = [
_pda_key.as_bytes().as_ref(),
owner.key().as_ref()
],
bump
)]
pda_account: Account<'info, PdaAccount>,
#[account(mut)]
owner_token_account: Account<'info, TokenAccount>,
#[account(mut)]
buyer_token_account: Account<'info, TokenAccount>,
token_program: Program<'info, Token>,
system_program: Program<'info, System>,
}
#[account]
#[derive(Default)]
pub struct PdaAccount {
pub owner: Pubkey,
pub sent: bool
}
Upvotes: 0