Sol.College

Full lesson

solanacontract

solana contract

What it does

From the project README:

Since this program is extended from the original Escrow Program, I assumed you have gone through the original blog post at least once.
Original
T-emporal/solanacontract
SuperStack fork
Blockchains/solanacontract @ 65c4c72
Stars
0
Last push (original)
2024-10-07
Languages
Rust, Makefile, TypeScript, LLVM, DTrace, C
Detected stack
Anchor
Categories
Other
Licence
MIT

Architecture

11 source files. By extension: .rs ×9, .ts ×2.

Top-level directorySource files
programs9
migrations1
tests1

On-chain programs: programs/anchor-escrow

Dapp: deploying

This fork is queued for its own live dapp on Sol.College, with a Devnet/Mainnet switch. It appears here, at /dapps/solanacontract/, once it is deployed and checked on devnet. Until then, run it locally with the commands below.

Key code, explained

Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.

T-emporal/solanacontract · programs/anchor-escrow/src/contexts/exchange.rs L25–48 @ 65c4c72 · MIT · original
        associated_token::authority = taker    )]    pub taker_ata_a: Box<Account<'info, TokenAccount>>,    #[account(        mut,        associated_token::mint = mint_b,        associated_token::authority = taker    )]    pub taker_ata_b: Box<Account<'info, TokenAccount>>,    #[account(        init_if_needed,        payer = taker,        associated_token::mint = mint_b,        associated_token::authority = initializer    )]    pub initializer_ata_b: Box<Account<'info, TokenAccount>>,    #[account(        mut,        has_one = mint_b,        constraint = taker_ata_b.amount >= amount_to_exchange,        close = initializer,        seeds=[b"state", escrow.seed.to_le_bytes().as_ref()],        bump = escrow.bump,    )]
  1. Line 35 init_if_needed,: Creates the account only if it doesn't exist. Watch for re-initialisation bugs.
  2. Line 43 has_one = mint_b,: Checks that a stored pubkey field matches the passed account.
  3. Line 45 close = initializer,: Closes the account at the end of the instruction and refunds its lamports.
  4. Line 46 seeds=[b"state", escrow.seed.to_le_bytes().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  5. Line 47 bump = escrow.bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
T-emporal/solanacontract · programs/anchor-escrow/src/lib.rs L133–156 @ 65c4c72 · MIT · original
    #[account(mut)]    pub pt_mint: Account<'info, Mint>,    #[account(mut)]    pub yt_mint: Account<'info, Mint>,    #[account(mut)]    pub pt_token_account: Account<'info, TokenAccount>,    #[account(mut)]    pub yt_token_account: Account<'info, TokenAccount>,    pub authority: Signer<'info>,    pub token_program: Program<'info, Token>,} #[derive(Accounts)]pub struct CreateVault<'info> {    #[account(mut)]    pub user: Signer<'info>,    #[account(        init,        payer = user,        space = Vault::LEN,        seeds = [b"vault", user.key().as_ref()],        bump    )]    pub vault: Account<'info, Vault>,
  1. Line 141 pub authority: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 150 init,: Creates and pays for a new account. Space and payer must be specified.
  3. Line 153 seeds = [b"vault", user.key().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 154 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
T-emporal/solanacontract · programs/anchor-escrow/src/contexts/cancel.rs L13–36 @ 65c4c72 · MIT · original
    pub initializer: Signer<'info>,    pub mint_a: Account<'info, Mint>,    #[account(        mut,        associated_token::mint = mint_a,        associated_token::authority = initializer    )]    pub initializer_ata_a: Account<'info, TokenAccount>,    #[account(        mut,        has_one = initializer,        has_one = mint_a,        seeds=[b"state", escrow.seed.to_le_bytes().as_ref()],        bump = escrow.bump,    )]    pub escrow: Account<'info, Escrow>,    #[account(        mut,        associated_token::mint = mint_a,        associated_token::authority = escrow    )]    pub vault: Account<'info, TokenAccount>,    pub associated_token_program: Program<'info, AssociatedToken>,    pub token_program: Program<'info, Token>,
  1. Line 13 pub initializer: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 23 has_one = initializer,: Checks that a stored pubkey field matches the passed account.
  3. Line 25 seeds=[b"state", escrow.seed.to_le_bytes().as_ref()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 26 bump = escrow.bump,: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
T-emporal/solanacontract · programs/anchor-escrow/src/contexts/initialize.rs L13–36 @ 65c4c72 · MIT · original
    pub initializer: Signer<'info>,    pub mint_a: Account<'info, Mint>,    pub mint_b: Account<'info, Mint>,    #[account(        mut,        constraint = initializer_ata_a.amount >= initializer_amount,        associated_token::mint = mint_a,        associated_token::authority = initializer    )]    pub initializer_ata_a: Account<'info, TokenAccount>,    #[account(        init_if_needed,        payer = initializer,        space = Escrow::INIT_SPACE,        seeds = [b"state".as_ref(), &seed.to_le_bytes()],        bump    )]    pub escrow: Account<'info, Escrow>,    #[account(        init_if_needed,        payer = initializer,        associated_token::mint = mint_a,        associated_token::authority = escrow    )]
  1. Line 13 pub initializer: Signer<'info>,: Requires this account to have signed the transaction.
  2. Line 24 init_if_needed,: Creates the account only if it doesn't exist. Watch for re-initialisation bugs.
  3. Line 27 seeds = [b"state".as_ref(), &seed.to_le_bytes()],: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
  4. Line 28 bump: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.

How to run, build and test

These commands come from the repo's own manifests (package.json scripts, Anchor.toml, Cargo, go.mod, Makefile). Check the README for prerequisites and environment variables.

DirectoryCommandRuns
.npm run buildanchor build
.npm run testanchor test --skip-build --skip-deploy
.npm run deployanchor deploy
.anchor buildcompile programs and generate IDLs
.anchor testlocal validator + test suite
.anchor run testyarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts
.cargo buildRust workspace build
.cargo testRust tests

What you could build from it

Used in lessons