Sol.College

Full lesson

kryptpay-solana-contract

Smart contract that handles payment and issue reward token to users as they transact. And also facilitate swapping

What it does

From the project README:

KryptPay is an innovative crypto wallet designed to simplify transactions at the point of sale (PoS). KryptPay offers users the ability to pay for products and services using various cryptocurrencies. In addition, users are rewarded with Krystal for every transaction made and for referring new users to the platform.
Original
KryptPay/kryptpay-solana-contract
SuperStack fork
Blockchains/kryptpay-solana-contract @ a528c51
Stars
0
Last push (original)
2024-04-07
Languages
Rust, TypeScript
Detected stack
AnchorMetaplex
Categories
DeFiPayments
Licence
MIT

Architecture

8 source files. By extension: .rs ×6, .ts ×2.

Top-level directorySource files
programs6
migrations1
tests1

On-chain programs: programs/kryptpay

🟡 Builds, verified 2026-11-02 Tested on 2026-11-02: full log results.json

Build it yourself: step-by-step guide

Every command below was run on 2026-11-02 by tests/run_fork.py against the pinned commit, and the results come from that run. The full output is in the committed log.

1. Prerequisites (versions we tested with)

cargo install --git https://github.com/coral-xyz/anchor avm --locked
avm install 0.29.0 && avm use 0.29.0
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"

2. Clone at the tested commit

git clone https://github.com/Blockchains/kryptpay-solana-contract.git && cd kryptpay-solana-contract
git checkout a528c517cd7dc23fff528a6b876297624d482b3e

3. Configure

No environment file is needed.

4. Install dependencies

DirectoryCommandResultTime
.npx -y yarn@1 install --ignore-engines --network-timeout 600000✅ pass3s
.npx -y yarn@1 install --ignore-engines --network-timeout 600000✅ pass1s

5. Build

DirectoryCommandResultTime
.anchor@0.29.0 build✅ pass83s

6. Test

DirectoryCommandResultTime
.anchor@0.29.0 test --skip-build --provider.cluster localnet --provider.wallet ~/.config/solana/id.json❌ exit 23s
Output tail: anchor@0.29.0 test --skip-build --provider.cluster localnet --provider.wallet ~/
Environment variable KEY_PAIR is not set.
(node:2697275) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///tmp/scbuild/kryptpay-solana-contract/tests/kryptpay.ts is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /tmp/scbuild/kryptpay-solana-contract/package.json.
(Use `node --trace-warnings ...` to show where the warning was created)
error Command failed with exit code 2.

7. Deploy to a local validator

solana-test-validator --reset   # separate terminal
solana config set -ul && solana airdrop 100
anchor deploy --provider.cluster localnet
DirectoryCommandResultTime
.solana airdrop 100 -u localhost >/dev/null; anchor@0.29.0 deploy --provider.cluster localnet --provider.wallet ~/.config/solana/id.json✅ pass5s

Proof: program IDs and transactions

Transaction signatures recorded on the local validator (1 shown). Local ledgers are thrown away after the run, so these work as receipts in the log and can't be looked up on an explorer:

Deploy to devnet (free)

solana config set --url devnet
solana airdrop 2   # or https://faucet.solana.com
anchor deploy --provider.cluster devnet   # native: solana program deploy target/deploy/<name>.so
# point the frontend RPC env var at https://api.devnet.solana.com

How it works

Every instruction handler in the program, with the accounts struct it validates. Each link points to the line at the pinned commit.

InstructionAccountsWhere
transfer_spl_tokensTransferSplprograms/kryptpay/src/lib.rs:21
transfer_lamportsTransferLamportsprograms/kryptpay/src/lib.rs:70

Extend it

  1. Add an integration test that runs the main flow end to end and asserts every account state change.
  2. Add a negative test: call each instruction with the wrong signer or account and check that it fails.
  3. Add an event (emit!) to each state-changing instruction and subscribe to it from the client.
  4. Replace any unchecked AccountInfo with typed accounts plus has_one/seeds constraints.
  5. Wire the build into CI by copying this site's verify-forks workflow.

Open the dapp

Deployed on devnet; the full in-browser flow is not yet proven end to end.

Open the dapp Connect Phantom or Solflare. Every transaction is signed in your own wallet.

Key code, explained

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

KryptPay/kryptpay-solana-contract · programs/kryptpay/src/instructions/swap_exact_tokens_for_tokens.rs L49–72 @ a528c51 · MIT · original
            .checked_div(                I64F64::from_num(pool_b.amount)                    .checked_add(I64F64::from_num(taxed_input))                    .unwrap(),            )            .unwrap()    }    .to_num::<u64>();     if output < min_output_amount {        return err!(TutorialError::OutputTooSmall);    }     // Compute the invariant before the trade    let invariant = pool_a.amount * pool_b.amount;     // Transfer tokens to the pool    let authority_bump = *ctx.bump.get("pool_authority").unwrap();    let authority_seeds = &[        &ctx.accounts.pool.amm.to_bytes(),        &ctx.accounts.mint_a.key().to_bytes(),        &ctx.accounts.mint_b.key().to_bytes(),        AUTHORITY_SEED.as_bytes(),        &[authority_bump],
  1. Line 49 .checked_div(: Uses checked arithmetic so overflow fails instead of wrapping.
  2. Line 59 return err!(TutorialError::OutputTooSmall);: An explicit validation that aborts the instruction with an error.
  3. Line 66 let authority_bump = *ctx.bump.get("pool_authority").unwrap();: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  4. Line 67 let authority_seeds = &[: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
KryptPay/kryptpay-solana-contract · programs/kryptpay/src/lib.rs L109–132 @ a528c51 · MIT · original
            platform_fee,        );        anchor_lang::solana_program::program::invoke_signed(            &transfer_platform_instruction,            &[                ctx.accounts.from.to_account_info(),                platform_account,                ctx.accounts.system_program.to_account_info(),            ],            &[],        )?;         // Reward user with 10 Krystal tokens        // Transfer tokens from taker to initializer        let cpi_accounts = SplTransfer {            from: source.to_account_info().clone(),            to: destination.to_account_info().clone(),            authority: authority.to_account_info().clone(),        };        let cpi_program = token_program.to_account_info();                transfer(            CpiContext::new(cpi_program, cpi_accounts),            reward_amount)?;
  1. Line 111 anchor_lang::solana_program::program::invoke_signed(: Makes a CPI signed by a PDA. The signer seeds prove the program controls that address.
  2. Line 131 CpiContext::new(cpi_program, cpi_accounts),: Makes a cross-program invocation into another program.

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 lintprettier */*.js "*/**/*{.js,.ts}" --check
.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