Просмотр исходного кода

Merge pull request #22 from valentinmadrid/main

🍉 - Add Token 2022 Basics Program
Joe Caulfield 2 лет назад
Родитель
Сommit
8dcf99e2e7

+ 0 - 3
tokens/token-2022/README.md

@@ -1,3 +0,0 @@
-# Token 2022
-
-> Coming soon!

+ 7 - 0
tokens/token-2022/anchor/.gitignore

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

+ 8 - 0
tokens/token-2022/anchor/.prettierignore

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

+ 15 - 0
tokens/token-2022/anchor/Anchor.toml

@@ -0,0 +1,15 @@
+[features]
+seeds = false
+skip-lint = false
+[programs.localnet]
+anchor = "6qNqxkRF791FXFeQwqYQLEzAbGiqDULC5SSHVsfRoG89"
+
+[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
tokens/token-2022/anchor/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

+ 12 - 0
tokens/token-2022/anchor/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
tokens/token-2022/anchor/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"
+  }
+}

+ 23 - 0
tokens/token-2022/anchor/programs/basics/Cargo.toml

@@ -0,0 +1,23 @@
+[package]
+name = "anchor"
+version = "0.1.0"
+description = "Created with Anchor"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib", "lib"]
+name = "anchor"
+
+[features]
+no-entrypoint = []
+no-idl = []
+no-log-ix-name = []
+cpi = ["no-entrypoint"]
+default = []
+
+[dependencies]
+anchor-spl = "0.27.0"
+anchor-lang = { version = "0.27.0", features= ["init-if-needed"]}
+spl-token = { version = "3.1.1", features = ["no-entrypoint"] }
+spl-token-2022 = { version = "0.5.0", features = ["no-entrypoint"] }
+

+ 2 - 0
tokens/token-2022/anchor/programs/basics/Xargo.toml

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

+ 139 - 0
tokens/token-2022/anchor/programs/basics/src/lib.rs

