This repository has been archived by the owner on Jan 24, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: cookbook * prettier * feat: added cookbook to crowdin * Update content/cookbook/index.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/index.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/nfts/index.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/transactions/index.md Co-authored-by: Nick Frostbutter <[email protected]> * fix: prettier * fix: prettier * cookbook material * added seo descriptions to cookbook pages * refactor: editorial changes * Update content/cookbook/wallets/generate-mnemonic.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/wallets/sign-message.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/transactions/add-priority-fees.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/transactions/add-memo.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/transactions/calculate-cost.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/transactions/calculate-cost.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/transactions/optimize-compute.md Co-authored-by: Nick Frostbutter <[email protected]> * Update content/cookbook/transactions/add-memo.md Co-authored-by: Nick Frostbutter <[email protected]> * cookbook feedback fixes * fix: links --------- Co-authored-by: nickfrosty <[email protected]>
- Loading branch information
1 parent
632086a
commit 0736916
Showing
29 changed files
with
1,189 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
--- | ||
title: How to Calculate Account Creation Cost | ||
sidebarSortOrder: 2 | ||
description: | ||
"Every time you create an account, that creation costs a small amount of SOL. | ||
Learn how to calculate how much an account costs at creation." | ||
--- | ||
|
||
Keeping accounts alive on Solana incurs a storage cost called rent. For the | ||
calculation, you need to consider the amount of data you intend to store in the | ||
account. Rent can be reclaimed in full if the account is closed. | ||
|
||
```typescript filename="calculate-rent.ts" | ||
import { Connection, clusterApiUrl } from "@solana/web3.js"; | ||
|
||
(async () => { | ||
const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); | ||
|
||
// length of data in bytes in the account to calculate rent for | ||
const dataLength = 1500; | ||
const rentExemptionAmount = | ||
await connection.getMinimumBalanceForRentExemption(dataLength); | ||
console.log({ | ||
rentExemptionAmount, | ||
}); | ||
})(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
--- | ||
title: How to Close an Account | ||
sidebarSortOrder: 5 | ||
description: | ||
"When an account is no longer needed, you can close the account to reclaim the | ||
rent. Learn how to close accounts efficiently on Solana." | ||
--- | ||
|
||
Closing accounts enables you to reclaim the SOL that was used to open the | ||
account, but requires deleting of all information in the account. When an | ||
account is closed, make sure that the data is zeroed out in the same instruction | ||
to avoid people reopening the account in the same transaction and getting access | ||
to the data. This is because the account is not actually closed until the | ||
transaction is completed. | ||
|
||
```rust filename="close-account.rs" {18-25} | ||
use solana_program::{ | ||
account_info::next_account_info, account_info::AccountInfo, entrypoint, | ||
entrypoint::ProgramResult, pubkey::Pubkey, | ||
}; | ||
|
||
entrypoint!(process_instruction); | ||
|
||
fn process_instruction( | ||
_program_id: &Pubkey, | ||
accounts: &[AccountInfo], | ||
_instruction_data: &[u8], | ||
) -> ProgramResult { | ||
let account_info_iter = &mut accounts.iter(); | ||
|
||
let source_account_info = next_account_info(account_info_iter)?; | ||
let dest_account_info = next_account_info(account_info_iter)?; | ||
|
||
let dest_starting_lamports = dest_account_info.lamports(); | ||
**dest_account_info.lamports.borrow_mut() = dest_starting_lamports | ||
.checked_add(source_account_info.lamports()) | ||
.unwrap(); | ||
**source_account_info.lamports.borrow_mut() = 0; | ||
|
||
let mut source_data = source_account_info.data.borrow_mut(); | ||
source_data.fill(0); | ||
|
||
Ok(()) | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
--- | ||
title: How to Create an Account | ||
sidebarSortOrder: 1 | ||
description: | ||
"Accounts are the basic building blocks of anything on Solana. Learn how to | ||
create accounts on the Solana blockchain." | ||
--- | ||
|
||
Creating an account requires using the System Program `createAccount` | ||
instruction. The Solana runtime will grant the owner of an account, access to | ||
write to its data or transfer lamports. When creating an account, we have to | ||
preallocate a fixed storage space in bytes (space) and enough lamports to cover | ||
the rent. | ||
|
||
```typescript filename="create-account.ts" | ||
import { | ||
SystemProgram, | ||
Keypair, | ||
Transaction, | ||
sendAndConfirmTransaction, | ||
Connection, | ||
clusterApiUrl, | ||
LAMPORTS_PER_SOL, | ||
} from "@solana/web3.js"; | ||
|
||
(async () => { | ||
const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); | ||
const fromPubkey = Keypair.generate(); | ||
|
||
// Airdrop SOL for transferring lamports to the created account | ||
const airdropSignature = await connection.requestAirdrop( | ||
fromPubkey.publicKey, | ||
LAMPORTS_PER_SOL, | ||
); | ||
await connection.confirmTransaction(airdropSignature); | ||
|
||
// amount of space to reserve for the account | ||
const space = 0; | ||
|
||
// Seed the created account with lamports for rent exemption | ||
const rentExemptionAmount = | ||
await connection.getMinimumBalanceForRentExemption(space); | ||
|
||
const newAccountPubkey = Keypair.generate(); | ||
const createAccountParams = { | ||
fromPubkey: fromPubkey.publicKey, | ||
newAccountPubkey: newAccountPubkey.publicKey, | ||
lamports: rentExemptionAmount, | ||
space, | ||
programId: SystemProgram.programId, | ||
}; | ||
|
||
const createAccountTransaction = new Transaction().add( | ||
SystemProgram.createAccount(createAccountParams), | ||
); | ||
|
||
await sendAndConfirmTransaction(connection, createAccountTransaction, [ | ||
fromPubkey, | ||
newAccountPubkey, | ||
]); | ||
})(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
--- | ||
title: How to Create a PDA's Account | ||
sidebarSortOrder: 3 | ||
description: | ||
"Program Derived Addresses, also known as PDAs, enable developers to extend | ||
their program's functionality with program-owned accounts. Learn how to create | ||
accounts at PDAs on Solana." | ||
--- | ||
|
||
Accounts found at Program Derived Addresses (PDAs) can only be created on-chain. | ||
The accounts have addresses that have an associated off-curve public key, but no | ||
secret key. | ||
|
||
To generate a PDA, use `findProgramAddressSync` with your required seeds. | ||
Generating with the same seeds will always generate the same PDA. | ||
|
||
## Generating a PDA | ||
|
||
```typescript filename="generate-pda.ts" | ||
import { PublicKey } from "@solana/web3.js"; | ||
|
||
const programId = new PublicKey("G1DCNUQTSGHehwdLCAmRyAG8hf51eCHrLNUqkgGKYASj"); | ||
|
||
let [pda, bump] = PublicKey.findProgramAddressSync( | ||
[Buffer.from("test")], | ||
programId, | ||
); | ||
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`); | ||
// you will find the result is different from `createProgramAddress`. | ||
// It is expected because the real seed we used to calculate is ["test" + bump] | ||
``` | ||
|
||
## Create an Account at a PDA | ||
|
||
### Program | ||
|
||
```rust filename="create-pda.rs" {24-37} | ||
use solana_program::{ | ||
account_info::next_account_info, account_info::AccountInfo, entrypoint, | ||
entrypoint::ProgramResult, program::invoke_signed, pubkey::Pubkey, system_instruction, sysvar::{rent::Rent, Sysvar} | ||
}; | ||
|
||
entrypoint!(process_instruction); | ||
|
||
fn process_instruction( | ||
program_id: &Pubkey, | ||
accounts: &[AccountInfo], | ||
instruction_data: &[u8], | ||
) -> ProgramResult { | ||
let account_info_iter = &mut accounts.iter(); | ||
|
||
let payer_account_info = next_account_info(account_info_iter)?; | ||
let pda_account_info = next_account_info(account_info_iter)?; | ||
let rent_sysvar_account_info = &Rent::from_account_info(next_account_info(account_info_iter)?)?; | ||
|
||
// find space and minimum rent required for account | ||
let space = instruction_data[0]; | ||
let bump = instruction_data[1]; | ||
let rent_lamports = rent_sysvar_account_info.minimum_balance(space.into()); | ||
|
||
invoke_signed( | ||
&system_instruction::create_account( | ||
&payer_account_info.key, | ||
&pda_account_info.key, | ||
rent_lamports, | ||
space.into(), | ||
program_id | ||
), | ||
&[ | ||
payer_account_info.clone(), | ||
pda_account_info.clone() | ||
], | ||
&[&[&payer_account_info.key.as_ref(), &[bump]]] | ||
)?; | ||
|
||
Ok(()) | ||
} | ||
``` | ||
|
||
## Client | ||
|
||
```typescript filename="create-pda.ts" | ||
import { | ||
clusterApiUrl, | ||
Connection, | ||
Keypair, | ||
Transaction, | ||
SystemProgram, | ||
PublicKey, | ||
TransactionInstruction, | ||
LAMPORTS_PER_SOL, | ||
SYSVAR_RENT_PUBKEY, | ||
} from "@solana/web3.js"; | ||
|
||
(async () => { | ||
// program id | ||
const programId = new PublicKey( | ||
"7ZP42kRwUQ2zgbqXoaXzAFaiQnDyp6swNktTSv8mNQGN", | ||
); | ||
|
||
// connection | ||
const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); | ||
|
||
// setup fee payer | ||
const feePayer = Keypair.generate(); | ||
const feePayerAirdropSignature = await connection.requestAirdrop( | ||
feePayer.publicKey, | ||
LAMPORTS_PER_SOL, | ||
); | ||
await connection.confirmTransaction(feePayerAirdropSignature); | ||
|
||
// setup pda | ||
let [pda, bump] = await PublicKey.findProgramAddress( | ||
[feePayer.publicKey.toBuffer()], | ||
programId, | ||
); | ||
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`); | ||
|
||
const data_size = 0; | ||
|
||
let tx = new Transaction().add( | ||
new TransactionInstruction({ | ||
keys: [ | ||
{ | ||
pubkey: feePayer.publicKey, | ||
isSigner: true, | ||
isWritable: true, | ||
}, | ||
{ | ||
pubkey: pda, | ||
isSigner: false, | ||
isWritable: true, | ||
}, | ||
{ | ||
pubkey: SYSVAR_RENT_PUBKEY, | ||
isSigner: false, | ||
isWritable: false, | ||
}, | ||
{ | ||
pubkey: SystemProgram.programId, | ||
isSigner: false, | ||
isWritable: false, | ||
}, | ||
], | ||
data: Buffer.from(new Uint8Array([data_size, bump])), | ||
programId: programId, | ||
}), | ||
); | ||
|
||
console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`); | ||
})(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
--- | ||
title: How to Get Account Balance | ||
sidebarSortOrder: 6 | ||
description: | ||
"Every account on Solana has a balance of SOL stored. Learn how to retrieve | ||
that account balance on Solana." | ||
--- | ||
|
||
```typescript filename="get-account-balance.ts" {13} | ||
import { | ||
clusterApiUrl, | ||
Connection, | ||
PublicKey, | ||
LAMPORTS_PER_SOL, | ||
} from "@solana/web3.js"; | ||
|
||
(async () => { | ||
const connection = new Connection(clusterApiUrl("devnet"), "confirmed"); | ||
|
||
let wallet = new PublicKey("G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY"); | ||
console.log( | ||
`${(await connection.getBalance(wallet)) / LAMPORTS_PER_SOL} SOL`, | ||
); | ||
})(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
metaOnly: true | ||
title: Accounts | ||
sidebarSortOrder: 3 | ||
--- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
--- | ||
title: How to Sign with a PDA's Account | ||
sidebarSortOrder: 4 | ||
description: | ||
"A main feature of accounts at Program Derived Addresses is the ability for | ||
programs to sign using those accounts. Learn how to sign with PDA accounts on | ||
Solana." | ||
--- | ||
|
||
Program derived addresses (PDA) can be used to have accounts owned by programs | ||
that can sign. This is useful if you want a program to own a token account and | ||
you want the program to transfer tokens from one account to another. | ||
|
||
```rust filename="sign-with-pda.rs" {22-34} | ||
use solana_program::{ | ||
account_info::next_account_info, account_info::AccountInfo, entrypoint, | ||
entrypoint::ProgramResult, program::invoke_signed, pubkey::Pubkey, system_instruction, | ||
}; | ||
|
||
entrypoint!(process_instruction); | ||
|
||
fn process_instruction( | ||
_program_id: &Pubkey, | ||
accounts: &[AccountInfo], | ||
instruction_data: &[u8], | ||
) -> ProgramResult { | ||
let account_info_iter = &mut accounts.iter(); | ||
|
||
let pda_account_info = next_account_info(account_info_iter)?; | ||
let to_account_info = next_account_info(account_info_iter)?; | ||
let system_program_account_info = next_account_info(account_info_iter)?; | ||
|
||
// pass bump seed for saving compute budget | ||
let bump_seed = instruction_data[0]; | ||
|
||
invoke_signed( | ||
&system_instruction::transfer( | ||
&pda_account_info.key, | ||
&to_account_info.key, | ||
100_000_000, // 0.1 SOL | ||
), | ||
&[ | ||
pda_account_info.clone(), | ||
to_account_info.clone(), | ||
system_program_account_info.clone(), | ||
], | ||
&[&[b"escrow", &[bump_seed]]], | ||
)?; | ||
|
||
Ok(()) | ||
} | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
--- | ||
sidebarSortOrder: 0 | ||
title: Solana Cookbook | ||
seoTitle: Code examples for Solana development | ||
description: | ||
"The Solana cookbook is a collection of useful examples and references for | ||
building on Solana" | ||
--- | ||
|
||
The _Solana Cookbook_ is a developer resource that provides examples and | ||
references for building applications on Solana. Each example and reference will | ||
focus on specific aspects of Solana development while providing additional | ||
details and usage examples. |
Oops, something went wrong.