Browse Source

Merge pull request #29 from valentinmadrid/main

Joe C 2 years ago
parent
commit
4f692f6c86
48 changed files with 2843 additions and 0 deletions
  1. 7 0
      basics/transfer-sol/seahorse/.gitignore
  2. 8 0
      basics/transfer-sol/seahorse/.prettierignore
  3. 15 0
      basics/transfer-sol/seahorse/Anchor.toml
  4. 13 0
      basics/transfer-sol/seahorse/Cargo.toml
  5. 3 0
      basics/transfer-sol/seahorse/README.md
  6. 12 0
      basics/transfer-sol/seahorse/migrations/deploy.ts
  7. 19 0
      basics/transfer-sol/seahorse/package.json
  8. 21 0
      basics/transfer-sol/seahorse/programs/seahorse/Cargo.toml
  9. 2 0
      basics/transfer-sol/seahorse/programs/seahorse/Xargo.toml
  10. 1 0
      basics/transfer-sol/seahorse/programs/seahorse/src/dot/mod.rs
  11. 74 0
      basics/transfer-sol/seahorse/programs/seahorse/src/dot/program.rs
  12. 239 0
      basics/transfer-sol/seahorse/programs/seahorse/src/lib.rs
  13. 26 0
      basics/transfer-sol/seahorse/programs_py/seahorse.py
  14. 0 0
      basics/transfer-sol/seahorse/programs_py/seahorse/__init__.py
  15. 1062 0
      basics/transfer-sol/seahorse/programs_py/seahorse/prelude.py
  16. 38 0
      basics/transfer-sol/seahorse/tests/seahorse.ts
  17. 11 0
      basics/transfer-sol/seahorse/tsconfig.json
  18. 8 0
      tokens/token-2022/default-account-state/native/README.md
  19. 8 0
      tokens/token-2022/default-account-state/native/cicd.sh
  20. 22 0
      tokens/token-2022/default-account-state/native/package.json
  21. 14 0
      tokens/token-2022/default-account-state/native/program/Cargo.toml
  22. 130 0
      tokens/token-2022/default-account-state/native/program/src/lib.rs
  23. 86 0
      tokens/token-2022/default-account-state/native/tests/test.ts
  24. 10 0
      tokens/token-2022/default-account-state/native/tsconfig.json
  25. 8 0
      tokens/token-2022/mint-close-authority/native/cicd.sh
  26. 22 0
      tokens/token-2022/mint-close-authority/native/package.json
  27. 14 0
      tokens/token-2022/mint-close-authority/native/program/Cargo.toml
  28. 103 0
      tokens/token-2022/mint-close-authority/native/program/src/lib.rs
  29. 87 0
      tokens/token-2022/mint-close-authority/native/tests/test.ts
  30. 10 0
      tokens/token-2022/mint-close-authority/native/tsconfig.json
  31. 8 0
      tokens/token-2022/multiple-extensions/native/cicd.sh
  32. 22 0
      tokens/token-2022/multiple-extensions/native/package.json
  33. 14 0
      tokens/token-2022/multiple-extensions/native/program/Cargo.toml
  34. 117 0
      tokens/token-2022/multiple-extensions/native/program/src/lib.rs
  35. 87 0
      tokens/token-2022/multiple-extensions/native/tests/test.ts
  36. 10 0
      tokens/token-2022/multiple-extensions/native/tsconfig.json
  37. 8 0
      tokens/token-2022/non-transferable/native/cicd.sh
  38. 22 0
      tokens/token-2022/non-transferable/native/package.json
  39. 14 0
      tokens/token-2022/non-transferable/native/program/Cargo.toml
  40. 97 0
      tokens/token-2022/non-transferable/native/program/src/lib.rs
  41. 86 0
      tokens/token-2022/non-transferable/native/tests/test.ts
  42. 10 0
      tokens/token-2022/non-transferable/native/tsconfig.json
  43. 8 0
      tokens/token-2022/transfer-fees/native/cicd.sh
  44. 22 0
      tokens/token-2022/transfer-fees/native/package.json
  45. 14 0
      tokens/token-2022/transfer-fees/native/program/Cargo.toml
  46. 135 0
      tokens/token-2022/transfer-fees/native/program/src/lib.rs
  47. 86 0
      tokens/token-2022/transfer-fees/native/tests/test.ts
  48. 10 0
      tokens/token-2022/transfer-fees/native/tsconfig.json

+ 7 - 0
basics/transfer-sol/seahorse/.gitignore

