Sol.College

Full lesson

GotokHQ-cash

Original
GotokHQ/cash
SuperStack fork
Blockchains/GotokHQ-cash @ 5c25fd0
Stars
0
Last push (original)
2024-11-24
Languages
Rust, TypeScript, Shell, JavaScript
Detected stack
MetaplexNative Rustweb3.js
Categories
Other
Licence
MIT

Architecture

24 source files. By extension: .ts ×12, .rs ×10, .js ×2.

Top-level directorySource files
src12
program10
(root)2

Dapp: deploying

This fork is queued for its own live dapp on Sol.College, with a Devnet/Mainnet switch. It appears here, at /dapps/gotokhq-cash/, 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.

GotokHQ/cash · program/src/utils.rs L169–192 @ 5c25fd0 · MIT · original
    authority: &AccountInfo<'a>,    mint: &AccountInfo<'a>,    token_id: &Pubkey,    amount: u64,    decimals: u8,    signers_seeds: &[&[&[u8]]],) -> Result<(), ProgramError> {    let ix = spl_token_2022::instruction::transfer_checked(        token_id,        source.key,        mint.key,        destination.key,        authority.key,        &[],        amount,        decimals,    )?;     invoke_signed(        &ix,        &[source.clone(), mint.clone(), destination.clone(), authority.clone()],        signers_seeds,    )}
  1. Line 176 let ix = spl_token_2022::instruction::transfer_checked(: A checked token transfer, which also verifies the mint and decimals.
  2. Line 176 let ix = spl_token_2022::instruction::transfer_checked(: Targets the Token-2022 program instead of the original Token Program.
  3. Line 187 invoke_signed(: Makes a CPI signed by a PDA. The signer seeds prove the program controls that address.
GotokHQ/cash · src/cash/index.ts L97–120 @ 5c25fd0 · MIT · original
    if (cash == null) {      throw new Error(FAILED_TO_FIND_ACCOUNT);    }    const { instructions, signers } = await this.cancelTransaction(cash, bump, input);    if (input.computeBudget) {      instructions.push(        ComputeBudgetProgram.setComputeUnitLimit({          units: input.computeBudget,        }),      );    }    if (input.computeUnitPrice) {      instructions.push(        ComputeBudgetProgram.setComputeUnitPrice({          microLamports: input.computeUnitPrice,        }),      );    }    const { context, value } = await this.connection.getLatestBlockhashAndContext(input.commitment);    signers.push(this._feePayer, this._authority);    if (input.asLegacyTransaction) {      const transaction = new Transaction();      transaction.recentBlockhash = value.blockhash;      transaction.lastValidBlockHeight = value.lastValidBlockHeight;
  1. Line 100 const { instructions, signers } = await this.cancelTransaction(cash, bump, input);: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  2. Line 103 ComputeBudgetProgram.setComputeUnitLimit({: Sets the compute-unit limit or price (priority fee).
  3. Line 115 const { context, value } = await this.connection.getLatestBlockhashAndContext(input.commit: Fetches a recent blockhash. Transactions expire if it gets too old.
GotokHQ/cash · program/src/processor/cash.rs L97–120 @ 5c25fd0 · MIT · original
        }        _ => args.amount,    };    if args.distribution_type == DistributionType::Random {        if args.min_amount.is_none() {            return Err(CashError::MinAmountNotSet.into());        }        if let Some(min_amount) = args.min_amount {            if min_amount > total_amount {                return Err(CashError::MinAmountMustBeLessThanAmount.into());            }        }    }    // if args.num_days_to_expire == 0 {    //     return Err(CashError::InvalidExpiryInDays.into());    // }    //let now = clock.unix_timestamp as u64;    let total = total_amount        .checked_add(total_platform_fee)        .ok_or::<ProgramError>(CashError::Overflow.into())?        .checked_add(total_redemption_fee)        .ok_or::<ProgramError>(CashError::Overflow.into())?;    cash.account_type = AccountType::Cash;    cash.state = CashState::Initialized;
  1. Line 113 //let now = clock.unix_timestamp as u64;: Reads on-chain time from the Clock sysvar.
  2. Line 115 .checked_add(total_platform_fee): Uses checked arithmetic so overflow fails instead of wrapping.

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 starttsc --watch
.npm run buildrimraf dist && tsc -p tsconfig.json
.npm run testesr ./test/*.test.ts
.npm run linteslint "{src,test}/**/*.ts" --format stylish

What you could build from it

Used in lessons