@solana/web3.js is the JavaScript API built on top of the Solana JSON RPC API. We will use it to interact with the Solana Network
SDK Basics
Keypairs
Keypairs are a system of public and private keys used to access the Solana blockchain network. A keypair consists of a public key (which is publicly available and used to receive tokens) and a private key (which is kept securely and used to sign transactions).
Making a new KeyPair
constkeypair=Keypair.generate() // Helper function from **@solana/web3.js**constpublicKey=keypair.publickey// Index public keyconstprivateKey=keypair.secretkey// Index private key
Transactions
Transactions are instructions that call solana programs, usually to modify on-chain data.
They have 3 key elements:
uid of the program to call
list of accounts to read/write to
data in the form of a byte array
Writing Data
Here is an example of a complete program that writes data to the network.
Assignment
Generate a new keypair using the Keypair.generate() method from the @solana/web3.js library.
Create a program that creates a new transaction that transfers a specified amount of SOL from the public key to another public key, while also storing a message to be sent with the transaction.
The message should be encrypted using a basic encryption algorithm of the your choice (e.g. Caesar cipher, Vigenère cipher, etc.).
Confirm that the transaction has been completed, retrieve the encrypted message from the data account, and decrypt it.
Note: You should use the information provided in the course, including the code examples, to complete the assignment. The program should be written in JavaScript and use the @solana/web3.js library.
/* a simple transaction might look like this.
we are using helper functions from **@solana/web3.js** */
const transaction = new Transaction()
const sendInstruction = SystemProgram.transfer({
fromPubkey: sender, // sender address
toPubkey: recipient, // reciever address
lamports: LAMPORTS_PER_SOL * amount // amount of SOL to be sent
})
transaction.add(sendSolInstruction)
async function callProgram(
connection: web3.Connection,
payer: web3.Keypair,
programId: web3.PublicKey,
programDataAccount: web3.PublicKey
) {
/* This is a new transaction instruction - the programId
is the key of the program you are calling and keys contains
accounts that will be written to */
const instruction = new web3.TransactionInstruction({
keys: [
{
pubkey: programDataAccount,
isSigner: false,
isWritable: true
},
],
programId
})
/* "sig" waits for the confirmation of the transaction being completed.
The return of this is a signature created from the message and secret key,
used to log the transaction. */
const sig = await web3.sendAndConfirmTransaction(
connection,
new web3.Transaction().add(instruction),
[payer]
)
console.log(sig)
}
import { Keypair } from '@solana/web3.js';
import { Connection, Transaction } from '@solana/web3.js/src/transaction';
// Step 1: Generate a new keypair
const keypair = Keypair.generate();
console.log('Private key: ', keypair.secretKey);
console.log('Public key: ', keypair.publicKey);
// Step 2: Create a new transaction
const transferAmount = 1000;
const recipientPublicKey = 'Public key of the recipient';
const message = 'This is a secret message';
// Basic encryption using Caesar cipher
function encrypt(text, shift) {
let result = '';
for (let i = 0; i < text.length; i++) {
result += String.fromCharCode((text.charCodeAt(i) + shift - 65) % 26 + 65);
}
return result;
}
// Encrypt the message
const encryptedMessage = encrypt(message, 3);
// Create the transaction
const transaction = new Transaction();
transaction.addDataAccount(keypair.publicKey, encryptedMessage);
transaction.addTransfer(keypair.publicKey, recipientPublicKey, transferAmount);
// Step 3: Confirm the transaction has been completed
const connection = new Connection('<https://testnet.solana.com>');
const confirmation = await connection.sendRawTransaction(transaction.serialize(), keypair.secretKey);
console.log('Transaction confirmed: ', confirmation);
// Step 4: Retrieve the encrypted message and decrypt it
const dataAccount = await connection.getDataAccount(keypair.publicKey);
const decryptedMessage = encrypt(dataAccount.data, -3);
console.log('Decrypted message: ', decryptedMessage);
// Step 5 (Extra credit): Allow user input for message and encryption key
const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});
readline.question('Enter the message to be encrypted: ', (userMessage) => {
readline.question('Enter the encryption key: ', (encryptionKey) => {
const encrypted = encrypt(userMessage, parseInt(encryptionKey));
console.log('Encrypted message: ', encrypted);
readline.close();
});
});