@@ -0,0 +1,7 @@
+
+.anchor
+.DS_Store
+target
+**/*.rs.bk
+node_modules
+test-ledger

+ 8 - 0
basics/transfer-sol/seahorse/.prettierignore

@@ -0,0 +1,8 @@
+
+.anchor
+.DS_Store
+target
+node_modules
+dist
+build
+test-ledger

+ 15 - 0
basics/transfer-sol/seahorse/Anchor.toml

@@ -0,0 +1,15 @@
+[features]
+seeds = true
+skip-lint = false
+[programs.localnet]
+seahorse = "Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS"
+
+[registry]
+url = "https://api.apr.dev"
+
+[provider]
+cluster = "Localnet"
+wallet = "/Users/devenv/.config/solana/id.json"
+
+[scripts]
+test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

+ 13 - 0
basics/transfer-sol/seahorse/Cargo.toml

@@ -0,0 +1,13 @@
+[workspace]
+members = [
+    "programs/*"
+]
+
+[profile.release]
+overflow-checks = true
+lto = "fat"
+codegen-units = 1
+[profile.release.build-override]
+opt-level = 3
+incremental = false
+codegen-units = 1

+ 3 - 0
basics/transfer-sol/seahorse/README.md

@@ -0,0 +1,3 @@
+## Transfer SOL with Seahorse
+
+Sadly, you can't send SOL(lamports) to another SystemAccount (Public Key) with Seahorse. That's why this Seahorse example looks a little different than the Anchor and Native ones. Here, we initialize a Mock PDA account where we send SOL to using transferLamports, which invokes a CPI with the System Program.

+ 12 - 0
basics/transfer-sol/seahorse/migrations/deploy.ts

@@ -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 function (provider) {
+  // Configure client to use the provider.
+  anchor.setProvider(provider);
+
+  // Add your deploy script here.
+};

+ 19 - 0
basics/transfer-sol/seahorse/package.json

@@ -0,0 +1,19 @@
+{
+    "scripts": {
+        "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w",
+        "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check"
+    },
+    "dependencies": {
+        "@coral-xyz/anchor": "^0.27.0"
+    },
+    "devDependencies": {
+        "chai": "^4.3.4",
+        "mocha": "^9.0.3",
+        "ts-mocha": "^10.0.0",
+        "@types/bn.js": "^5.1.0",
+        "@types/chai": "^4.3.0",
+        "@types/mocha": "^9.0.0",
+        "typescript": "^4.3.5",
+        "prettier": "^2.6.2"
+    }
+}

+ 21 - 0
basics/transfer-sol/seahorse/programs/seahorse/Cargo.toml

@@ -0,0 +1,21 @@
+[package]
+name = "seahorse"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "seahorse"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-lang = "0.27.0"
+anchor-spl = "0.27.0"
+pyth-sdk-solana = { version = "0.7.1", optional = true }

+ 2 - 0
basics/transfer-sol/seahorse/programs/seahorse/Xargo.toml

@@ -0,0 +1,2 @@
+[target.bpfel-unknown-unknown.dependencies.std]
+features = []

+ 1 - 0
basics/transfer-sol/seahorse/programs/seahorse/src/dot/mod.rs

@@ -0,0 +1 @@
+pub mod program;

+ 74 - 0
basics/transfer-sol/seahorse/programs/seahorse/src/dot/program.rs

@@ -0,0 +1,74 @@
+#![allow(unused_imports)]
+#![allow(unused_variables)]
+#![allow(unused_mut)]
+use crate::{id, seahorse_util::*};
+use anchor_lang::{prelude::*, solana_program};
+use anchor_spl::token::{self, Mint, Token, TokenAccount};
+use std::{cell::RefCell, rc::Rc};
+
+#[account]
+#[derive(Debug)]
+pub struct MockAccount {
+    pub mock_value: u8,
+}
+
+impl<'info, 'entrypoint> MockAccount {
+    pub fn load(
+        account: &'entrypoint mut Box<Account<'info, Self>>,
+        programs_map: &'entrypoint ProgramsMap<'info>,
+    ) -> Mutable<LoadedMockAccount<'info, 'entrypoint>> {
+        let mock_value = account.mock_value;
+
+        Mutable::new(LoadedMockAccount {
+            __account__: account,
+            __programs__: programs_map,
+            mock_value,
+        })
+    }
+
+    pub fn store(loaded: Mutable<LoadedMockAccount>) {
+        let mut loaded = loaded.borrow_mut();
+        let mock_value = loaded.mock_value;
+
+        loaded.__account__.mock_value = mock_value;
+    }
+}
+
+#[derive(Debug)]
+pub struct LoadedMockAccount<'info, 'entrypoint> {
+    pub __account__: &'entrypoint mut Box<Account<'info, MockAccount>>,
+    pub __programs__: &'entrypoint ProgramsMap<'info>,
+    pub mock_value: u8,
+}
+
+pub fn init_mock_account_handler<'info>(
+    mut signer: SeahorseSigner<'info, '_>,
+    mut mock_account: Empty<Mutable<LoadedMockAccount<'info, '_>>>,
+) -> () {
+    let mut account = mock_account.account.clone();
+
+    assign!(
+        account.borrow_mut().mock_value,
+        <u8 as TryFrom<_>>::try_from(0).unwrap()
+    );
+}
+
+pub fn transfer_sol_with_cpi_handler<'info>(
+    mut sender: SeahorseSigner<'info, '_>,
+    mut recipient: Mutable<LoadedMockAccount<'info, '_>>,
+    mut amount: u64,
+) -> () {
+    solana_program::program::invoke(
+        &solana_program::system_instruction::transfer(
+            &sender.key(),
+            &recipient.borrow().__account__.key(),
+            amount.clone(),
+        ),
+        &[
+            sender.to_account_info(),
+            recipient.borrow().__account__.to_account_info(),
+            sender.programs.get("system_program").clone(),
+        ],
+    )
+    .unwrap();
+}

+ 239 - 0
basics/transfer-sol/seahorse/programs/seahorse/src/lib.rs

@@ -0,0 +1,239 @@
+#![allow(unused_imports)]
+#![allow(unused_variables)]
+#![allow(unused_mut)]
+
+pub mod dot;
+
+use anchor_lang::prelude::*;
+use anchor_spl::{
+    associated_token::{self, AssociatedToken},
+    token::{self, Mint, Token, TokenAccount},
+};
+
+use dot::program::*;
+use std::{cell::RefCell, rc::Rc};
+
+declare_id!("2RjL4mpTANyGxz7fLWEbQtmdEDti7c4CqsLR96mgvcaV");
+
+pub mod seahorse_util {
+    use super::*;
+
+    #[cfg(feature = "pyth-sdk-solana")]
+    pub use pyth_sdk_solana::{load_price_feed_from_account_info, PriceFeed};
+    use std::{collections::HashMap, fmt::Debug, ops::Deref};
+
+    pub struct Mutable<T>(Rc<RefCell<T>>);
+
+    impl<T> Mutable<T> {
+        pub fn new(obj: T) -> Self {
+            Self(Rc::new(RefCell::new(obj)))
+        }
+    }
+
+    impl<T> Clone for Mutable<T> {
+        fn clone(&self) -> Self {
+            Self(self.0.clone())
+        }
+    }
+
+    impl<T> Deref for Mutable<T> {
+        type Target = Rc<RefCell<T>>;
+
+        fn deref(&self) -> &Self::Target {
+            &self.0
+        }
+    }
+
+    impl<T: Debug> Debug for Mutable<T> {
+        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+            write!(f, "{:?}", self.0)
+        }
+    }
+
+    impl<T: Default> Default for Mutable<T> {
+        fn default() -> Self {
+            Self::new(T::default())
+        }
+    }
+
+    impl<T: Clone> Mutable<Vec<T>> {
+        pub fn wrapped_index(&self, mut index: i128) -> usize {
+            if index >= 0 {
+                return index.try_into().unwrap();
+            }
+
+            index += self.borrow().len() as i128;
+
+            return index.try_into().unwrap();
+        }
+    }
+
+    impl<T: Clone, const N: usize> Mutable<[T; N]> {
+        pub fn wrapped_index(&self, mut index: i128) -> usize {
+            if index >= 0 {
+                return index.try_into().unwrap();
+            }
+
+            index += self.borrow().len() as i128;
+
+            return index.try_into().unwrap();
+        }
+    }
+
+    #[derive(Clone)]
+    pub struct Empty<T: Clone> {
+        pub account: T,
+        pub bump: Option<u8>,
+    }
+
+    #[derive(Clone, Debug)]
+    pub struct ProgramsMap<'info>(pub HashMap<&'static str, AccountInfo<'info>>);
+
+    impl<'info> ProgramsMap<'info> {
+        pub fn get(&self, name: &'static str) -> AccountInfo<'info> {
+            self.0.get(name).unwrap().clone()
+        }
+    }
+
+    #[derive(Clone, Debug)]
+    pub struct WithPrograms<'info, 'entrypoint, A> {
+        pub account: &'entrypoint A,
+        pub programs: &'entrypoint ProgramsMap<'info>,
+    }
+
+    impl<'info, 'entrypoint, A> Deref for WithPrograms<'info, 'entrypoint, A> {
+        type Target = A;
+
+        fn deref(&self) -> &Self::Target {
+            &self.account
+        }
+    }
+
+    pub type SeahorseAccount<'info, 'entrypoint, A> =
+        WithPrograms<'info, 'entrypoint, Box<Account<'info, A>>>;
+
+    pub type SeahorseSigner<'info, 'entrypoint> = WithPrograms<'info, 'entrypoint, Signer<'info>>;
+
+    #[derive(Clone, Debug)]
+    pub struct CpiAccount<'info> {
+        #[doc = "CHECK: CpiAccounts temporarily store AccountInfos."]
+        pub account_info: AccountInfo<'info>,
+        pub is_writable: bool,
+        pub is_signer: bool,
+        pub seeds: Option<Vec<Vec<u8>>>,
+    }
+
+    #[macro_export]
+    macro_rules! seahorse_const {
+        ($ name : ident , $ value : expr) => {
+            macro_rules! $name {
+                () => {
+                    $value
+                };
+            }
+
+            pub(crate) use $name;
+        };
+    }
+
+    #[macro_export]
+    macro_rules! assign {
+        ($ lval : expr , $ rval : expr) => {{
+            let temp = $rval;
+
+            $lval = temp;
+        }};
+    }
+
+    #[macro_export]
+    macro_rules! index_assign {
+        ($ lval : expr , $ idx : expr , $ rval : expr) => {
+            let temp_rval = $rval;
+            let temp_idx = $idx;
+
+            $lval[temp_idx] = temp_rval;
+        };
+    }
+
+    pub(crate) use assign;
+
+    pub(crate) use index_assign;
+
+    pub(crate) use seahorse_const;
+}
+
+#[program]
+mod seahorse {
+    use super::*;
+    use seahorse_util::*;
+    use std::collections::HashMap;
+
+    #[derive(Accounts)]
+    pub struct InitMockAccount<'info> {
+        #[account(mut)]
+        pub signer: Signer<'info>,
+        # [account (init , space = std :: mem :: size_of :: < dot :: program :: MockAccount > () + 8 , payer = signer , seeds = ["mock_account" . as_bytes () . as_ref ()] , bump)]
+        pub mock_account: Box<Account<'info, dot::program::MockAccount>>,
+        pub rent: Sysvar<'info, Rent>,
+        pub system_program: Program<'info, System>,
+    }
+
+    pub fn init_mock_account(ctx: Context<InitMockAccount>) -> Result<()> {
+        let mut programs = HashMap::new();
+
+        programs.insert(
+            "system_program",
+            ctx.accounts.system_program.to_account_info(),
+        );
+
+        let programs_map = ProgramsMap(programs);
+        let signer = SeahorseSigner {
+            account: &ctx.accounts.signer,
+            programs: &programs_map,
+        };
+
+        let mock_account = Empty {
+            account: dot::program::MockAccount::load(&mut ctx.accounts.mock_account, &programs_map),
+            bump: ctx.bumps.get("mock_account").map(|bump| *bump),
+        };
+
+        init_mock_account_handler(signer.clone(), mock_account.clone());
+
+        dot::program::MockAccount::store(mock_account.account);
+
+        return Ok(());
+    }
+
+    #[derive(Accounts)]
+    # [instruction (amount : u64)]
+    pub struct TransferSolWithCpi<'info> {
+        #[account(mut)]
+        pub sender: Signer<'info>,
+        #[account(mut)]
+        pub recipient: Box<Account<'info, dot::program::MockAccount>>,
+        pub system_program: Program<'info, System>,
+    }
+
+    pub fn transfer_sol_with_cpi(ctx: Context<TransferSolWithCpi>, amount: u64) -> Result<()> {
+        let mut programs = HashMap::new();
+
+        programs.insert(
+            "system_program",
+            ctx.accounts.system_program.to_account_info(),
+        );
+
+        let programs_map = ProgramsMap(programs);
+        let sender = SeahorseSigner {
+            account: &ctx.accounts.sender,
+            programs: &programs_map,
+        };
+
+        let recipient = dot::program::MockAccount::load(&mut ctx.accounts.recipient, &programs_map);
+
+        transfer_sol_with_cpi_handler(sender.clone(), recipient.clone(), amount);
+
+        dot::program::MockAccount::store(recipient);
+
+        return Ok(());
+    }
+}

+ 26 - 0
basics/transfer-sol/seahorse/programs_py/seahorse.py

@@ -0,0 +1,26 @@
+# seahorse
+# Built with Seahorse v0.2.7
+
+from seahorse.prelude import *
+
+declare_id('2RjL4mpTANyGxz7fLWEbQtmdEDti7c4CqsLR96mgvcaV')
+
+class MockAccount(Account):
+    mock_value: u8
+
+
+## We don't care about this instruction, but we need an address to send our SOL to.
+@instruction
+def init_mock_account(signer: Signer, mock_account: Empty[MockAccount]):
+    account = mock_account.init(
+        payer = signer,
+        seeds = ['mock_account'],
+    )
+    account.mock_value = u8(0)
+
+@instruction
+def transfer_sol_with_cpi(sender: Signer, recipient: MockAccount, amount: u64):
+    sender.transfer_lamports(
+        to = recipient,
+        amount = amount,
+    )

+ 0 - 0
basics/transfer-sol/seahorse/programs_py/seahorse/__init__.py


+ 1062 - 0
basics/transfer-sol/seahorse/programs_py/seahorse/prelude.py

@@ -0,0 +1,1062 @@
+# seahorse.prelude: the basis for writing Seahorse programs.
+#
+# NOTE: this file just contains types and documentation for your editor. This
+# is NOT executable code, and you won't be able to change the behavior of your
+# Seahorse programs by editing this file.
+
+from typing import *
+from math import floor, ceil
+
+T = TypeVar('T')
+N = TypeVar('N')
+
+
+# ==========
+# Rust types
+# ==========
+
+class u8:
+    """8-bit unsigned integer."""
+
+    def __init__(self, _: Any) -> 'u8':
+        """Construct an u8."""
+
+    def __add__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __radd__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __iadd__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __sub__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __rsub__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __isub__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __mul__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __rmul__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __imul__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __rfloordiv__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __ifloordiv__(self, other: 'u8') -> 'u8':
+        pass
+
+    def __lt__(self, other: 'u8') -> bool:
+        pass
+
+    def __le__(self, other: 'u8') -> bool:
+        pass
+
+    def __eq__(self, other: 'u8') -> bool:
+        pass
+
+    def __ne__(self, other: 'u8') -> bool:
+        pass
+
+    def __ge__(self, other: 'u8') -> bool:
+        pass
+
+    def __gt__(self, other: 'u8') -> bool:
+        pass
+
+
+class u16:
+    """16-bit unsigned integer."""
+
+    def __init__(self, _: Any) -> 'u16':
+        """Construct an u16."""
+
+    def __add__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __radd__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __iadd__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __sub__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __rsub__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __isub__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __mul__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __rmul__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __imul__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __rfloordiv__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __ifloordiv__(self, other: 'u16') -> 'u16':
+        pass
+
+    def __lt__(self, other: 'u16') -> bool:
+        pass
+
+    def __le__(self, other: 'u16') -> bool:
+        pass
+
+    def __eq__(self, other: 'u16') -> bool:
+        pass
+
+    def __ne__(self, other: 'u16') -> bool:
+        pass
+
+    def __ge__(self, other: 'u16') -> bool:
+        pass
+
+    def __gt__(self, other: 'u16') -> bool:
+        pass
+
+class u32:
+    """32-bit unsigned integer."""
+
+    def __init__(self, _: Any) -> 'u32':
+        """Construct an u32."""
+
+    def __add__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __radd__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __iadd__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __sub__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __rsub__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __isub__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __mul__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __rmul__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __imul__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __rfloordiv__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __ifloordiv__(self, other: 'u32') -> 'u32':
+        pass
+
+    def __lt__(self, other: 'u32') -> bool:
+        pass
+
+    def __le__(self, other: 'u32') -> bool:
+        pass
+
+    def __eq__(self, other: 'u32') -> bool:
+        pass
+
+    def __ne__(self, other: 'u32') -> bool:
+        pass
+
+    def __ge__(self, other: 'u32') -> bool:
+        pass
+
+    def __gt__(self, other: 'u32') -> bool:
+        pass
+
+class u64:
+    """64-bit unsigned integer."""
+
+    def __init__(self, _: Any) -> 'u64':
+        """Construct an u64."""
+
+    def __add__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __radd__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __iadd__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __sub__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __rsub__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __isub__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __mul__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __rmul__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __imul__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __rfloordiv__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __ifloordiv__(self, other: 'u64') -> 'u64':
+        pass
+
+    def __lt__(self, other: 'u64') -> bool:
+        pass
+
+    def __le__(self, other: 'u64') -> bool:
+        pass
+
+    def __eq__(self, other: 'u64') -> bool:
+        pass
+
+    def __ne__(self, other: 'u64') -> bool:
+        pass
+
+    def __ge__(self, other: 'u64') -> bool:
+        pass
+
+    def __gt__(self, other: 'u64') -> bool:
+        pass
+
+class u128:
+    """128-bit unsigned integer."""
+
+    def __init__(self, _: Any) -> 'u128':
+        """Construct an u128."""
+
+    def __add__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __radd__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __iadd__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __sub__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __rsub__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __isub__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __mul__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __rmul__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __imul__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __rfloordiv__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __ifloordiv__(self, other: 'u128') -> 'u128':
+        pass
+
+    def __lt__(self, other: 'u128') -> bool:
+        pass
+
+    def __le__(self, other: 'u128') -> bool:
+        pass
+
+    def __eq__(self, other: 'u128') -> bool:
+        pass
+
+    def __ne__(self, other: 'u128') -> bool:
+        pass
+
+    def __ge__(self, other: 'u128') -> bool:
+        pass
+
+    def __gt__(self, other: 'u128') -> bool:
+        pass
+
+class i8:
+    """8-bit signed integer."""
+
+    def __init__(self, _: Any) -> 'i8':
+        """Construct an i8."""
+
+    def __add__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __radd__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __iadd__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __sub__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __rsub__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __isub__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __mul__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __rmul__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __imul__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __rfloordiv__(self, other: 'i8') -> 'i8':
+        pass
+
+    def __ifloordiv__(self, other: 'i8') -> 'i8':
+        pass
+
+class i16:
+    """16-bit signed integer."""
+
+    def __init__(self, _: Any) -> 'i16':
+        """Construct an i16."""
+
+    def __add__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __radd__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __iadd__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __sub__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __rsub__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __isub__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __mul__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __rmul__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __imul__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __rfloordiv__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __ifloordiv__(self, other: 'i16') -> 'i16':
+        pass
+
+    def __lt__(self, other: 'i16') -> bool:
+        pass
+
+    def __le__(self, other: 'i16') -> bool:
+        pass
+
+    def __eq__(self, other: 'i16') -> bool:
+        pass
+
+    def __ne__(self, other: 'i16') -> bool:
+        pass
+
+    def __ge__(self, other: 'i16') -> bool:
+        pass
+
+    def __gt__(self, other: 'i16') -> bool:
+        pass
+
+class i32:
+    """32-bit signed integer."""
+
+    def __init__(self, _: Any) -> 'i32':
+        """Construct an i32."""
+
+    def __add__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __radd__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __iadd__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __sub__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __rsub__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __isub__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __mul__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __rmul__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __imul__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __rfloordiv__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __ifloordiv__(self, other: 'i32') -> 'i32':
+        pass
+
+    def __lt__(self, other: 'i32') -> bool:
+        pass
+
+    def __le__(self, other: 'i32') -> bool:
+        pass
+
+    def __eq__(self, other: 'i32') -> bool:
+        pass
+
+    def __ne__(self, other: 'i32') -> bool:
+        pass
+
+    def __ge__(self, other: 'i32') -> bool:
+        pass
+
+    def __gt__(self, other: 'i32') -> bool:
+        pass
+
+class i64:
+    """64-bit signed integer."""
+
+    def __init__(self, _: Any) -> 'i64':
+        """Construct an i64."""
+
+    def __add__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __radd__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __iadd__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __sub__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __rsub__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __isub__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __mul__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __rmul__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __imul__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __rfloordiv__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __ifloordiv__(self, other: 'i64') -> 'i64':
+        pass
+
+    def __lt__(self, other: 'i64') -> bool:
+        pass
+
+    def __le__(self, other: 'i64') -> bool:
+        pass
+
+    def __eq__(self, other: 'i64') -> bool:
+        pass
+
+    def __ne__(self, other: 'i64') -> bool:
+        pass
+
+    def __ge__(self, other: 'i64') -> bool:
+        pass
+
+    def __gt__(self, other: 'i64') -> bool:
+        pass
+
+class i128:
+    """128-bit signed integer."""
+
+    def __init__(self, _: Any) -> 'i128':
+        """Construct an i128."""
+
+    def __add__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __radd__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __iadd__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __sub__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __rsub__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __isub__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __mul__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __rmul__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __imul__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __rfloordiv__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __ifloordiv__(self, other: 'i128') -> 'i128':
+        pass
+
+    def __lt__(self, other: 'i128') -> bool:
+        pass
+
+    def __le__(self, other: 'i128') -> bool:
+        pass
+
+    def __eq__(self, other: 'i128') -> bool:
+        pass
+
+    def __ne__(self, other: 'i128') -> bool:
+        pass
+
+    def __ge__(self, other: 'i128') -> bool:
+        pass
+
+    def __gt__(self, other: 'i128') -> bool:
+        pass
+
+class f64:
+    """64-bit floating point number."""
+
+    def __init__(self, _: Any) -> 'f64':
+        """Construct an f64."""
+
+    def __add__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __radd__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __iadd__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __sub__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rsub__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __isub__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __mul__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rmul__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __imul__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __truediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rtruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __itruediv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __floordiv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __rfloordiv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __ifloordiv__(self, other: 'f64') -> 'f64':
+        pass
+
+    def __lt__(self, other: 'f64') -> bool:
+        pass
+
+    def __le__(self, other: 'f64') -> bool:
+        pass
+
+    def __eq__(self, other: 'f64') -> bool:
+        pass
+
+    def __ne__(self, other: 'f64') -> bool:
+        pass
+
+    def __ge__(self, other: 'f64') -> bool:
+        pass
+
+    def __gt__(self, other: 'f64') -> bool:
+        pass
+
+class Array(Generic[T, N]):
+    """
+    A fixed-length array: contains type T and has size N.
+
+    N must be known at compile-time, and may not be anything other than a non-negative integer literal. Example:
+
+    ```
+    # Good
+    a: Array[u8, 4]
+
+    # Bad
+    N = 4
+    a: Array[u8, N]
+    ```
+    """
+
+    def __init__(iterable: Iterable[T], len: N) -> 'Array[T, N]':
+        """
+        Construct an array from an iterable and a length.
+
+        The parameter len must be known at compile-time, and may not be anything other than a non-negative integer literal. Example:
+
+        ```
+        a = [0, 1, 2, 3]
+
+        # Good
+        Array(a, 4)
+        # Compiles, but will definitely error at runtime
+        Array(a, 5)
+
+        # Bad (will not compile)
+        a = [0, 1, 2, 3]
+        Array(a, len(a))
+        ```
+        """
+
+    def __getitem__(self, index: Any) -> T:
+        """
+        Index into this array.
+        
+        Like Python's native list type, performs wrapping indexing - if you pass in -1, you'll get the last element of the array.
+        """
+
+def array(*elements: T) -> Array[T, N]:
+    """
+    Create an array from a variadic list of elements. Example:
+
+    ```
+    # Array[u64, 3]
+    array(u64(0), 1, 2)
+
+    # Array[str, 4]
+    array('seahorse', 'is', 'the', 'best!')
+    ```
+    """
+
+class Enum:
+    """
+    A type that can have one of multiple named values.
+
+    Note that unlike Rust enums, these cannot contain any data (other than the variant itself). Example:
+
+    ```
+    class MyEnum(Enum):
+        ONE = 1
+        TWO = 2
+        THREE = 3
+
+    @instruction
+    def use_enum(code: MyEnum):
+        if code == MyEnum.ONE:
+            print(1)
+        # ...
+    ```
+    """
+
+
+# ============
+# Solana types
+# ============
+
+class Pubkey:
+    """32-byte account identifier."""
+
+    def find_program_address(seeds: List[Any], program_id: 'Pubkey' = None) -> Tuple['Pubkey', u8]:
+        """
+        Find a valid program derived address and its corresponding bump seed. Calls the same function from Solana's Pubkey struct - read more [here](https://docs.rs/solana-program/latest/solana_program/pubkey/struct.Pubkey.html#method.find_program_address).
+        
+        @param seeds: A list of parameters to uniquely identify this account among all accounts created by your program. These may be string literals, other accounts, integers, or lists of bytes.
+        @param program_id: The pubkey of the program that the PDA belongs to. Defaults to the current program's key.
+        @returns: The canonical pubkey and bump seed.
+        """
+
+class AccountWithKey:
+    """Generic Solana account."""
+
+    def key(self) -> Pubkey:
+        """Get this account's key."""
+
+class Account(AccountWithKey):
+    """User-defined Solana account."""
+
+    def transfer_lamports(self, to: AccountWithKey, amount: u64):
+        """
+        Transfer some SOL directly to another account. Since this account is program-owned, this transfer does not require a CPI.
+
+        @param to: The recipient Solana account.
+        @param amount: The amount (in lamports, not SOL) to transfer.
+        """
+
+class Event:
+    """Anchor event that clients can listen for"""
+
+    def emit(self):
+        """
+        Emit the event to the blockchain
+        """
+
+class Signer(AccountWithKey):
+    """Instruction signer."""
+
+    def transfer_lamports(self, to: AccountWithKey, amount: u64):
+        """
+        Transfer some SOL directly to another account. Unlike using transfer_lamports from a program account, this transfer will require a CPI.
+
+        @param to: The recipient Solana account.
+        @param amount: The amount (in lamports, not SOL) to transfer.
+        """
+
+class Empty(Generic[T]):
+    """An account that needs to be initialized."""
+
+    def init(self, payer: Signer, seeds: List[Any] = None, mint: 'TokenMint' = None, decimals: u8 = None, authority: AccountWithKey = None, associated: bool = False, space: u64 = None, padding: u64 = None)  -> T:
+        """
+        Initialize the account.
+        
+        @param payer: The account that will pay for the rent cost of the initialized account. Must be an instruction signer.
+        @param seeds: A list of parameters to uniquely identify this account among all accounts created by your program. These may be string literals, other accounts, integers, or lists of bytes.
+        @param mint: If initializing a TokenAccount, this is the mint that the account belongs to.
+        @param decimals: If initializing a TokenMint, this is the number of decimals the new token has.
+        @param authority: If initializing a TokenAccount/TokenMint, this is the account that has authority over the account.
+        @param associated: If initializing an associated token account, must be set to true.
+        @param space: If initializing a program account, you can use this to overwrite Seahorse's calculation of the account size.
+        @param padding: If initializing a program account, you can use this to add extra space to Seahorse's calculation of the account size.
+        @returns: The new, initialized account. All of the data in this account will be set to 0, bytewise.
+        """
+
+    def bump(self) -> u8:
+        """
+        Get this account's bump, needed if you want to use this account to sign CPI calls.
+        
+        If you've initialized an account without seeds, then a bump will not have been calculated. This will result in a runtime error when you try to access it.
+        """
+
+    def key(self) -> Pubkey:
+        """Get this account's key."""
+
+class CpiAccount:
+    """Account and metadata used for making arbitrary CPIs (via `Program.invoke`)."""
+
+    def __init__(account: AccountWithKey, mut: bool = False, signer: bool = False, seeds: List[Any] = None) -> 'CpiAccount':
+        """
+        Create the CpiAccount.
+
+        @param account: The account being passed to the CPI.
+        @param mut: Whether this account needs to be mutable for the CPI - defaults to false.
+        @param signer: Whether this account needs to be an instruction signer - defaults to false. Mutually exclusive with seeds, and should only really be true if account is a Signer.
+        @param seeds: PDA signer seeds, if this account needs to sign the CPI. Mutually exclusive with signer.
+        """
+
+class Program(AccountWithKey):
+    """Arbitrary program."""
+
+    def invoke(self, accounts: List[CpiAccount], data: List[u8]):
+        """
+        Call this program in a cross-program invocation. Make sure you know what you're doing before you try using this - a poorly crafted data list could cost you real money.
+
+        @param accounts: List of accounts being passed to the CPI - the program itself does not need to be in here.
+        @param data: "Raw" list of bytes used to tell the program what to do, pass args, etc.
+        """
+
+class UncheckedAccount(AccountWithKey):
+    """
+    Raw account that has had no safety checks performed on it.
+    
+    The underlying Anchor code cannot guarantee anything about the account unless you check it in your instruction - not the type, not the data, not the program it came from. Use carefully.
+    """
+
+class Clock:
+    """
+    Solana's Clock sysvar.
+    
+    Consult Solana's reference to learn more. Information copied from https://docs.rs/solana-program/1.14.3/solana_program/clock/struct.Clock.html.
+    """
+
+    def slot(self) -> u64:
+        """Get the current network/bank Slot."""
+
+    def epoch_start_timestamp(self) -> i64:
+        """Get the timestamp of the first Slot in this Epoch."""
+
+    def epoch(self) -> u64:
+        """Get the bank Epoch."""
+
+    def leader_schedule_epoch(self) -> u64:
+        """Get the future Epoch for which the leader schedule has most recently been calculated."""
+
+    def unix_timestamp(self) -> i64:
+        """
+        Get the estimated current UNIX timestamp.
+        
+        Originally computed from genesis creation time and network time in slots (drifty); corrected using validator timestamp oracle as of timestamp_correction and timestamp_bounding features.
+        """
+
+class TokenAccount(AccountWithKey):
+    """SPL token account."""
+
+    def authority(self) -> Pubkey:
+        """Get the owner of this token account."""
+
+    def amount(self) -> u64:
+        """Get the amount of token stored in this account."""
+
+    def mint(self) -> Pubkey:
+        """Get the mint that this token account corresponds to."""
+
+    def transfer(self, authority: AccountWithKey, to: 'TokenAccount', amount: u64, signer: List[Any] = None):
+        """
+        Transfer funds from this SPL token account to another.
+        
+        @param authority: The account that owns this TokenAccount. Must be an instruction signer or the account given by the `signer` param.
+        @param to: The recipient TokenAccount.
+        @param amount: How much (in *native* token units) to transfer.
+        @param signer: (Optional) seeds for the signature of a PDA.
+        """
+
+class TokenMint(AccountWithKey):
+    """SPL token mint."""
+
+    def authority(self) -> Pubkey:
+        """Get the owner of this token mint."""
+
+    def freeze_authority(self) -> Pubkey:
+        """Get the freeze authority of this token mint."""
+
+    def decimals(self) -> u8:
+        """Get the number of decimals for this token."""
+
+    def supply(self) -> u64:
+        """Get the amount of this token that exists."""
+
+    def mint(self, authority: AccountWithKey, to: TokenAccount, amount: u64, signer: List[Any] = None):
+        """
+        Mint new tokens to a token account.
+
+        @param authority: The account that owns this TokenMint. Must be an instruction signer or the account given by the `signer` param.
+        @param to: The recipient TokenAccount.
+        @param amount: How much (in *native* token units) to mint.
+        @param signer: (Optional) seeds for the signature of a PDA.
+        """
+
+    def burn(self, authority: AccountWithKey, holder: TokenAccount, amount: u64, signer: List[Any] = None):
+        """
+        Burn tokens from a token account.
+
+        @param authority: The account that owns the `holder` TokenAccount. Must be an instruction signer or the account given by the `signer` param.
+        @param holder: The TokenAccount to burn from.
+        @param amount: How much (in *native* token units) to burn.
+        @param signer: (Optional) seeds for the signature of a PDA.
+        """
+
+
+# ================
+# Helper functions
+# ================
+
+def declare_id(id: str):
+    """Inform Anchor what this program's ID is.
+
+    @param id: The program's ID, generated by Anchor in /target/idl/<program>.json. This must be copied-pasted straight from there as a string literal.
+    """
+
+def instruction(function: Callable[..., None]) -> Callable[..., None]:
+    """Decorator to turn a function into a program instruction."""
+
+def dataclass(function: Callable[..., None]) -> Callable[..., None]:
+    """Decorator to create an automatic default class constructor."""
+
+def int_bytes(n: Any, be: bool = False) -> List[u8]:
+    """
+    Convenience method to turn an integer type into a little-endian (by default) list of bytes.
+    
+    @param n: The integer you wish to convert to bytes.
+    @param be: Whether you want the conversion to be big-endian - defaults to false.
+    """
+
+def size(ob: str) -> u64:
+    """
+    Get the size of an object in bytes.
+    Currently this is only supported for strings.
+    
+    @param ob: The object to get the size of.
+    """

+ 38 - 0
basics/transfer-sol/seahorse/tests/seahorse.ts

@@ -0,0 +1,38 @@
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { Seahorse } from "../target/types/seahorse";
+
+describe("seahorse", () => {
+  // Configure the client to use the local cluster.
+  anchor.setProvider(anchor.AnchorProvider.env());
+
+  const program = anchor.workspace.Seahorse as Program<Seahorse>;
+
+  const mockReceiverAccount = anchor.web3.PublicKey.findProgramAddressSync(
+    [Buffer.from("mock_account")],
+    program.programId
+  );
+
+  it("Initialize the Mock account to send our SOL to", async () => {
+    const tx = await program.methods
+      .initMockAccount()
+      .accounts({
+        mockAccount: mockReceiverAccount[0],
+        signer: program.provider.publicKey,
+      })
+      .rpc();
+  });
+  it("Send SOL To Mock account", async () => {
+    const transferAmount = 1;
+    // Convert to lamport.
+    const lamports: number = anchor.web3.LAMPORTS_PER_SOL * transferAmount;
+    const tx = await program.methods
+      .transferSolWithCpi(new anchor.BN(lamports))
+      .accounts({
+        recipient: mockReceiverAccount[0],
+        sender: program.provider.publicKey,
+      })
+      .rpc();
+    console.log("Your transaction signature: ", tx);
+  });
+});

+ 11 - 0
basics/transfer-sol/seahorse/tsconfig.json

@@ -0,0 +1,11 @@
+{
+            "compilerOptions": {
+              "types": ["mocha", "chai"],
+              "typeRoots": ["./node_modules/@types"],
+              "lib": ["es2015"],
+              "module": "commonjs",
+              "target": "es6",
+              "esModuleInterop": true
+            }
+          }
+          

+ 8 - 0
tokens/token-2022/default-account-state/native/README.md

@@ -0,0 +1,8 @@
+## Token22 with default account state
+
+This extension makes it possible to set a default state for all underlying Token accounts of a certain Mint.
+
+These account states can be:
+
+- initialized: normal token account that can perform actions like transfers
+- frozen: the owner of this token account will not be able to perform any actions with his token.

+ 8 - 0
tokens/token-2022/default-account-state/native/cicd.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This script is for quick building & deploying of the program.
+# It also serves as a reference for the commands used for building & deploying Solana programs.
+# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
+
+cargo build-bpf --manifest-path=./program/Cargo.toml
+solana program deploy ./program/target/deploy/program.so

+ 22 - 0
tokens/token-2022/default-account-state/native/package.json

@@ -0,0 +1,22 @@
+{
+  "scripts": {
+    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
+  },
+  "dependencies": {
+    "@metaplex-foundation/mpl-token-metadata": "^2.5.2",
+    "@solana/spl-token": "^0.3.7",
+    "@solana/web3.js": "^1.73.0",
+    "borsh": "^0.7.0",
+    "buffer": "^6.0.3",
+    "fs": "^0.0.1-security"
+  },
+  "devDependencies": {
+    "@types/bn.js": "^5.1.0",
+    "@types/chai": "^4.3.1",
+    "@types/mocha": "^9.1.1",
+    "chai": "^4.3.4",
+    "mocha": "^9.0.3",
+    "ts-mocha": "^10.0.0",
+    "typescript": "^4.3.5"
+  }
+}

+ 14 - 0
tokens/token-2022/default-account-state/native/program/Cargo.toml

@@ -0,0 +1,14 @@
+[package]
+name = "program"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+borsh = "0.9.3"
+borsh-derive = "0.9.1"
+solana-program = "1.10.26"
+spl-associated-token-account = { version="1.0.5", features = [ "no-entrypoint" ] }
+spl-token-2022 = {version = "0.6.1", features = [ "no-entrypoint" ] }
+
+[lib]
+crate-type = ["cdylib", "lib"]

+ 130 - 0
tokens/token-2022/default-account-state/native/program/src/lib.rs

@@ -0,0 +1,130 @@
+use {
+    borsh::{BorshDeserialize, BorshSerialize},
+    solana_program::{
+        account_info::{next_account_info, AccountInfo},
+        entrypoint,
+        entrypoint::ProgramResult,
+        msg,
+        program::invoke,
+        pubkey::Pubkey,
+        rent::Rent,
+        system_instruction,
+        sysvar::Sysvar,
+    },
+    spl_token_2022::{
+        extension::{
+            default_account_state::instruction::{
+                initialize_default_account_state, update_default_account_state,
+            },
+            ExtensionType,
+        },
+        instruction as token_instruction,
+        state::AccountState,
+        state::Mint,
+    },
+};
+
+#[derive(BorshSerialize, BorshDeserialize, Debug)]
+pub struct CreateTokenArgs {
+    pub token_decimals: u8,
+}
+
+entrypoint!(process_instruction);
+
+fn process_instruction(
+    _program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    instruction_data: &[u8],
+) -> ProgramResult {
+    let args = CreateTokenArgs::try_from_slice(instruction_data)?;
+
+    let accounts_iter = &mut accounts.iter();
+
+    let mint_account = next_account_info(accounts_iter)?;
+    let mint_authority = next_account_info(accounts_iter)?;
+    let payer = next_account_info(accounts_iter)?;
+    let rent = next_account_info(accounts_iter)?;
+    let system_program = next_account_info(accounts_iter)?;
+    let token_program = next_account_info(accounts_iter)?;
+
+    // Find the size for the account with the Extension
+    let space = ExtensionType::get_account_len::<Mint>(&[ExtensionType::DefaultAccountState]);
+
+    // Get the required rent exemption amount for the account
+    let rent_required = Rent::get()?.minimum_balance(space);
+
+    // Create the account for the Mint and allocate space
+
+    msg!("Mint account address : {}", mint_account.key);
+    invoke(
+        &system_instruction::create_account(
+            &payer.key,
+            mint_account.key,
+            rent_required,
+            space as u64,
+            token_program.key,
+        ),
+        &[
+            mint_account.clone(),
+            payer.clone(),
+            system_program.clone(),
+            token_program.clone(),
+        ],
+    )?;
+
+    // This needs to be done before the Mint is initialized
+
+    // Initialize the Default Account State as Frozen
+    invoke(
+        &initialize_default_account_state(
+            token_program.key,
+            mint_account.key,
+            &AccountState::Frozen,
+        )
+        .unwrap(),
+        &[
+            mint_account.clone(),
+            token_program.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    // Initialize the Token Mint
+    invoke(
+        &token_instruction::initialize_mint(
+            &token_program.key,
+            &mint_account.key,
+            &mint_authority.key,
+            Some(&mint_authority.key),
+            args.token_decimals,
+        )?,
+        &[
+            mint_account.clone(),
+            mint_authority.clone(),
+            token_program.clone(),
+            rent.clone(),
+        ],
+    )?;
+
+    // Update the Default Account State to Initialized
+    invoke(
+        &update_default_account_state(
+            token_program.key,
+            mint_account.key,
+            payer.key,
+            &[&payer.key],
+            &AccountState::Initialized,
+        )
+        .unwrap(),
+        &[
+            mint_account.clone(),
+            payer.clone(),
+            token_program.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    msg!("Mint created!");
+
+    Ok(())
+}

+ 86 - 0
tokens/token-2022/default-account-state/native/tests/test.ts

@@ -0,0 +1,86 @@
+import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata";
+import {
+  Connection,
+  Keypair,
+  PublicKey,
+  SystemProgram,
+  SYSVAR_RENT_PUBKEY,
+  TransactionInstruction,
+  Transaction,
+  sendAndConfirmTransaction,
+} from "@solana/web3.js";
+import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
+import * as borsh from "borsh";
+import { Buffer } from "buffer";
+
+function createKeypairFromFile(path: string): Keypair {
+  return Keypair.fromSecretKey(
+    Buffer.from(JSON.parse(require("fs").readFileSync(path, "utf-8")))
+  );
+}
+
+class Assignable {
+  constructor(properties) {
+    Object.keys(properties).map((key) => {
+      return (this[key] = properties[key]);
+    });
+  }
+}
+
+class CreateTokenArgs extends Assignable {
+  toBuffer() {
+    return Buffer.from(borsh.serialize(CreateTokenArgsSchema, this));
+  }
+}
+const CreateTokenArgsSchema = new Map([
+  [
+    CreateTokenArgs,
+    {
+      kind: "struct",
+      fields: [["token_decimals", "u8"]],
+    },
+  ],
+]);
+
+describe("Create Token", async () => {
+  const connection = new Connection(
+    `https://api.devnet.solana.com/`,
+    "confirmed"
+  );
+  const payer = createKeypairFromFile(
+    require("os").homedir() + "/.config/solana/id.json"
+  );
+  const program = createKeypairFromFile(
+    "./program/target/deploy/program-keypair.json"
+  );
+
+  it("Create a Token-22 SPL-Token !", async () => {
+    const mintKeypair: Keypair = Keypair.generate();
+
+    const instructionData = new CreateTokenArgs({
+      token_decimals: 9,
+    });
+
+    const instruction = new TransactionInstruction({
+      keys: [
+        { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
+        { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
+        { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Transaction Payer
+        { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
+        { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
+        { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
+      ],
+      programId: program.publicKey,
+      data: instructionData.toBuffer(),
+    });
+
+    const signature = await sendAndConfirmTransaction(
+      connection,
+      new Transaction().add(instruction),
+      [payer, mintKeypair]
+    );
+
+    console.log(`Token Mint Address: `, mintKeypair.publicKey.toBase58());
+    console.log(`Transaction Signature: `, signature);
+  });
+});

+ 10 - 0
tokens/token-2022/default-account-state/native/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 8 - 0
tokens/token-2022/mint-close-authority/native/cicd.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This script is for quick building & deploying of the program.
+# It also serves as a reference for the commands used for building & deploying Solana programs.
+# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
+
+cargo build-bpf --manifest-path=./program/Cargo.toml
+solana program deploy ./program/target/deploy/program.so

+ 22 - 0
tokens/token-2022/mint-close-authority/native/package.json

@@ -0,0 +1,22 @@
+{
+  "scripts": {
+    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
+  },
+  "dependencies": {
+    "@metaplex-foundation/mpl-token-metadata": "^2.5.2",
+    "@solana/spl-token": "^0.3.7",
+    "@solana/web3.js": "^1.73.0",
+    "borsh": "^0.7.0",
+    "buffer": "^6.0.3",
+    "fs": "^0.0.1-security"
+  },
+  "devDependencies": {
+    "@types/bn.js": "^5.1.0",
+    "@types/chai": "^4.3.1",
+    "@types/mocha": "^9.1.1",
+    "chai": "^4.3.4",
+    "mocha": "^9.0.3",
+    "ts-mocha": "^10.0.0",
+    "typescript": "^4.3.5"
+  }
+}

+ 14 - 0
tokens/token-2022/mint-close-authority/native/program/Cargo.toml

@@ -0,0 +1,14 @@
+[package]
+name = "program"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+borsh = "0.9.3"
+borsh-derive = "0.9.1"
+solana-program = "1.10.26"
+spl-associated-token-account = { version="1.0.5", features = [ "no-entrypoint" ] }
+spl-token-2022 = {version = "0.6.1", features = [ "no-entrypoint" ] }
+
+[lib]
+crate-type = ["cdylib", "lib"]

+ 103 - 0
tokens/token-2022/mint-close-authority/native/program/src/lib.rs

@@ -0,0 +1,103 @@
+use {
+    borsh::{BorshDeserialize, BorshSerialize},
+    solana_program::{
+        account_info::{next_account_info, AccountInfo},
+        entrypoint,
+        entrypoint::ProgramResult,
+        msg,
+        program::invoke,
+        pubkey::Pubkey,
+        rent::Rent,
+        system_instruction,
+        sysvar::Sysvar,
+    },
+    spl_token_2022::{extension::ExtensionType, instruction as token_instruction, state::Mint},
+};
+
+#[derive(BorshSerialize, BorshDeserialize, Debug)]
+pub struct CreateTokenArgs {
+    pub token_decimals: u8,
+}
+
+entrypoint!(process_instruction);
+
+fn process_instruction(
+    _program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    instruction_data: &[u8],
+) -> ProgramResult {
+    let args = CreateTokenArgs::try_from_slice(instruction_data)?;
+
+    let accounts_iter = &mut accounts.iter();
+
+    let mint_account = next_account_info(accounts_iter)?;
+    let mint_authority = next_account_info(accounts_iter)?;
+    let close_authority = next_account_info(accounts_iter)?;
+    let payer = next_account_info(accounts_iter)?;
+    let rent = next_account_info(accounts_iter)?;
+    let system_program = next_account_info(accounts_iter)?;
+    let token_program = next_account_info(accounts_iter)?;
+
+    // Find the size for the account with the Extension
+    let space = ExtensionType::get_account_len::<Mint>(&[ExtensionType::MintCloseAuthority]);
+
+    // Get the required rent exemption amount for the account
+    let rent_required = Rent::get()?.minimum_balance(space);
+
+    // Create the account for the Mint and allocate space
+    msg!("Mint account address : {}", mint_account.key);
+    invoke(
+        &system_instruction::create_account(
+            &payer.key,
+            mint_account.key,
+            rent_required,
+            space as u64,
+            token_program.key,
+        ),
+        &[
+            mint_account.clone(),
+            payer.clone(),
+            system_program.clone(),
+            token_program.clone(),
+        ],
+    )?;
+
+    // This needs to be done before the Mint is initialized
+
+    // Initialize the Mint close authority Extension
+    invoke(
+        &token_instruction::initialize_mint_close_authority(
+            token_program.key,
+            mint_account.key,
+            Some(close_authority.key),
+        )
+        .unwrap(),
+        &[
+            mint_account.clone(),
+            close_authority.clone(),
+            token_program.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    // Initialize the Token Mint
+    invoke(
+        &token_instruction::initialize_mint(
+            &token_program.key,
+            &mint_account.key,
+            &mint_authority.key,
+            Some(&mint_authority.key),
+            args.token_decimals,
+        )?,
+        &[
+            mint_account.clone(),
+            mint_authority.clone(),
+            token_program.clone(),
+            rent.clone(),
+        ],
+    )?;
+
+    msg!("Mint created!");
+
+    Ok(())
+}

+ 87 - 0
tokens/token-2022/mint-close-authority/native/tests/test.ts

@@ -0,0 +1,87 @@
+import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata";
+import {
+  Connection,
+  Keypair,
+  PublicKey,
+  SystemProgram,
+  SYSVAR_RENT_PUBKEY,
+  TransactionInstruction,
+  Transaction,
+  sendAndConfirmTransaction,
+} from "@solana/web3.js";
+import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
+import * as borsh from "borsh";
+import { Buffer } from "buffer";
+
+function createKeypairFromFile(path: string): Keypair {
+  return Keypair.fromSecretKey(
+    Buffer.from(JSON.parse(require("fs").readFileSync(path, "utf-8")))
+  );
+}
+
+class Assignable {
+  constructor(properties) {
+    Object.keys(properties).map((key) => {
+      return (this[key] = properties[key]);
+    });
+  }
+}
+
+class CreateTokenArgs extends Assignable {
+  toBuffer() {
+    return Buffer.from(borsh.serialize(CreateTokenArgsSchema, this));
+  }
+}
+const CreateTokenArgsSchema = new Map([
+  [
+    CreateTokenArgs,
+    {
+      kind: "struct",
+      fields: [["token_decimals", "u8"]],
+    },
+  ],
+]);
+
+describe("Create Token", async () => {
+  const connection = new Connection(
+    `https://api.devnet.solana.com/`,
+    "confirmed"
+  );
+  const payer = createKeypairFromFile(
+    require("os").homedir() + "/.config/solana/id.json"
+  );
+  const program = createKeypairFromFile(
+    "./program/target/deploy/program-keypair.json"
+  );
+
+  it("Create a Token-22 SPL-Token !", async () => {
+    const mintKeypair: Keypair = Keypair.generate();
+
+    const instructionData = new CreateTokenArgs({
+      token_decimals: 9,
+    });
+
+    const instruction = new TransactionInstruction({
+      keys: [
+        { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
+        { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
+        { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint close authority account
+        { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Transaction Payer
+        { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
+        { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
+        { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
+      ],
+      programId: program.publicKey,
+      data: instructionData.toBuffer(),
+    });
+
+    const signature = await sendAndConfirmTransaction(
+      connection,
+      new Transaction().add(instruction),
+      [payer, mintKeypair]
+    );
+
+    console.log(`Token Mint Address: `, mintKeypair.publicKey.toBase58());
+    console.log(`Transaction Signature: `, signature);
+  });
+});

+ 10 - 0
tokens/token-2022/mint-close-authority/native/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 8 - 0
tokens/token-2022/multiple-extensions/native/cicd.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This script is for quick building & deploying of the program.
+# It also serves as a reference for the commands used for building & deploying Solana programs.
+# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
+
+cargo build-bpf --manifest-path=./program/Cargo.toml
+solana program deploy ./program/target/deploy/program.so

+ 22 - 0
tokens/token-2022/multiple-extensions/native/package.json

@@ -0,0 +1,22 @@
+{
+  "scripts": {
+    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
+  },
+  "dependencies": {
+    "@metaplex-foundation/mpl-token-metadata": "^2.5.2",
+    "@solana/spl-token": "^0.3.7",
+    "@solana/web3.js": "^1.73.0",
+    "borsh": "^0.7.0",
+    "buffer": "^6.0.3",
+    "fs": "^0.0.1-security"
+  },
+  "devDependencies": {
+    "@types/bn.js": "^5.1.0",
+    "@types/chai": "^4.3.1",
+    "@types/mocha": "^9.1.1",
+    "chai": "^4.3.4",
+    "mocha": "^9.0.3",
+    "ts-mocha": "^10.0.0",
+    "typescript": "^4.3.5"
+  }
+}

+ 14 - 0
tokens/token-2022/multiple-extensions/native/program/Cargo.toml

@@ -0,0 +1,14 @@
+[package]
+name = "program"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+borsh = "0.9.3"
+borsh-derive = "0.9.1"
+solana-program = "1.10.26"
+spl-associated-token-account = { version="1.0.5", features = [ "no-entrypoint" ] }
+spl-token-2022 = {version = "0.6.1", features = [ "no-entrypoint" ] }
+
+[lib]
+crate-type = ["cdylib", "lib"]

+ 117 - 0
tokens/token-2022/multiple-extensions/native/program/src/lib.rs

@@ -0,0 +1,117 @@
+use {
+    borsh::{BorshDeserialize, BorshSerialize},
+    solana_program::{
+        account_info::{next_account_info, AccountInfo},
+        entrypoint,
+        entrypoint::ProgramResult,
+        msg,
+        program::invoke,
+        pubkey::Pubkey,
+        rent::Rent,
+        system_instruction,
+        sysvar::Sysvar,
+    },
+    spl_token_2022::{extension::ExtensionType, instruction as token_instruction, state::Mint},
+};
+
+#[derive(BorshSerialize, BorshDeserialize, Debug)]
+pub struct CreateTokenArgs {
+    pub token_decimals: u8,
+}
+
+entrypoint!(process_instruction);
+
+fn process_instruction(
+    _program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    instruction_data: &[u8],
+) -> ProgramResult {
+    let args = CreateTokenArgs::try_from_slice(instruction_data)?;
+
+    let accounts_iter = &mut accounts.iter();
+
+    let mint_account = next_account_info(accounts_iter)?;
+    let mint_authority = next_account_info(accounts_iter)?;
+    let close_authority = next_account_info(accounts_iter)?;
+    let payer = next_account_info(accounts_iter)?;
+    let rent = next_account_info(accounts_iter)?;
+    let system_program = next_account_info(accounts_iter)?;
+    let token_program = next_account_info(accounts_iter)?;
+
+    // Find the size for the Mint account with the the number of extensions we want to use.
+    let space = ExtensionType::get_account_len::<Mint>(&[
+        ExtensionType::MintCloseAuthority,
+        ExtensionType::NonTransferable,
+    ]);
+
+    // Get the required rent exemption amount for the account
+    let rent_required = Rent::get()?.minimum_balance(space);
+
+    // Create the account for the Mint and allocate space
+    msg!("Mint account address : {}", mint_account.key);
+    invoke(
+        &system_instruction::create_account(
+            &payer.key,
+            mint_account.key,
+            rent_required,
+            space as u64,
+            token_program.key,
+        ),
+        &[
+            mint_account.clone(),
+            payer.clone(),
+            system_program.clone(),
+            token_program.clone(),
+        ],
+    )?;
+
+    // Here, let's enable two extensions for the Mint. This needs to be done before the Mint is initialized
+
+    // Initialize the Mint close authority Extension
+    invoke(
+        &token_instruction::initialize_mint_close_authority(
+            token_program.key,
+            mint_account.key,
+            Some(close_authority.key),
+        )
+        .unwrap(),
+        &[
+            mint_account.clone(),
+            close_authority.clone(),
+            token_program.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    // Initialize the Non Transferable Mint Extension
+    invoke(
+        &token_instruction::initialize_non_transferable_mint(token_program.key, mint_account.key)
+            .unwrap(),
+        &[
+            mint_account.clone(),
+            token_program.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    // Initialize the Token Mint
+    invoke(
+        &token_instruction::initialize_mint(
+            &token_program.key,
+            &mint_account.key,
+            &mint_authority.key,
+            Some(&mint_authority.key),
+            args.token_decimals,
+        )?,
+        &[
+            mint_account.clone(),
+            mint_authority.clone(),
+            token_program.clone(),
+            rent.clone(),
+        ],
+    )?;
+
+    msg!("Mint created!");
+
+    Ok(())
+}

+ 87 - 0
tokens/token-2022/multiple-extensions/native/tests/test.ts

@@ -0,0 +1,87 @@
+import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata";
+import {
+  Connection,
+  Keypair,
+  PublicKey,
+  SystemProgram,
+  SYSVAR_RENT_PUBKEY,
+  TransactionInstruction,
+  Transaction,
+  sendAndConfirmTransaction,
+} from "@solana/web3.js";
+import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
+import * as borsh from "borsh";
+import { Buffer } from "buffer";
+
+function createKeypairFromFile(path: string): Keypair {
+  return Keypair.fromSecretKey(
+    Buffer.from(JSON.parse(require("fs").readFileSync(path, "utf-8")))
+  );
+}
+
+class Assignable {
+  constructor(properties) {
+    Object.keys(properties).map((key) => {
+      return (this[key] = properties[key]);
+    });
+  }
+}
+
+class CreateTokenArgs extends Assignable {
+  toBuffer() {
+    return Buffer.from(borsh.serialize(CreateTokenArgsSchema, this));
+  }
+}
+const CreateTokenArgsSchema = new Map([
+  [
+    CreateTokenArgs,
+    {
+      kind: "struct",
+      fields: [["token_decimals", "u8"]],
+    },
+  ],
+]);
+
+describe("Create Token", async () => {
+  const connection = new Connection(
+    `https://api.devnet.solana.com/`,
+    "confirmed"
+  );
+  const payer = createKeypairFromFile(
+    require("os").homedir() + "/.config/solana/id.json"
+  );
+  const program = createKeypairFromFile(
+    "./program/target/deploy/program-keypair.json"
+  );
+
+  it("Create a Token-22 SPL-Token !", async () => {
+    const mintKeypair: Keypair = Keypair.generate();
+
+    const instructionData = new CreateTokenArgs({
+      token_decimals: 9,
+    });
+
+    const instruction = new TransactionInstruction({
+      keys: [
+        { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
+        { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
+        { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint close authority account
+        { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Transaction Payer
+        { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
+        { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
+        { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
+      ],
+      programId: program.publicKey,
+      data: instructionData.toBuffer(),
+    });
+
+    const signature = await sendAndConfirmTransaction(
+      connection,
+      new Transaction().add(instruction),
+      [payer, mintKeypair]
+    );
+
+    console.log(`Token Mint Address: `, mintKeypair.publicKey.toBase58());
+    console.log(`Transaction Signature: `, signature);
+  });
+});

+ 10 - 0
tokens/token-2022/multiple-extensions/native/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 8 - 0
tokens/token-2022/non-transferable/native/cicd.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This script is for quick building & deploying of the program.
+# It also serves as a reference for the commands used for building & deploying Solana programs.
+# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
+
+cargo build-bpf --manifest-path=./program/Cargo.toml
+solana program deploy ./program/target/deploy/program.so

+ 22 - 0
tokens/token-2022/non-transferable/native/package.json

@@ -0,0 +1,22 @@
+{
+  "scripts": {
+    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
+  },
+  "dependencies": {
+    "@metaplex-foundation/mpl-token-metadata": "^2.5.2",
+    "@solana/spl-token": "^0.3.7",
+    "@solana/web3.js": "^1.73.0",
+    "borsh": "^0.7.0",
+    "buffer": "^6.0.3",
+    "fs": "^0.0.1-security"
+  },
+  "devDependencies": {
+    "@types/bn.js": "^5.1.0",
+    "@types/chai": "^4.3.1",
+    "@types/mocha": "^9.1.1",
+    "chai": "^4.3.4",
+    "mocha": "^9.0.3",
+    "ts-mocha": "^10.0.0",
+    "typescript": "^4.3.5"
+  }
+}

+ 14 - 0
tokens/token-2022/non-transferable/native/program/Cargo.toml

@@ -0,0 +1,14 @@
+[package]
+name = "program"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+borsh = "0.9.3"
+borsh-derive = "0.9.1"
+solana-program = "1.10.26"
+spl-associated-token-account = { version="1.0.5", features = [ "no-entrypoint" ] }
+spl-token-2022 = {version = "0.6.1", features = [ "no-entrypoint" ] }
+
+[lib]
+crate-type = ["cdylib", "lib"]

+ 97 - 0
tokens/token-2022/non-transferable/native/program/src/lib.rs

@@ -0,0 +1,97 @@
+use {
+    borsh::{BorshDeserialize, BorshSerialize},
+    solana_program::{
+        account_info::{next_account_info, AccountInfo},
+        entrypoint,
+        entrypoint::ProgramResult,
+        msg,
+        program::invoke,
+        pubkey::Pubkey,
+        rent::Rent,
+        system_instruction,
+        sysvar::Sysvar,
+    },
+    spl_token_2022::{extension::ExtensionType, instruction as token_instruction, state::Mint},
+};
+
+#[derive(BorshSerialize, BorshDeserialize, Debug)]
+pub struct CreateTokenArgs {
+    pub token_decimals: u8,
+}
+
+entrypoint!(process_instruction);
+
+fn process_instruction(
+    _program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    instruction_data: &[u8],
+) -> ProgramResult {
+    let args = CreateTokenArgs::try_from_slice(instruction_data)?;
+
+    let accounts_iter = &mut accounts.iter();
+
+    let mint_account = next_account_info(accounts_iter)?;
+    let mint_authority = next_account_info(accounts_iter)?;
+    let payer = next_account_info(accounts_iter)?;
+    let rent = next_account_info(accounts_iter)?;
+    let system_program = next_account_info(accounts_iter)?;
+    let token_program = next_account_info(accounts_iter)?;
+
+    // Find the size for the account with the Extension
+    let space = ExtensionType::get_account_len::<Mint>(&[ExtensionType::NonTransferable]);
+
+    // Get the required rent exemption amount for the account
+    let rent_required = Rent::get()?.minimum_balance(space);
+
+    // Create the account for the Mint and allocate space
+    msg!("Mint account address : {}", mint_account.key);
+    invoke(
+        &system_instruction::create_account(
+            &payer.key,
+            mint_account.key,
+            rent_required,
+            space as u64,
+            token_program.key,
+        ),
+        &[
+            mint_account.clone(),
+            payer.clone(),
+            system_program.clone(),
+            token_program.clone(),
+        ],
+    )?;
+
+    // This needs to be done before the Mint is initialized
+
+    // Initialize the Non Transferable Mint Extension
+    invoke(
+        &token_instruction::initialize_non_transferable_mint(token_program.key, mint_account.key)
+            .unwrap(),
+        &[
+            mint_account.clone(),
+            token_program.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    // Initialize the Token Mint
+    invoke(
+        &token_instruction::initialize_mint(
+            &token_program.key,
+            &mint_account.key,
+            &mint_authority.key,
+            Some(&mint_authority.key),
+            args.token_decimals,
+        )?,
+        &[
+            mint_account.clone(),
+            mint_authority.clone(),
+            token_program.clone(),
+            rent.clone(),
+        ],
+    )?;
+
+    msg!("Mint created!");
+
+    Ok(())
+}

+ 86 - 0
tokens/token-2022/non-transferable/native/tests/test.ts

@@ -0,0 +1,86 @@
+import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata";
+import {
+  Connection,
+  Keypair,
+  PublicKey,
+  SystemProgram,
+  SYSVAR_RENT_PUBKEY,
+  TransactionInstruction,
+  Transaction,
+  sendAndConfirmTransaction,
+} from "@solana/web3.js";
+import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
+import * as borsh from "borsh";
+import { Buffer } from "buffer";
+
+function createKeypairFromFile(path: string): Keypair {
+  return Keypair.fromSecretKey(
+    Buffer.from(JSON.parse(require("fs").readFileSync(path, "utf-8")))
+  );
+}
+
+class Assignable {
+  constructor(properties) {
+    Object.keys(properties).map((key) => {
+      return (this[key] = properties[key]);
+    });
+  }
+}
+
+class CreateTokenArgs extends Assignable {
+  toBuffer() {
+    return Buffer.from(borsh.serialize(CreateTokenArgsSchema, this));
+  }
+}
+const CreateTokenArgsSchema = new Map([
+  [
+    CreateTokenArgs,
+    {
+      kind: "struct",
+      fields: [["token_decimals", "u8"]],
+    },
+  ],
+]);
+
+describe("Create Token", async () => {
+  const connection = new Connection(
+    `https://api.devnet.solana.com/`,
+    "confirmed"
+  );
+  const payer = createKeypairFromFile(
+    require("os").homedir() + "/.config/solana/id.json"
+  );
+  const program = createKeypairFromFile(
+    "./program/target/deploy/program-keypair.json"
+  );
+
+  it("Create a Token-22 SPL-Token !", async () => {
+    const mintKeypair: Keypair = Keypair.generate();
+
+    const instructionData = new CreateTokenArgs({
+      token_decimals: 9,
+    });
+
+    const instruction = new TransactionInstruction({
+      keys: [
+        { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
+        { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
+        { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Transaction Payer
+        { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
+        { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
+        { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
+      ],
+      programId: program.publicKey,
+      data: instructionData.toBuffer(),
+    });
+
+    const signature = await sendAndConfirmTransaction(
+      connection,
+      new Transaction().add(instruction),
+      [payer, mintKeypair]
+    );
+
+    console.log(`Token Mint Address: `, mintKeypair.publicKey.toBase58());
+    console.log(`Transaction Signature: `, signature);
+  });
+});

+ 10 - 0
tokens/token-2022/non-transferable/native/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}

+ 8 - 0
tokens/token-2022/transfer-fees/native/cicd.sh

@@ -0,0 +1,8 @@
+#!/bin/bash
+
+# This script is for quick building & deploying of the program.
+# It also serves as a reference for the commands used for building & deploying Solana programs.
+# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
+
+cargo build-bpf --manifest-path=./program/Cargo.toml
+solana program deploy ./program/target/deploy/program.so

+ 22 - 0
tokens/token-2022/transfer-fees/native/package.json

@@ -0,0 +1,22 @@
+{
+  "scripts": {
+    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
+  },
+  "dependencies": {
+    "@metaplex-foundation/mpl-token-metadata": "^2.5.2",
+    "@solana/spl-token": "^0.3.7",
+    "@solana/web3.js": "^1.73.0",
+    "borsh": "^0.7.0",
+    "buffer": "^6.0.3",
+    "fs": "^0.0.1-security"
+  },
+  "devDependencies": {
+    "@types/bn.js": "^5.1.0",
+    "@types/chai": "^4.3.1",
+    "@types/mocha": "^9.1.1",
+    "chai": "^4.3.4",
+    "mocha": "^9.0.3",
+    "ts-mocha": "^10.0.0",
+    "typescript": "^4.3.5"
+  }
+}

+ 14 - 0
tokens/token-2022/transfer-fees/native/program/Cargo.toml

@@ -0,0 +1,14 @@
+[package]
+name = "program"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+borsh = "0.9.3"
+borsh-derive = "0.9.1"
+solana-program = "1.10.26"
+spl-associated-token-account = { version="1.0.5", features = [ "no-entrypoint" ] }
+spl-token-2022 = {version = "0.6.1", features = [ "no-entrypoint" ] }
+
+[lib]
+crate-type = ["cdylib", "lib"]

+ 135 - 0
tokens/token-2022/transfer-fees/native/program/src/lib.rs

@@ -0,0 +1,135 @@
+use {
+    borsh::{BorshDeserialize, BorshSerialize},
+    solana_program::{
+        account_info::{next_account_info, AccountInfo},
+        entrypoint,
+        entrypoint::ProgramResult,
+        msg,
+        program::invoke,
+        pubkey::Pubkey,
+        rent::Rent,
+        system_instruction,
+        sysvar::Sysvar,
+    },
+    spl_token_2022::{
+        extension::{
+            transfer_fee::instruction::{initialize_transfer_fee_config, set_transfer_fee},
+            ExtensionType,
+        },
+        instruction as token_instruction,
+        state::Mint,
+    },
+};
+
+#[derive(BorshSerialize, BorshDeserialize, Debug)]
+pub struct CreateTokenArgs {
+    pub token_decimals: u8,
+}
+
+entrypoint!(process_instruction);
+
+fn process_instruction(
+    _program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    instruction_data: &[u8],
+) -> ProgramResult {
+    let args = CreateTokenArgs::try_from_slice(instruction_data)?;
+
+    let accounts_iter = &mut accounts.iter();
+
+    let mint_account = next_account_info(accounts_iter)?;
+    let mint_authority = next_account_info(accounts_iter)?;
+    let payer = next_account_info(accounts_iter)?;
+    let rent = next_account_info(accounts_iter)?;
+    let system_program = next_account_info(accounts_iter)?;
+    let token_program = next_account_info(accounts_iter)?;
+
+    // Find the size for the account with the Extension
+    let space = ExtensionType::get_account_len::<Mint>(&[ExtensionType::TransferFeeConfig]);
+
+    // Get the required rent exemption amount for the account
+    let rent_required = Rent::get()?.minimum_balance(space);
+
+    // Create the account for the Mint and allocate space
+    msg!("Mint account address : {}", mint_account.key);
+    invoke(
+        &system_instruction::create_account(
+            &payer.key,
+            mint_account.key,
+            rent_required,
+            space as u64,
+            token_program.key,
+        ),
+        &[
+            mint_account.clone(),
+            payer.clone(),
+            system_program.clone(),
+            token_program.clone(),
+        ],
+    )?;
+
+    // The max fee will be 5 tokens, here we adjust it with the tokens decimals
+    let max_fee = 5 * 10u64.pow(args.token_decimals as u32);
+
+    // This needs to be done before the Mint is initialized
+    // Initialize the Transfer Fee config
+    invoke(
+        &initialize_transfer_fee_config(
+            token_program.key,
+            mint_account.key,
+            Some(payer.key),
+            Some(payer.key),
+            // 1% fee on transfers
+            100,
+            max_fee,
+        )
+        .unwrap(),
+        &[
+            mint_account.clone(),
+            token_program.clone(),
+            payer.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    // Initialize the Token Mint
+    invoke(
+        &token_instruction::initialize_mint(
+            &token_program.key,
+            &mint_account.key,
+            &mint_authority.key,
+            Some(&mint_authority.key),
+            args.token_decimals,
+        )?,
+        &[
+            mint_account.clone(),
+            mint_authority.clone(),
+            token_program.clone(),
+            rent.clone(),
+        ],
+    )?;
+
+    // Initialize the Transfer Fee config
+    invoke(
+        &set_transfer_fee(
+            token_program.key,
+            mint_account.key,
+            payer.key,
+            &[payer.key],
+            // 10% fee on transfers
+            1000,
+            max_fee,
+        )
+        .unwrap(),
+        &[
+            mint_account.clone(),
+            token_program.clone(),
+            payer.clone(),
+            system_program.clone(),
+        ],
+    )?;
+
+    msg!("Mint created!");
+
+    Ok(())
+}

+ 86 - 0
tokens/token-2022/transfer-fees/native/tests/test.ts

@@ -0,0 +1,86 @@
+import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata";
+import {
+  Connection,
+  Keypair,
+  PublicKey,
+  SystemProgram,
+  SYSVAR_RENT_PUBKEY,
+  TransactionInstruction,
+  Transaction,
+  sendAndConfirmTransaction,
+} from "@solana/web3.js";
+import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
+import * as borsh from "borsh";
+import { Buffer } from "buffer";
+
+function createKeypairFromFile(path: string): Keypair {
+  return Keypair.fromSecretKey(
+    Buffer.from(JSON.parse(require("fs").readFileSync(path, "utf-8")))
+  );
+}
+
+class Assignable {
+  constructor(properties) {
+    Object.keys(properties).map((key) => {
+      return (this[key] = properties[key]);
+    });
+  }
+}
+
+class CreateTokenArgs extends Assignable {
+  toBuffer() {
+    return Buffer.from(borsh.serialize(CreateTokenArgsSchema, this));
+  }
+}
+const CreateTokenArgsSchema = new Map([
+  [
+    CreateTokenArgs,
+    {
+      kind: "struct",
+      fields: [["token_decimals", "u8"]],
+    },
+  ],
+]);
+
+describe("Create Token", async () => {
+  const connection = new Connection(
+    `https://api.devnet.solana.com/`,
+    "confirmed"
+  );
+  const payer = createKeypairFromFile(
+    require("os").homedir() + "/.config/solana/id.json"
+  );
+  const program = createKeypairFromFile(
+    "./program/target/deploy/program-keypair.json"
+  );
+
+  it("Create a Token-22 SPL-Token !", async () => {
+    const mintKeypair: Keypair = Keypair.generate();
+
+    const instructionData = new CreateTokenArgs({
+      token_decimals: 9,
+    });
+
+    const instruction = new TransactionInstruction({
+      keys: [
+        { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
+        { pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
+        { pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Transaction Payer
+        { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
+        { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
+        { pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
+      ],
+      programId: program.publicKey,
+      data: instructionData.toBuffer(),
+    });
+
+    const signature = await sendAndConfirmTransaction(
+      connection,
+      new Transaction().add(instruction),
+      [payer, mintKeypair]
+    );
+
+    console.log(`Token Mint Address: `, mintKeypair.publicKey.toBase58());
+    console.log(`Transaction Signature: `, signature);
+  });
+});

+ 10 - 0
tokens/token-2022/transfer-fees/native/tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "types": ["mocha", "chai"],
+    "typeRoots": ["./node_modules/@types"],
+    "lib": ["es2015"],
+    "module": "commonjs",
+    "target": "es6",
+    "esModuleInterop": true
+  }
+}