Sol.College

Full lesson

GadoWallet

Protecting your crypto wealth beyond your lifetime

What it does

From the project README:

A comprehensive, business-ready digital asset inheritance platform built on Solana with advanced features including Smart Wallets, automated inheritance execution, platform fees, multi-tier user management, and real-time analytics dashboard.
Original
Emmyhack/GadoWallet
SuperStack fork
Blockchains/GadoWallet @ f4e01c4
Stars
0
Last push (original)
2025-11-03
Languages
TypeScript, JavaScript, Rust, Shell, CSS, HTML
Detected stack
Anchorweb3.js
Categories
Wallets & Identity
Licence
MIT
Homepage
https://gado-wallet.vercel.app

Architecture

119 source files. By extension: .tsx ×49, .ts ×40, .js ×26, .rs ×4.

Top-level directorySource files
frontend79
gado28
(root)6
chrome-extension6

On-chain programs: gado/programs/gado

Dapp: devnet deploy pending

⏳ Devnet deploy pending — goes live when the devnet wallet is topped up. This fork's own dapp is not deployed yet, so there is no program address or transaction to show. It is queued in dapp-queue.txt; once devnet SOL is available it is deployed, exercised with real devnet transactions, and this section switches to the live dapp at /dapps/gadowallet/. Until then, the lesson and step-by-step guide below are complete, and you can 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.

Emmyhack/GadoWallet · gado/programs/gado/src/lib.rs L109–131 @ f4e01c4 · MIT · original
        token_heir.amount = amount;        token_heir.inactivity_period_seconds = inactivity_period_seconds;        token_heir.last_activity = Clock::get()?.unix_timestamp;        token_heir.is_claimed = false;        token_heir.bump = ctx.bumps.token_heir;                // Transfer tokens from owner to escrow account        let cpi_accounts = Transfer {            from: ctx.accounts.owner_token_account.to_account_info(),            to: ctx.accounts.escrow_token_account.to_account_info(),            authority: ctx.accounts.owner.to_account_info(),        };        let cpi_program = ctx.accounts.token_program.to_account_info();        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);        token::transfer(cpi_ctx, amount)?;                // Update user profile        let user_profile = &mut ctx.accounts.user_profile;        user_profile.total_inheritances += 1;                msg!("Token heir added: {} tokens for heir: {}", amount, ctx.accounts.heir.key());        Ok(())    }
  1. Line 111 token_heir.last_activity = Clock::get()?.unix_timestamp;: Reads on-chain time from the Clock sysvar.
  2. Line 113 token_heir.bump = ctx.bumps.token_heir;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 122 let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);: Makes a cross-program invocation into another program.
  4. Line 123 token::transfer(cpi_ctx, amount)?;: An SPL token transfer through the Token Program.
  5. Line 129 msg!("Token heir added: {} tokens for heir: {}", amount, ctx.accounts.heir.key());: Logs to the program log, which is visible in explorers and the test output.
Emmyhack/GadoWallet · gado/programs/gado/src/lib_new.rs L97–120 @ f4e01c4 · MIT · original
        token_heir.last_activity = Clock::get()?.unix_timestamp;        token_heir.is_claimed = false;        token_heir.bump = ctx.bumps.token_heir;                // Transfer tokens from owner to escrow account        let cpi_accounts = Transfer {            from: ctx.accounts.owner_token_account.to_account_info(),            to: ctx.accounts.escrow_token_account.to_account_info(),            authority: ctx.accounts.owner.to_account_info(),        };        let cpi_program = ctx.accounts.token_program.to_account_info();        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);        token::transfer(cpi_ctx, amount)?;                // Update user profile        let user_profile = &mut ctx.accounts.user_profile;        user_profile.total_inheritances += 1;                msg!("Token heir added: {} tokens for heir: {}", amount, ctx.accounts.heir.key());        Ok(())    }     /// Update activity for SOL heir (resets inactivity timer)    pub fn update_sol_activity(ctx: Context<UpdateSolActivity>) -> Result<()> {
  1. Line 97 token_heir.last_activity = Clock::get()?.unix_timestamp;: Reads on-chain time from the Clock sysvar.
  2. Line 99 token_heir.bump = ctx.bumps.token_heir;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 108 let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);: Makes a cross-program invocation into another program.
  4. Line 109 token::transfer(cpi_ctx, amount)?;: An SPL token transfer through the Token Program.
  5. Line 115 msg!("Token heir added: {} tokens for heir: {}", amount, ctx.accounts.heir.key());: Logs to the program log, which is visible in explorers and the test output.
