Sol.College

Full lesson

Sav3ana

What it does

From the project README:

Our app, as we mentioned before, aims to increase crypto adoption, improve the financial health of users, and give them more access to services without all the hassles of traditional banks.1
Original
altaga/Sav3ana
SuperStack fork
Blockchains/Sav3ana @ 2365a37
Stars
2
Last push (original)
2024-10-09
Languages
JavaScript, Rust, Kotlin, Objective-C, Ruby, Objective-C++
Detected stack
web3.js
Categories
Other
Licence
MIT

Architecture

62 source files. By extension: .js ×60, .tsx ×1, .rs ×1.

Top-level directorySource files
Sav3ana48
Programs10
Cloud4

Dapp: deploying

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

altaga/Sav3ana · Sav3ana/src/screens/topUp/topUp.js L85–108 @ 2365a37 · MIT · original
            true,          );          tx.add(            createTransferInstruction(              tokenAccountFrom,              tokenAccountTo,              new PublicKey(this.context.value.publicKey),              tokenAmount,            ),          );        }        const privateKey = await getEncryptedStorageValue('privateKey');        const wallet = Keypair.fromSecretKey(          Uint8Array.from(privateKey.split(',')),        );        const recentBlockhash = (await this.provider.getLatestBlockhash())          .blockhash;        tx.recentBlockhash = recentBlockhash;        tx.feePayer = wallet.publicKey;        tx.sign(wallet);        await this.provider.sendRawTransaction(tx.serialize(), {          maxRetries: 5,        });        const myHeaders = new Headers();
  1. Line 88 createTransferInstruction(: An SPL token transfer through the Token Program.
  2. Line 100 const recentBlockhash = (await this.provider.getLatestBlockhash()): Fetches a recent blockhash. Transactions expire if it gets too old.
altaga/Sav3ana · Sav3ana/src/screens/main/tabs/tab3.js L277–300 @ 2365a37 · MIT · original
        amount: this.state.amount,        tokenSymbol: this.state.tokenSelected.symbol,        // Bulk Display        labelBulk,        toBulk,        amountBulk,        tokenSymbolBulk,      },    });  }   async setupCard() {    await this.setupChainCard();    await this.setupCloudCard();  }   async createCard() {    const programId = new PublicKey(SolanaCardProgramID);    const owner = new PublicKey(this.context.value.publicKey);    let [pda, bump] = await PublicKey.findProgramAddressSync(      [Buffer.from('card'), owner.toBuffer()],      programId,    );    const kind = ProgramInstruction.CreateCard;
  1. Line 296 let [pda, bump] = await PublicKey.findProgramAddressSync(: Derives a PDA from seeds and the program ID and returns the address with its canonical bump.
  2. Line 296 let [pda, bump] = await PublicKey.findProgramAddressSync(: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
altaga/Sav3ana · Cloud/CardTransaction/index.js L49–72 @ 2365a37 · MIT · original
    const toAddress = req.body.toAddress;    const amount = req.body.amount;    const tokenAddress = req.body.tokenAddress;    const decimals = req.body.decimals;    const concept =  req.body.concept;    const query = await Accounts.where(      "cardHash",      "==",      decrypted.toString()    ).get();    if (query.empty) {      throw "Query Empty";    } else {        let transactionSignature;        const owner = new PublicKey(query.docs[0].data().pubKey);        const to = new PublicKey(toAddress);        let [pda,bump] = await PublicKey.findProgramAddressSync(            [Buffer.from("card"), owner.toBuffer()],            programId        );        let tx = new Transaction()        if(tokenAddress ==='So11111111111111111111111111111111111111112'){            const payload = {                instruction: ProgramInstruction.Purchase,
  1. Line 65 let [pda,bump] = await PublicKey.findProgramAddressSync(: Derives a PDA from seeds and the program ID and returns the address with its canonical bump.
  2. Line 65 let [pda,bump] = await PublicKey.findProgramAddressSync(: Uses the bump seed, the extra byte that pushes the derived address off the ed25519 curve.
altaga/Sav3ana · Cloud/TopUp/index.js L97–120 @ 2365a37 · MIT · original
        tx.add(            createAssociatedTokenAccountInstruction(            new PublicKey(feePayer.publicKey),            tokenAccountTo,            new PublicKey(publicKey),            new PublicKey(tokenAddress),            TOKEN_PROGRAM_ID,            ),        );        }        tx.add(        createTransferInstruction(            tokenAccountFrom,            tokenAccountTo,            new PublicKey(feePayer.publicKey),            Math.round(tokenAmount*Math.pow(10,decimals)),        ),        )    }    const recentBlockhash = (await connection.getLatestBlockhash()).blockhash;    tx.recentBlockhash = recentBlockhash;    tx.feePayer = feePayer.publicKey;    tx.sign(feePayer)    await connection.sendRawTransaction(
  1. Line 108 createTransferInstruction(: An SPL token transfer through the Token Program.
  2. Line 116 const recentBlockhash = (await connection.getLatestBlockhash()).blockhash;: Fetches a recent blockhash. Transactions expire if it gets too old.

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
Sav3ananpm run startreact-native start
Sav3ananpm run buildcd android && gradlew assembleRelease && cd ..
Sav3ananpm run testjest
Sav3ananpm run linteslint .
Sav3ananpm run deploycd android && gradlew :app:assembleRelease && adb install -r app/build/outputs/apk/release/app-release.apk
Programs/clientnpm run testecho "Error: no test specified" && exit 1

What you could build from it