浏览代码

add default account state mint

Valentin Madrid 2 年之前
父节点
当前提交
2e9548d0ff

+ 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"
+  }
+}

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

@@ -0,0 +1,15 @@
+[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-token = { version="3.3.0", features = [ "no-entrypoint" ] }
+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"]

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

@@ -0,0 +1,127 @@
+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(),
+        ],
+    )?;
+
+    // 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
+  }
+}