@@ -0,0 +1,139 @@
+use anchor_lang::prelude::*;
+use anchor_spl::associated_token::AssociatedToken;
+use anchor_spl::token_interface::{
+    self, Mint, MintTo, TokenAccount, TokenInterface, TransferChecked,
+};
+
+declare_id!("6qNqxkRF791FXFeQwqYQLEzAbGiqDULC5SSHVsfRoG89");
+
+#[program]
+pub mod anchor {
+
+    use super::*;
+
+    pub fn create_token(_ctx: Context<CreateToken>, _token_name: String) -> Result<()> {
+        msg!("Create Token");
+        Ok(())
+    }
+    pub fn create_token_account(_ctx: Context<CreateTokenAccount>) -> Result<()> {
+        msg!("Create Token Account");
+        Ok(())
+    }
+    pub fn create_associated_token_account(
+        _ctx: Context<CreateAssociatedTokenAccount>,
+    ) -> Result<()> {
+        msg!("Create Associated Token Account");
+        Ok(())
+    }
+    pub fn transfer_token(ctx: Context<TransferToken>, amount: u64) -> Result<()> {
+        let cpi_accounts = TransferChecked {
+            from: ctx.accounts.from.to_account_info().clone(),
+            mint: ctx.accounts.mint.to_account_info().clone(),
+            to: ctx.accounts.to_ata.to_account_info().clone(),
+            authority: ctx.accounts.signer.to_account_info(),
+        };
+        let cpi_program = ctx.accounts.token_program.to_account_info();
+        let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
+        token_interface::transfer_checked(cpi_context, amount, ctx.accounts.mint.decimals)?;
+        msg!("Transfer Token");
+        Ok(())
+    }
+    pub fn mint_token(ctx: Context<MintToken>, amount: u64) -> Result<()> {
+        let cpi_accounts = MintTo {
+            mint: ctx.accounts.mint.to_account_info().clone(),
+            to: ctx.accounts.receiver.to_account_info().clone(),
+            authority: ctx.accounts.signer.to_account_info(),
+        };
+        let cpi_program = ctx.accounts.token_program.to_account_info();
+        let cpi_context = CpiContext::new(cpi_program, cpi_accounts);
+        token_interface::mint_to(cpi_context, amount)?;
+        msg!("Mint Token");
+        Ok(())
+    }
+}
+
+#[derive(Accounts)]
+#[instruction(token_name: String)]
+pub struct CreateToken<'info> {
+    #[account(mut)]
+    pub signer: Signer<'info>,
+    #[account(
+        init,
+        payer = signer,
+        mint::decimals = 6,
+        mint::authority = signer.key(),
+        seeds = [b"token-2022-token", signer.key().as_ref(), token_name.as_bytes()],
+        bump,
+    )]
+    pub mint: InterfaceAccount<'info, Mint>,
+    pub system_program: Program<'info, System>,
+    pub token_program: Interface<'info, TokenInterface>,
+}
+
+#[derive(Accounts)]
+pub struct CreateTokenAccount<'info> {
+    #[account(mut)]
+    pub signer: Signer<'info>,
+    pub mint: InterfaceAccount<'info, Mint>,
+    #[account(
+        init,
+        token::mint = mint,
+        token::authority = signer,
+        payer = signer,
+        seeds = [b"token-2022-token-account", signer.key().as_ref(), mint.key().as_ref()],
+        bump,
+    )]
+    pub token_account: InterfaceAccount<'info, TokenAccount>,
+    pub system_program: Program<'info, System>,
+    pub token_program: Interface<'info, TokenInterface>,
+}
+
+#[derive(Accounts)]
+pub struct CreateAssociatedTokenAccount<'info> {
+    #[account(mut)]
+    pub signer: Signer<'info>,
+    pub mint: InterfaceAccount<'info, Mint>,
+    #[account(
+        init,
+        associated_token::mint = mint,
+        payer = signer,
+        associated_token::authority = signer,
+    )]
+    pub token_account: InterfaceAccount<'info, TokenAccount>,
+    pub system_program: Program<'info, System>,
+    pub token_program: Interface<'info, TokenInterface>,
+    pub associated_token_program: Program<'info, AssociatedToken>,
+}
+
+#[derive(Accounts)]
+
+pub struct TransferToken<'info> {
+    #[account(mut)]
+    pub signer: Signer<'info>,
+    #[account(mut)]
+    pub from: InterfaceAccount<'info, TokenAccount>,
+    pub to: SystemAccount<'info>,
+    #[account(
+        init,
+        associated_token::mint = mint,
+        payer = signer,
+        associated_token::authority = to
+    )]
+    pub to_ata: InterfaceAccount<'info, TokenAccount>,
+    #[account(mut)]
+    pub mint: InterfaceAccount<'info, Mint>,
+    pub token_program: Interface<'info, TokenInterface>,
+    pub system_program: Program<'info, System>,
+    pub associated_token_program: Program<'info, AssociatedToken>,
+}
+
+#[derive(Accounts)]
+pub struct MintToken<'info> {
+    #[account(mut)]
+    pub signer: Signer<'info>,
+    #[account(mut)]
+    pub mint: InterfaceAccount<'info, Mint>,
+    #[account(mut)]
+    pub receiver: InterfaceAccount<'info, TokenAccount>,
+    pub token_program: Interface<'info, TokenInterface>,
+}

+ 170 - 0
tokens/token-2022/anchor/tests/anchor.ts

