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 directory | Source files |
|---|---|
programs | 6 |
migrations | 1 |
tests | 1 |
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)
- Rust:
rustc 1.99.1 (58cf8f9c3 2026-10-13) - Solana CLI (Agave):
solana-cli 1.18.17 (src:c027cfc3; feat:4215500110, client:Agave) - Anchor (via avm):
0.29.0 - Node.js:
v24.22.1 - npm:
11.21.1 - pnpm:
10.34.6 - Go:
go version go1.27.3 linux/amd64
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 a528c517cd7dc23fff528a6b876297624d482b3e3. Configure
No environment file is needed.
4. Install dependencies
| Directory | Command | Result | Time |
|---|---|---|---|
. | npx -y yarn@1 install --ignore-engines --network-timeout 600000 | ✅ pass | 3s |
. | npx -y yarn@1 install --ignore-engines --network-timeout 600000 | ✅ pass | 1s |
5. Build
| Directory | Command | Result | Time |
|---|---|---|---|
. | anchor@0.29.0 build | ✅ pass | 83s |
6. Test
| Directory | Command | Result | Time |
|---|---|---|---|
. | anchor@0.29.0 test --skip-build --provider.cluster localnet --provider.wallet ~/.config/solana/id.json | ❌ exit 2 | 3s |
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| Directory | Command | Result | Time |
|---|---|---|---|
. | solana airdrop 100 -u localhost >/dev/null; anchor@0.29.0 deploy --provider.cluster localnet --provider.wallet ~/.config/solana/id.json | ✅ pass | 5s |
Proof: program IDs and transactions
kryptpay:4t7s1ip7eKcwytjwQMnCtf8nZ2RCTuBNxR7faFL7XoAV(local validator)
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:
kryptpay2pK3TvDYUQE8uh6xuu6w…yz6Gxv8P
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.comHow it works
Every instruction handler in the program, with the accounts struct it validates. Each link points to the line at the pinned commit.
| Instruction | Accounts | Where |
|---|---|---|
transfer_spl_tokens | TransferSpl | programs/kryptpay/src/lib.rs:21 |
transfer_lamports | TransferLamports | programs/kryptpay/src/lib.rs:70 |
Extend it
- Add an integration test that runs the main flow end to end and asserts every account state change.
- Add a negative test: call each instruction with the wrong signer or account and check that it fails.
- Add an event (
emit!) to each state-changing instruction and subscribe to it from the client. - Replace any unchecked
AccountInfowith typed accounts plushas_one/seedsconstraints. - 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.
- Devnet (test tokens): program
4t7s1ip7eKcwytjwQMnCtf8nZ2RCTuBNxR7faFL7XoAV. Get free devnet SOL at faucet.solana.com. - Mainnet: not yet deployed on mainnet (needs owner approval), so it is disabled
Key code, explained
Excerpts chosen automatically where the code uses the most Solana concepts, pinned to the fork's commit.
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],- Line 49
.checked_div(: Uses checked arithmetic so overflow fails instead of wrapping. - Line 59
return err!(TutorialError::OutputTooSmall);: An explicit validation that aborts the instruction with an error. - 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. - Line 67
let authority_seeds = &[: Declares the PDA seeds. Anchor re-derives the address and rejects the account if it doesn't match.
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)?;- 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. - 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.
| Directory | Command | Runs |
|---|---|---|
. | npm run lint | prettier */*.js "*/**/*{.js,.ts}" --check |
. | anchor build | compile programs and generate IDLs |
. | anchor test | local validator + test suite |
. | anchor run test | yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts |
. | cargo build | Rust workspace build |
. | cargo test | Rust tests |
What you could build from it
- Fork the SuperStack copy and extend it within the DeFi gaps listed on the idea page.
- Learn the pattern first: Program Derived Addresses (PDAs)
- Learn the pattern first: Cross-Program Invocations (CPIs)
- Learn the pattern first: SPL Tokens: mints, accounts and transfers