-
Notifications
You must be signed in to change notification settings - Fork 300
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add favorites and escrow projects from professional-education repo
Minor biome fixes Move into proper dirs
- Loading branch information
1 parent
2c4cb8f
commit a6e2528
Showing
32 changed files
with
913 additions
and
0 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
basics/favorites/anchor/favorites/anchor/favorites/.gitignore
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,9 @@ | ||
|
||
.anchor | ||
.DS_Store | ||
target | ||
**/*.rs.bk | ||
node_modules | ||
test-ledger | ||
.yarn | ||
.env |
8 changes: 8 additions & 0 deletions
8
basics/favorites/anchor/favorites/anchor/favorites/.prettierignore
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,8 @@ | ||
|
||
.anchor | ||
.DS_Store | ||
target | ||
node_modules | ||
dist | ||
build | ||
test-ledger |
18 changes: 18 additions & 0 deletions
18
basics/favorites/anchor/favorites/anchor/favorites/Anchor.toml
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,18 @@ | ||
[toolchain] | ||
|
||
[features] | ||
resolution = true | ||
skip-lint = false | ||
|
||
[programs.localnet] | ||
favorites = "ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV" | ||
|
||
[registry] | ||
url = "https://api.apr.dev" | ||
|
||
[provider] | ||
cluster = "Localnet" | ||
wallet = "~/.config/solana/id.json" | ||
|
||
[scripts] | ||
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" |
15 changes: 15 additions & 0 deletions
15
basics/favorites/anchor/favorites/anchor/favorites/Cargo.toml
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,15 @@ | ||
[workspace] | ||
members = [ | ||
"programs/*" | ||
] | ||
resolver = "2" | ||
|
||
[profile.release] | ||
overflow-checks = true | ||
lto = "fat" | ||
codegen-units = 1 | ||
|
||
[profile.release.build-override] | ||
opt-level = 3 | ||
incremental = false | ||
codegen-units = 1 |
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,9 @@ | ||
# Favorites | ||
|
||
This is a basic Anchor app using PDAs to store data for a user, and Anchor's account checks to ensure each user is only allowed to modify their own data. | ||
|
||
It's used by the [https://github.com/solana-developers/professional-education](Solana Professional Education) course. | ||
|
||
## Usage | ||
|
||
`anchor test`, `anchor deploy` etc. |
12 changes: 12 additions & 0 deletions
12
basics/favorites/anchor/favorites/anchor/favorites/migrations/deploy.ts
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,12 @@ | ||
// Migrations are an early feature. Currently, they're nothing more than this | ||
// single deploy script that's invoked from the CLI, injecting a provider | ||
// configured from the workspace's Anchor.toml. | ||
|
||
const anchor = require('@coral-xyz/anchor'); | ||
|
||
module.exports = async (provider) => { | ||
// Configure client to use the provider. | ||
anchor.setProvider(provider); | ||
|
||
// Add your deploy script here. | ||
}; |
21 changes: 21 additions & 0 deletions
21
basics/favorites/anchor/favorites/anchor/favorites/package.json
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,21 @@ | ||
{ | ||
"scripts": { | ||
"lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", | ||
"lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" | ||
}, | ||
"dependencies": { | ||
"@coral-xyz/anchor": "^0.30.0", | ||
"@solana-developers/helpers": "^2.0.0" | ||
}, | ||
"license": "UNLICENSED", | ||
"devDependencies": { | ||
"@types/bn.js": "^5.1.0", | ||
"@types/chai": "^4.3.0", | ||
"@types/mocha": "^9.0.0", | ||
"chai": "^4.3.4", | ||
"mocha": "^9.0.3", | ||
"prettier": "^2.6.2", | ||
"ts-mocha": "^10.0.0", | ||
"typescript": "^4.3.5" | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
basics/favorites/anchor/favorites/anchor/favorites/programs/favorites/Cargo.toml
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,21 @@ | ||
[package] | ||
name = "favorites" | ||
version = "0.1.0" | ||
description = "Created with Anchor" | ||
edition = "2021" | ||
|
||
[lib] | ||
crate-type = ["cdylib", "lib"] | ||
name = "favorites" | ||
|
||
[features] | ||
no-entrypoint = [] | ||
no-idl = [] | ||
no-log-ix-name = [] | ||
cpi = ["no-entrypoint"] | ||
default = [] | ||
idl-build = ["anchor-lang/idl-build"] | ||
|
||
[dependencies] | ||
anchor-lang = {version = "0.30.0", features = ["init-if-needed"]} | ||
solana-program = "=1.18.5" |
2 changes: 2 additions & 0 deletions
2
basics/favorites/anchor/favorites/anchor/favorites/programs/favorites/Xargo.toml
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,2 @@ | ||
[target.bpfel-unknown-unknown.dependencies.std] | ||
features = [] |
65 changes: 65 additions & 0 deletions
65
basics/favorites/anchor/favorites/anchor/favorites/programs/favorites/src/lib.rs
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,65 @@ | ||
use anchor_lang::prelude::*; | ||
// Our program's address! | ||
// This matches the key in the target/deploy directory | ||
declare_id!("ww9C83noARSQVBnqmCUmaVdbJjmiwcV9j2LkXYMoUCV"); | ||
|
||
// Anchor programs always use 8 bits for the discriminator | ||
pub const ANCHOR_DISCRIMINATOR_SIZE: usize = 8; | ||
|
||
// Our Solana program! | ||
#[program] | ||
pub mod favorites { | ||
use super::*; | ||
|
||
// Our instruction handler! It sets the user's favorite number and color | ||
pub fn set_favorites(context: Context<SetFavorites>, number: u64, color: String, hobbies: Vec<String>) -> Result<()> { | ||
let user_public_key = context.accounts.user.key(); | ||
msg!("Greetings from {}", context.program_id); | ||
msg!( | ||
"User {user_public_key}'s favorite number is {number}, favorite color is: {color}", | ||
); | ||
|
||
msg!( | ||
"User's hobbies are: {:?}", | ||
hobbies | ||
); | ||
|
||
context.accounts.favorites.set_inner(Favorites { | ||
number, | ||
color, | ||
hobbies | ||
}); | ||
Ok(()) | ||
} | ||
|
||
// We can also add a get_favorites instruction handler to return the user's favorite number and color | ||
} | ||
|
||
// What we will put inside the Favorites PDA | ||
#[account] | ||
#[derive(InitSpace)] | ||
pub struct Favorites { | ||
pub number: u64, | ||
|
||
#[max_len(50)] | ||
pub color: String, | ||
|
||
#[max_len(5, 50)] | ||
pub hobbies: Vec<String> | ||
} | ||
// When people call the set_favorites instruction, they will need to provide the accounts that will be modifed. This keeps Solana fast! | ||
#[derive(Accounts)] | ||
pub struct SetFavorites<'info> { | ||
#[account(mut)] | ||
pub user: Signer<'info>, | ||
|
||
#[account( | ||
init_if_needed, | ||
payer = user, | ||
space = ANCHOR_DISCRIMINATOR_SIZE + Favorites::INIT_SPACE, | ||
seeds=[b"favorites", user.key().as_ref()], | ||
bump)] | ||
pub favorites: Account<'info, Favorites>, | ||
|
||
pub system_program: Program<'info, System>, | ||
} |
77 changes: 77 additions & 0 deletions
77
basics/favorites/anchor/favorites/anchor/favorites/tests/favorites.ts
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,77 @@ | ||
import * as anchor from '@coral-xyz/anchor'; | ||
import type { Program } from '@coral-xyz/anchor'; | ||
import { getCustomErrorMessage } from '@solana-developers/helpers'; | ||
import { assert } from 'chai'; | ||
import type { Favorites } from '../target/types/favorites'; | ||
import { systemProgramErrors } from './system-errors'; | ||
const web3 = anchor.web3; | ||
|
||
describe('Favorites', () => { | ||
// Use the cluster and the keypair from Anchor.toml | ||
const provider = anchor.AnchorProvider.env(); | ||
anchor.setProvider(provider); | ||
const user = (provider.wallet as anchor.Wallet).payer; | ||
const someRandomGuy = anchor.web3.Keypair.generate(); | ||
const program = anchor.workspace.Favorites as Program<Favorites>; | ||
|
||
// Here's what we want to write to the blockchain | ||
const favoriteNumber = new anchor.BN(23); | ||
const favoriteColor = 'purple'; | ||
const favoriteHobbies = ['skiing', 'skydiving', 'biking']; | ||
|
||
// We don't need to airdrop if we're using the local cluster | ||
// because the local cluster gives us 85 billion dollars worth of SOL | ||
before(async () => { | ||
const balance = await provider.connection.getBalance(user.publicKey); | ||
const balanceInSOL = balance / web3.LAMPORTS_PER_SOL; | ||
const formattedBalance = new Intl.NumberFormat().format(balanceInSOL); | ||
console.log(`Balance: ${formattedBalance} SOL`); | ||
}); | ||
|
||
it('Writes our favorites to the blockchain', async () => { | ||
await program.methods | ||
// set_favourites in Rust becomes setFavorites in TypeScript | ||
.setFavorites(favoriteNumber, favoriteColor, favoriteHobbies) | ||
// Sign the transaction | ||
.signers([user]) | ||
// Send the transaction to the cluster or RPC | ||
.rpc(); | ||
|
||
// Find the PDA for the user's favorites | ||
const favoritesPdaAndBump = web3.PublicKey.findProgramAddressSync([Buffer.from('favorites'), user.publicKey.toBuffer()], program.programId); | ||
const favoritesPda = favoritesPdaAndBump[0]; | ||
const dataFromPda = await program.account.favorites.fetch(favoritesPda); | ||
// And make sure it matches! | ||
assert.equal(dataFromPda.color, favoriteColor); | ||
// A little extra work to make sure the BNs are equal | ||
assert.equal(dataFromPda.number.toString(), favoriteNumber.toString()); | ||
// And check the hobbies too | ||
assert.deepEqual(dataFromPda.hobbies, favoriteHobbies); | ||
}); | ||
|
||
it('Updates the favorites', async () => { | ||
const newFavoriteHobbies = ['skiing', 'skydiving', 'biking', 'swimming']; | ||
try { | ||
await program.methods.setFavorites(favoriteNumber, favoriteColor, newFavoriteHobbies).signers([user]).rpc(); | ||
} catch (error) { | ||
console.error((error as Error).message); | ||
const customErrorMessage = getCustomErrorMessage(systemProgramErrors, error); | ||
throw new Error(customErrorMessage); | ||
} | ||
}); | ||
|
||
it('Rejects transactions from unauthorized signers', async () => { | ||
try { | ||
await program.methods | ||
// set_favourites in Rust becomes setFavorites in TypeScript | ||
.setFavorites(favoriteNumber, favoriteColor, favoriteHobbies) | ||
// Sign the transaction | ||
.signers([someRandomGuy]) | ||
// Send the transaction to the cluster or RPC | ||
.rpc(); | ||
} catch (error) { | ||
const errorMessage = (error as Error).message; | ||
assert.isTrue(errorMessage.includes('unknown signer')); | ||
} | ||
}); | ||
}); |
20 changes: 20 additions & 0 deletions
20
basics/favorites/anchor/favorites/anchor/favorites/tests/system-errors.ts
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,20 @@ | ||
// From https://github.com/solana-labs/solana/blob/a94920a4eadf1008fc292e47e041c1b3b0d949df/sdk/program/src/system_instruction.rs | ||
export const systemProgramErrors = [ | ||
'an account with the same address already exists', | ||
|
||
'account does not have enough SOL to perform the operation', | ||
|
||
'cannot assign account to this program id', | ||
|
||
'cannot allocate account data of this length', | ||
|
||
'length of requested seed is too long', | ||
|
||
'provided address does not match addressed derived from seed', | ||
|
||
'advancing stored nonce requires a populated RecentBlockhashes sysvar', | ||
|
||
'stored nonce is still in recent_blockhashes', | ||
|
||
'specified nonce does not match stored nonce', | ||
]; |
10 changes: 10 additions & 0 deletions
10
basics/favorites/anchor/favorites/anchor/favorites/tsconfig.json
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,10 @@ | ||
{ | ||
"compilerOptions": { | ||
"types": ["mocha", "chai"], | ||
"typeRoots": ["./node_modules/@types"], | ||
"lib": ["es2015"], | ||
"module": "commonjs", | ||
"target": "es6", | ||
"esModuleInterop": true | ||
} | ||
} |
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,7 @@ | ||
.anchor | ||
.DS_Store | ||
target | ||
**/*.rs.bk | ||
node_modules | ||
test-ledger | ||
.yarn |
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,7 @@ | ||
.anchor | ||
.DS_Store | ||
target | ||
node_modules | ||
dist | ||
build | ||
test-ledger |
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,18 @@ | ||
[toolchain] | ||
|
||
[features] | ||
resolution = true | ||
skip-lint = false | ||
|
||
[programs.localnet] | ||
escrow = "qbuMdeYxYJXBjU6C6qFKjZKjXmrU83eDQomHdrch826" | ||
|
||
[registry] | ||
url = "https://api.apr.dev" | ||
|
||
[provider] | ||
cluster = "Localnet" | ||
wallet = "~/.config/solana/id.json" | ||
|
||
[scripts] | ||
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" |
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,15 @@ | ||
[workspace] | ||
members = [ | ||
"programs/*" | ||
] | ||
resolver = "2" | ||
|
||
[profile.release] | ||
overflow-checks = true | ||
lto = "fat" | ||
codegen-units = 1 | ||
|
||
[profile.release.build-override] | ||
opt-level = 3 | ||
incremental = false | ||
codegen-units = 1 |
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,48 @@ | ||
# Anchor Escrow | ||
|
||
## Introduction | ||
|
||
This Solana program is called an **_escrow_** - it allows a user to swap a specific amount of one token for a desired amount of another token. | ||
|
||
For example, Alice is offering 10 USDC, and wants 100 WIF in return. | ||
|
||
Without our program, users would have to engage in manual token swapping. Imagine the potential problems if Bob promised to send Alice 100 WIF, but instead took the 10 USDC and ran? Or what if Alice was dishonest, received the 10 USDC from Bob, and decided not to send the 100 WIF? Our Escrow program handles these complexities by acting a trusted entity that will only release tokens to both parties at the right time. | ||
|
||
Our Escrow program is designed to provide a secure environment for users to swap a specific amount of one token with a specific amount of another token without having to trust each other. | ||
|
||
Better yet, since our program allows Alice and Bob to transact directly with each other, they both get a hundred percent of the token they desire! | ||
|
||
## Usage | ||
|
||
`anchor test`, `anchor deploy` etc. | ||
|
||
## Credit | ||
|
||
This project is based on [Dean Little's Anchor Escrow,](https://github.com/deanmlittle/anchor-escrow-2024) with a few changes to make discussion in class easier. | ||
|
||
### Changes from original | ||
|
||
One of the challenges when teaching is avoiding ambiguity — names have to be carefully chosen to be clear and not possible to confuse with other times. | ||
|
||
- Custom instructions were replaced by `@solana-developers/helpers` for many tasks to reduce the file size. | ||
- The upstream project has a custom file layout. We use the 'multiple files' Anchor layout. | ||
- Contexts are separate data structures from functions that use the contexts. There is no need for OO-like `impl` patterns here - there's no mutable state stored in the Context, and the 'methods' do not mutate that state. Besides, it's easier to type! | ||
- The name 'deposit' was being used in multiple contexts, and `deposit` can be tough because it's a verb and a noun: | ||
|
||
- Renamed deposit #1 -> 'token_a_offered_amount' | ||
- Renamed deposit #2 (in make() ) -> 'send_offered_tokens_to_vault' | ||
- Renamed deposit #3 (in take() ) -> 'send_wanted_tokens_to_maker' | ||
|
||
- 'seed' was renamed to 'id' because 'seed' as it conflicted with the 'seeds' used for PDA address generation. | ||
- 'Escrow' was used for the program's name and the account that records details of the offer. This wasn't great because people would confuse 'Escrow' with the 'Vault'. | ||
|
||
- Escrow (the program) -> remains Escrow | ||
- Escrow (the offer) -> Offer. | ||
|
||
- 'receive' was renamed to 'token_b_wanted_amount' as 'receive' is a verb and not a suitable name for an integer. | ||
- mint_a -> token_mint_a (ie, what the maker has offered and what the taker wants) | ||
- mint_b -> token_mint_b (ie, what that maker wants and what the taker must offer) | ||
- makerAtaA -> makerTokenAccountA, | ||
- makerAtaB -> makerTokenAccountB | ||
- takerAtaA -> takerTokenAccountA | ||
- takerAtaB -> takerTokenAccountB |
Oops, something went wrong.