@@ -0,0 +1,170 @@
+import * as anchor from "@coral-xyz/anchor";
+import { Program } from "@coral-xyz/anchor";
+import { Anchor } from "../target/types/anchor";
+
+describe("anchor", () => {
+  // Configure the client to use the local cluster.
+  anchor.setProvider(anchor.AnchorProvider.env());
+
+  const program = anchor.workspace.Anchor as Program<Anchor>;
+  const connection = program.provider.connection;
+  const TOKEN_2022_PROGRAM_ID = new anchor.web3.PublicKey(
+    "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
+  );
+  const payer = anchor.web3.Keypair.generate();
+  const ATA_PROGRAM_ID = new anchor.web3.PublicKey(
+    "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
+  );
+
+  const tokenName = "TestToken";
+  const [mint] = anchor.web3.PublicKey.findProgramAddressSync(
+    [
+      Buffer.from("token-2022-token"),
+      payer.publicKey.toBytes(),
+      Buffer.from(tokenName),
+    ],
+    program.programId
+  );
+  const [payerATA] = anchor.web3.PublicKey.findProgramAddressSync(
+    [
+      payer.publicKey.toBytes(),
+      TOKEN_2022_PROGRAM_ID.toBytes(),
+      mint.toBytes(),
+    ],
+    ATA_PROGRAM_ID
+  );
+
+  const receiver = anchor.web3.Keypair.generate();
+
+  const [receiverATA] = anchor.web3.PublicKey.findProgramAddressSync(
+    [
+      receiver.publicKey.toBytes(),
+      TOKEN_2022_PROGRAM_ID.toBytes(),
+      mint.toBytes(),
+    ],
+    ATA_PROGRAM_ID
+  );
+
+  it("Create Token-2022 Token", async () => {
+    await connection.requestAirdrop(receiver.publicKey, 1000000000);
+    await connection.requestAirdrop(payer.publicKey, 1000000000);
+    const tx = new anchor.web3.Transaction();
+
+    const ix = await program.methods
+      .createToken(tokenName)
+      .accounts({
+        mint: mint,
+        signer: payer.publicKey,
+        tokenProgram: TOKEN_2022_PROGRAM_ID,
+      })
+      .instruction();
+
+    tx.add(ix);
+
+    const sig = await anchor.web3.sendAndConfirmTransaction(
+      program.provider.connection,
+      tx,
+      [payer]
+    );
+    console.log("Your transaction signature", sig);
+  });
+
+  it("Initialize payer ATA", async () => {
+    const tx = new anchor.web3.Transaction();
+
+    const ix = await program.methods
+      .createAssociatedTokenAccount()
+      .accounts({
+        tokenAccount: payerATA,
+        mint: mint,
+        signer: payer.publicKey,
+        tokenProgram: TOKEN_2022_PROGRAM_ID,
+      })
+      .instruction();
+
+    tx.add(ix);
+
+    const sig = await anchor.web3.sendAndConfirmTransaction(
+      program.provider.connection,
+      tx,
+      [payer]
+    );
+    console.log("Your transaction signature", sig);
+  });
+
+  /*
+  // This instruction is included only as a reference, but is not required to run this test, because we are using "init" in the program's transfer instruction. The create_associated_token_account instruction on the program is provided as a reference as well.
+  it("Initialize receiver ATA", async () => {
+    const tx = new anchor.web3.Transaction();
+    const ix = await program.methods
+      .createAssociatedTokenAccount()
+      .accounts({
+        tokenAccount: receiverATA,
+        mint: mint,
+        signer: receiver.publicKey,
+        tokenProgram: TOKEN_2022_PROGRAM_ID,
+        associatedTokenProgram: ATA_PROGRAM_ID,
+      })
+      .signers([receiver])
+      .instruction();
+    tx.add(ix);
+    const sig = await anchor.web3.sendAndConfirmTransaction(
+      program.provider.connection,
+      tx,
+      [receiver]
+    );
+    console.log("Your transaction signature", sig);
+  });
+*/
+
+  it("Mint Token to payer", async () => {
+    const tx = new anchor.web3.Transaction();
+
+    const ix = await program.methods
+      .mintToken(new anchor.BN(200000000))
+      .accounts({
+        mint: mint,
+        signer: payer.publicKey,
+        receiver: payerATA,
+        tokenProgram: TOKEN_2022_PROGRAM_ID,
+      })
+      .signers([payer])
+      .instruction();
+
+    tx.add(ix);
+
+    const sig = await anchor.web3.sendAndConfirmTransaction(
+      program.provider.connection,
+      tx,
+      [payer]
+    );
+    console.log("Your transaction signature", sig);
+  });
+
+  // Using init in the transfer instruction, as init if needed is bot working with Token 2022 yet.
+  it("Transfer Token", async () => {
+    const tx = new anchor.web3.Transaction();
+
+    const ix = await program.methods
+      .transferToken(new anchor.BN(100))
+      .accounts({
+        mint: mint,
+        signer: payer.publicKey,
+        from: payerATA,
+        to: receiver.publicKey,
+        tokenProgram: TOKEN_2022_PROGRAM_ID,
+        associatedTokenProgram: ATA_PROGRAM_ID,
+        toAta: receiverATA,
+      })
+      .instruction();
+
+    tx.add(ix);
+
+    const sig = await anchor.web3.sendAndConfirmTransaction(
+      program.provider.connection,
+      tx,
+      [payer]
+    );
+    console.log("Your transaction signature", sig);
+  });
+});

+ 11 - 0
tokens/token-2022/anchor/tsconfig.json

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