Emmyhack/GadoWallet · gado/programs/gado/src/basic_inheritance.rs L97–120 @ f4e01c4 · MIT · original
        token_heir.last_activity = Clock::get()?.unix_timestamp;        token_heir.is_claimed = false;        token_heir.bump = ctx.bumps.token_heir;                // Transfer tokens from owner to escrow account        let cpi_accounts = Transfer {            from: ctx.accounts.owner_token_account.to_account_info(),            to: ctx.accounts.escrow_token_account.to_account_info(),            authority: ctx.accounts.owner.to_account_info(),        };        let cpi_program = ctx.accounts.token_program.to_account_info();        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);        token::transfer(cpi_ctx, amount)?;                // Update user profile        let user_profile = &mut ctx.accounts.user_profile;        user_profile.total_inheritances += 1;                msg!("Token heir added: {} tokens for heir: {}", amount, ctx.accounts.heir.key());        Ok(())    }     /// Update activity for SOL heir (resets inactivity timer)    pub fn update_sol_activity(ctx: Context<UpdateSolActivity>) -> Result<()> {
  1. Line 97 token_heir.last_activity = Clock::get()?.unix_timestamp;: Reads on-chain time from the Clock sysvar.
  2. Line 99 token_heir.bump = ctx.bumps.token_heir;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  3. Line 108 let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);: Makes a cross-program invocation into another program.
  4. Line 109 token::transfer(cpi_ctx, amount)?;: An SPL token transfer through the Token Program.
  5. Line 115 msg!("Token heir added: {} tokens for heir: {}", amount, ctx.accounts.heir.key());: Logs to the program log, which is visible in explorers and the test output.
Emmyhack/GadoWallet · gado/programs/gado/src/lib_backup.rs L253–276 @ f4e01c4 · MIT · original
        // Validate owner's token account        require_keys_eq!(ctx.accounts.owner_token_account.mint, ctx.accounts.token_mint.key(), ErrorCode::InvalidMint);        require_keys_eq!(ctx.accounts.owner_token_account.owner, ctx.accounts.owner.key(), ErrorCode::Unauthorized);         // Initialize state        let token_heir = &mut ctx.accounts.token_heir;        token_heir.owner = *ctx.accounts.owner.key;        token_heir.heir = *ctx.accounts.heir.key;        token_heir.token_mint = ctx.accounts.token_mint.key();        token_heir.amount = amount;        token_heir.last_active_time = Clock::get()?.unix_timestamp;        token_heir.is_claimed = false;        token_heir.inactivity_period_seconds = inactivity_period_seconds;        token_heir.bump = ctx.bumps.token_heir;         // Escrow: transfer tokens from owner to PDA-owned ATA (escrow)        let cpi_accounts = Transfer {            from: ctx.accounts.owner_token_account.to_account_info(),            to: ctx.accounts.escrow_token_account.to_account_info(),            authority: ctx.accounts.owner.to_account_info(),        };        let cpi_program = ctx.accounts.token_program.to_account_info();        let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);        token::transfer(cpi_ctx, amount)?;
  1. Line 254 require_keys_eq!(ctx.accounts.owner_token_account.mint, ctx.accounts.token_mint.key(), Err: An explicit validation that aborts the instruction with an error.
  2. Line 263 token_heir.last_active_time = Clock::get()?.unix_timestamp;: Reads on-chain time from the Clock sysvar.
  3. Line 266 token_heir.bump = ctx.bumps.token_heir;: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
  4. Line 275 let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);: Makes a cross-program invocation into another program.
  5. Line 276 token::transfer(cpi_ctx, amount)?;: An SPL token transfer through the Token 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
gadonpm run lintprettier */*.js "*/**/*{.js,.ts}" --check
frontendnpm run devvite
frontendnpm run buildtsc -b && vite build
frontendnpm run linteslint .
chrome-extensionnpm run devwebpack --mode=development --watch
chrome-extensionnpm run buildwebpack --mode=production
chrome-extensionnpm run testjest
chrome-extensionnpm run linteslint src/**/*.js
gadoanchor buildcompile programs and generate IDLs
gadoanchor testlocal validator + test suite
gadoanchor run testyarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts

What you could build from it

Used in lessons