Browse Source

token updates

jpcaulfi 3 years ago
parent
commit
766abd43ec
68 changed files with 650 additions and 1632 deletions
  1. 11 9
      README.md
  2. 0 3
      nfts/README.md
  3. 0 9
      nfts/mint/README.md
  4. 0 22
      nfts/mint/anchor/programs/mint-nft/Cargo.toml
  5. 0 165
      nfts/mint/anchor/programs/mint-nft/src/lib.rs
  6. 0 56
      nfts/mint/anchor/tests/test.ts
  7. 0 186
      nfts/mint/native/program/src/lib.rs
  8. 0 159
      nfts/mint/native/tests/test.ts
  9. 0 6
      nfts/nft_metadata.json
  10. 6 0
      reset.sh
  11. 12 1
      tokens/README.md
  12. 0 0
      tokens/mint-2/README.md
  13. 1 1
      tokens/mint-2/anchor/Anchor.toml
  14. 0 0
      tokens/mint-2/anchor/Cargo.toml
  15. 0 0
      tokens/mint-2/anchor/package.json
  16. 4 4
      tokens/mint-2/anchor/programs/mint-2/Cargo.toml
  17. 0 0
      tokens/mint-2/anchor/programs/mint-2/Xargo.toml
  18. 0 0
      tokens/mint-2/anchor/programs/mint-2/src/instructions/create_token_mint.rs
  19. 17 25
      tokens/mint-2/anchor/programs/mint-2/src/instructions/mint_to_wallet.rs
  20. 7 0
      tokens/mint-2/anchor/programs/mint-2/src/instructions/mod.rs
  21. 62 0
      tokens/mint-2/anchor/programs/mint-2/src/instructions/transfer_to_wallet.rs
  22. 13 2
      tokens/mint-2/anchor/programs/mint-2/src/lib.rs
  23. 44 12
      tokens/mint-2/anchor/tests/test.ts
  24. 0 0
      tokens/mint-2/anchor/tests/token_metadata.json
  25. 0 0
      tokens/mint-2/anchor/tsconfig.json
  26. 0 0
      tokens/mint-2/native/cicd.sh
  27. 0 0
      tokens/mint-2/native/package.json
  28. 0 0
      tokens/mint-2/native/program/Cargo.toml
  29. 59 16
      tokens/mint-2/native/program/src/instructions/create_token_mint.rs
  30. 19 10
      tokens/mint-2/native/program/src/instructions/mint_to_wallet.rs
  31. 3 0
      tokens/mint-2/native/program/src/instructions/mod.rs
  32. 81 0
      tokens/mint-2/native/program/src/instructions/transfer_to_wallet.rs
  33. 2 2
      tokens/mint-2/native/program/src/lib.rs
  34. 53 0
      tokens/mint-2/native/program/src/processor.rs
  35. 8 1
      tokens/mint-2/native/program/src/state/mint_state.rs
  36. 1 0
      tokens/mint-2/native/program/src/state/mod.rs
  37. 240 0
      tokens/mint-2/native/tests/test.ts
  38. 6 0
      tokens/mint-2/native/tests/token_metadata.json
  39. 1 1
      tokens/mint-2/native/tsconfig.json
  40. 0 14
      tokens/mint-to/anchor/Anchor.toml
  41. 0 13
      tokens/mint-to/anchor/Cargo.toml
  42. 0 14
      tokens/mint-to/anchor/package.json
  43. 0 21
      tokens/mint-to/anchor/programs/mint-token-to/Cargo.toml
  44. 0 2
      tokens/mint-to/anchor/programs/mint-token-to/Xargo.toml
  45. 0 5
      tokens/mint-to/anchor/programs/mint-token-to/src/instructions/mod.rs
  46. 0 10
      tokens/mint-to/anchor/tsconfig.json
  47. 0 8
      tokens/mint-to/native/cicd.sh
  48. 0 21
      tokens/mint-to/native/package.json
  49. 0 15
      tokens/mint-to/native/program/Cargo.toml
  50. 0 2
      tokens/mint-to/native/program/src/instructions/mod.rs
  51. 0 38
      tokens/mint-to/native/program/src/processor.rs
  52. 0 1
      tokens/mint-to/native/program/src/state/mod.rs
  53. 0 228
      tokens/mint-to/native/tests/test.ts
  54. 0 10
      tokens/mint-to/native/tsconfig.json
  55. 0 12
      tokens/mint/README.md
  56. 0 14
      tokens/mint/anchor/Anchor.toml
  57. 0 13
      tokens/mint/anchor/Cargo.toml
  58. 0 14
      tokens/mint/anchor/package.json
  59. 0 2
      tokens/mint/anchor/programs/mint-token/Xargo.toml
  60. 0 108
      tokens/mint/anchor/programs/mint-token/src/lib.rs
  61. 0 52
      tokens/mint/anchor/tests/test.ts
  62. 0 10
      tokens/mint/anchor/tsconfig.json
  63. 0 8
      tokens/mint/native/cicd.sh
  64. 0 21
      tokens/mint/native/package.json
  65. 0 14
      tokens/mint/native/program/Cargo.toml
  66. 0 122
      tokens/mint/native/program/src/lib.rs
  67. 0 140
      tokens/mint/native/tests/test.ts
  68. 0 10
      tokens/mint/native/tsconfig.json

+ 11 - 9
README.md

@@ -55,18 +55,20 @@ Regardless of what you may want to add on top of existing Solana programs, the n
 - [x] 3. Transferring SOL
 - [ ] 4. Transferring an account's ownership
 - [ ] 5. Destroying an account
-- ### [ ] Tokens
-- [x] 1. Creating an SPL Token
-- [x] 2. Mint tokens to a wallet
-- [ ] 3. Transferring tokens between wallets
-- ### [ ] NFTs
-- [x] 1. Creating an NFT
-- [ ] 2. Transferring an NFT
-- [ ] 3. Selling an NFT
-- [ ] 4. NFT metadata expanded
 - ### [ ] PDAs
 - [ ] 1. A simple PDA
 - [ ] 2. Dynamic PDA creation
+- ### [ ] Tokens
+- *Each example shows creating mint, minting to, and transferring*
+- [ ] 1. Mint and Mint Authority as keypairs
+- [x] 2. Mint as keypair and Mint Authority as PDA
+- [ ] 3. Mint and Mint Authority as PDAs
+- ### [ ] NFTs
+- *Each example shows creating mint, minting to, and transferring*
+- [ ] 1. Mint and Mint Authority as keypairs
+- [ ] 2. Mint as keypair and Mint Authority as PDA
+- [ ] 3. Mint and Mint Authority as PDAs
+- [ ] 4. NFT metadata expanded
 - ### [ ] Advanced PDAs
 - [ ] 1. Twitter
 - [ ] 2. Amazon

+ 0 - 3
nfts/README.md

@@ -1,3 +0,0 @@
-### :warning: All NFT examples are on devnet!
-
-`https://api.devnet.solana.com/`

+ 0 - 9
nfts/mint/README.md

@@ -1,9 +0,0 @@
-#  Create a New NFT Mint
-
-:notebook_with_decorative_cover: Note: This example is built off of [Mint Token](../../tokens/mint/README.md) and [Mint Token To](../../tokens/mint-to/README.md). If you get stuck, check out those examples.   
-
-___
-
-An NFT is obviously just a token on Solana! So, the process is the same for creating an NFT. There's just a few additional steps:
-- Decimals are set to 0
-- Minting must be disabled after one token is minted (ie. cap the supply at 1).

+ 0 - 22
nfts/mint/anchor/programs/mint-nft/Cargo.toml

@@ -1,22 +0,0 @@
-[package]
-name = "mint-nft"
-version = "0.1.0"
-description = "Created with Anchor"
-edition = "2021"
-
-[lib]
-crate-type = ["cdylib", "lib"]
-name = "mint_nft"
-
-[features]
-no-entrypoint = []
-no-idl = []
-no-log-ix-name = []
-cpi = ["no-entrypoint"]
-default = []
-
-[dependencies]
-anchor-lang = "0.24.2"
-anchor-spl = "0.24.2"
-mpl-token-metadata = { version="1.2.5", features = [ "no-entrypoint" ] }
-spl-token = { version="3.3.0", features = [ "no-entrypoint" ] }

+ 0 - 165
nfts/mint/anchor/programs/mint-nft/src/lib.rs

@@ -1,165 +0,0 @@
-use {
-    anchor_lang::{
-        prelude::*,
-        solana_program::program::invoke,
-        system_program,
-    },
-    anchor_spl::{
-        token,
-        associated_token,
-    },
-    mpl_token_metadata::instruction as mpl_instruction,
-    spl_token::instruction::AuthorityType,
-};
-
-
-declare_id!("AaWo2HWYXs5YtZoV4mPN1ZA8e8gb3wHqrXxQRxTWBJBC");
-
-
-#[program]
-pub mod mint_nft {
-    use super::*;
-
-    pub fn mint_token(
-        ctx: Context<MintToken>, 
-        metadata_title: String, 
-        metadata_symbol: String, 
-        metadata_uri: String,
-    ) -> Result<()> {
-
-        msg!("Creating mint account...");
-        msg!("Mint: {}", &ctx.accounts.mint_account.key());
-        system_program::create_account(
-            CpiContext::new(
-                ctx.accounts.token_program.to_account_info(),
-                system_program::CreateAccount {
-                    from: ctx.accounts.mint_authority.to_account_info(),
-                    to: ctx.accounts.mint_account.to_account_info(),
-                },
-            ),
-            (Rent::get()?).minimum_balance(token::Mint::LEN),
-            token::Mint::LEN as u64,
-            &ctx.accounts.token_program.key(),
-        )?;
-
-        msg!("Initializing mint account...");
-        msg!("Mint: {}", &ctx.accounts.mint_account.key());
-        token::initialize_mint(
-            CpiContext::new(
-                ctx.accounts.token_program.to_account_info(),
-                token::InitializeMint {
-                    mint: ctx.accounts.mint_account.to_account_info(),
-                    rent: ctx.accounts.rent.to_account_info(),
-                },
-            ),
-            0,                                              // 0 Decimals (NFT)
-            &ctx.accounts.mint_authority.key(),
-            Some(&ctx.accounts.mint_authority.key()),
-        )?;
-
-        msg!("Creating metadata account...");
-        msg!("Metadata account address: {}", &ctx.accounts.metadata_account.key());
-        invoke(
-            &mpl_instruction::create_metadata_accounts_v2(
-                ctx.accounts.token_metadata_program.key(),      // Program ID (the Token Metadata Program)
-                ctx.accounts.metadata_account.key(),            // Metadata account
-                ctx.accounts.mint_account.key(),                // Mint account
-                ctx.accounts.mint_authority.key(),              // Mint authority
-                ctx.accounts.mint_authority.key(),              // Payer
-                ctx.accounts.mint_authority.key(),              // Update authority
-                metadata_title,                                 // Name
-                metadata_symbol,                                // Symbol
-                metadata_uri,                                   // URI
-                None,                                           // Creators
-                0,                                              // Seller fee basis points
-                true,                                           // Update authority is signer
-                false,                                          // Is mutable
-                None,                                           // Collection
-                None,                                           // Uses
-            ),
-            &[
-                ctx.accounts.metadata_account.to_account_info(),
-                ctx.accounts.mint_account.to_account_info(),
-                ctx.accounts.mint_authority.to_account_info(),
-                ctx.accounts.token_metadata_program.to_account_info(),
-                ctx.accounts.rent.to_account_info(),
-            ],
-        )?;
-
-        msg!("NFT mint created successfully.");
-
-        msg!("Creating token account...");
-        msg!("Token Address: {}", &ctx.accounts.token_account.key());    
-        associated_token::create(
-            CpiContext::new(
-                ctx.accounts.associated_token_program.to_account_info(),
-                associated_token::Create {
-                    payer: ctx.accounts.mint_authority.to_account_info(),
-                    associated_token: ctx.accounts.token_account.to_account_info(),
-                    authority: ctx.accounts.mint_authority.to_account_info(),
-                    mint: ctx.accounts.mint_account.to_account_info(),
-                    system_program: ctx.accounts.system_program.to_account_info(),
-                    token_program: ctx.accounts.token_program.to_account_info(),
-                    rent: ctx.accounts.rent.to_account_info(),
-                },
-            ),
-        )?;
-
-        msg!("Minting NFT to token account...");
-        msg!("NFT Mint: {}", &ctx.accounts.mint_account.to_account_info().key());   
-        msg!("Token Address: {}", &ctx.accounts.token_account.key());     
-        token::mint_to(
-            CpiContext::new(
-                ctx.accounts.token_program.to_account_info(),
-                token::MintTo {
-                    mint: ctx.accounts.mint_account.to_account_info(),
-                    to: ctx.accounts.token_account.to_account_info(),
-                    authority: ctx.accounts.mint_authority.to_account_info(),
-                },
-            ),
-            1,
-        )?;
-
-        msg!("NFT minted to wallet successfully.");
-
-        msg!("Disabling future minting...");
-        msg!("NFT Mint: {}", &ctx.accounts.mint_account.to_account_info().key());   
-        token::set_authority(
-            CpiContext::new(
-                ctx.accounts.token_program.to_account_info(),
-                token::SetAuthority {
-                    current_authority: ctx.accounts.mint_authority.to_account_info(),
-                    account_or_mint: ctx.accounts.mint_account.to_account_info(),
-                },
-            ),
-            AuthorityType::MintTokens,
-            None
-        )?;
-
-        msg!("NFT minting disabled successfully.");
-        msg!("NFT mint process completed successfully.");
-
-        Ok(())
-    }
-}
-
-
-#[derive(Accounts)]
-pub struct MintToken<'info> {
-    /// CHECK: We're about to create this with Metaplex
-    #[account(mut)]
-    pub metadata_account: UncheckedAccount<'info>,
-    #[account(mut)]
-    pub mint_account: Signer<'info>,
-    /// CHECK: We're about to create this with Anchor
-    #[account(mut)]
-    pub token_account: UncheckedAccount<'info>,
-    #[account(mut)]
-    pub mint_authority: Signer<'info>,
-    pub rent: Sysvar<'info, Rent>,
-    pub system_program: Program<'info, System>,
-    pub token_program: Program<'info, token::Token>,
-    pub associated_token_program: Program<'info, associated_token::AssociatedToken>,
-    /// CHECK: Metaplex will check this
-    pub token_metadata_program: UncheckedAccount<'info>,
-}

+ 0 - 56
nfts/mint/anchor/tests/test.ts

@@ -1,56 +0,0 @@
-import * as anchor from "@project-serum/anchor";
-import { MintNft } from "../target/types/mint_nft";
-
-
-const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey(
-  "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
-);
-
-const testTokenTitle = "Solana Platinum NFT";
-const testTokenSymbol = "SOLP";
-const testTokenUri = "https://raw.githubusercontent.com/solana-developers/program-examples/main/nfts/nft_metadata.json";
-
-
-describe("mint-token", () => {
-  
-  const provider = anchor.AnchorProvider.env();
-  anchor.setProvider(provider);
-  const payer = provider.wallet as anchor.Wallet;
-  const program = anchor.workspace.MintNft as anchor.Program<MintNft>;
-
-  it("Mint!", async () => {
-
-    const mintKeypair: anchor.web3.Keypair = anchor.web3.Keypair.generate();
-    console.log(`New token: ${mintKeypair.publicKey}`);
-
-    const metadataAddress = (await anchor.web3.PublicKey.findProgramAddress(
-      [
-        Buffer.from("metadata"),
-        TOKEN_METADATA_PROGRAM_ID.toBuffer(),
-        mintKeypair.publicKey.toBuffer(),
-      ],
-      TOKEN_METADATA_PROGRAM_ID
-    ))[0];
-
-    const tokenAddress = await anchor.utils.token.associatedAddress({
-      mint: mintKeypair.publicKey,
-      owner: payer.publicKey
-    });
-
-    await program.methods.mintToken(
-      testTokenTitle, testTokenSymbol, testTokenUri
-    )
-    .accounts({
-      metadataAccount: metadataAddress,
-      mintAccount: mintKeypair.publicKey,
-      tokenAccount: tokenAddress,
-      mintAuthority: payer.publicKey,
-      systemProgram: anchor.web3.SystemProgram.programId,
-      tokenProgram: anchor.utils.token.TOKEN_PROGRAM_ID,
-      tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
-      associatedTokenProgram: anchor.utils.token.ASSOCIATED_PROGRAM_ID,
-    })
-    .signers([payer.payer, mintKeypair])
-    .rpc();
-  });
-});

+ 0 - 186
nfts/mint/native/program/src/lib.rs

@@ -1,186 +0,0 @@
-use {
-    borsh::{
-        BorshSerialize, BorshDeserialize,
-    },
-    solana_program::{
-        account_info::{next_account_info, AccountInfo}, 
-        entrypoint, 
-        entrypoint::ProgramResult, 
-        msg, 
-        program::invoke,
-        program_pack::Pack,
-        pubkey::Pubkey,
-        rent::Rent,
-        system_instruction,
-        sysvar::Sysvar,
-    },
-    spl_token::{
-        instruction as token_instruction,
-        state::Mint,
-    },
-    spl_associated_token_account::{
-        instruction as token_account_instruction,
-    },
-    mpl_token_metadata::{
-        instruction as mpl_instruction,
-    },
-};
-
-
-entrypoint!(process_instruction);
-
-
-fn process_instruction(
-    _program_id: &Pubkey,
-    accounts: &[AccountInfo],
-    instruction_data: &[u8],
-) -> ProgramResult {
-
-    let accounts_iter = &mut accounts.iter();
-
-    let metadata_account = next_account_info(accounts_iter)?;
-    let mint_account = next_account_info(accounts_iter)?;
-    let token_account = next_account_info(accounts_iter)?;
-    let mint_authority = 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)?;
-    let associated_token_program = next_account_info(accounts_iter)?;
-    let token_metadata_program = next_account_info(accounts_iter)?;
-
-    let nft_metadata = NftMetadata::try_from_slice(instruction_data)?;
-    
-    msg!("Creating mint account...");
-    msg!("Mint: {}", mint_account.key);
-    invoke(
-        &system_instruction::create_account(
-            &mint_authority.key,
-            &mint_account.key,
-            (Rent::get()?).minimum_balance(Mint::LEN),
-            Mint::LEN as u64,
-            &token_program.key,
-        ),
-        &[
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_program.clone(),
-        ]
-    )?;
-
-    msg!("Initializing mint account...");
-    msg!("Mint: {}", mint_account.key);
-    invoke(
-        &token_instruction::initialize_mint(
-            &token_program.key,
-            &mint_account.key,
-            &mint_authority.key,
-            Some(&mint_authority.key),
-            9,                              // 9 Decimals
-        )?,
-        &[
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_program.clone(),
-            rent.clone(),
-        ]
-    )?;
-
-    msg!("Creating metadata account...");
-    msg!("Metadata account address: {}", metadata_account.key);
-    invoke(
-        &mpl_instruction::create_metadata_accounts_v2(
-            *token_metadata_program.key,    // Program ID (the Token Metadata Program)
-            *metadata_account.key,          // Metadata Account
-            *mint_account.key,              // Mint Account
-            *mint_authority.key,            // Mint Authority
-            *mint_authority.key,            // Payer
-            *mint_authority.key,            // Update Authority
-            nft_metadata.title,           // Name
-            nft_metadata.symbol,          // Symbol
-            nft_metadata.uri,             // URI
-            None,                           // Creators
-            0,                              // Seller fee basis points
-            true,                           // Update authority is signer
-            false,                          // Is mutable
-            None,                           // Collection
-            None,                           // Uses
-        ),
-        &[
-            metadata_account.clone(),
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_metadata_program.clone(),
-            rent.clone(),
-        ],
-    )?;
-
-    msg!("NFT mint created successfully.");
-
-    msg!("Creating token account...");
-    msg!("Token Address: {}", token_account.key);    
-    invoke(
-        &token_account_instruction::create_associated_token_account(
-            &mint_authority.key,
-            &mint_authority.key,
-            &mint_account.key,
-        ),
-        &[
-            mint_account.clone(),
-            token_account.clone(),
-            mint_authority.clone(),
-            token_program.clone(),
-            associated_token_program.clone(),
-        ]
-    )?;
-
-    msg!("Minting NFT to token account...");
-    msg!("NFT Mint: {}", mint_account.key);   
-    msg!("Token Address: {}", token_account.key);
-    invoke(
-        &token_instruction::mint_to(
-            &token_program.key,
-            &mint_account.key,
-            &token_account.key,
-            &mint_authority.key,
-            &[&mint_authority.key],
-            1,
-        )?,
-        &[
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_account.clone(),
-            token_program.clone(),
-            rent.clone(),
-        ]
-    )?;
-
-    msg!("Disabling future minting...");
-    msg!("NFT Mint: {}", mint_account.key);   
-    invoke(
-        &token_instruction::set_authority(
-            &token_program.key, 
-            &mint_account.key, 
-            None, 
-            token_instruction::AuthorityType::MintTokens, 
-            &mint_authority.key, 
-            &[&mint_authority.key]
-        )?,
-        &[
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_program.clone(),
-        ],
-    )?;
-
-    msg!("NFT minting disabled successfully.");
-    msg!("Token mint process completed successfully.");
-
-    Ok(())
-}
-
-#[derive(BorshSerialize, BorshDeserialize, Debug)]
-pub struct NftMetadata {
-    title: String,
-    symbol: String,
-    uri: String,
-}

+ 0 - 159
nfts/mint/native/tests/test.ts

@@ -1,159 +0,0 @@
-import {
-    Connection,
-    Keypair,
-    PublicKey,
-    SystemProgram,
-    SYSVAR_RENT_PUBKEY,
-    TransactionInstruction,
-    Transaction,
-    sendAndConfirmTransaction,
-} from '@solana/web3.js';
-import { 
-    ASSOCIATED_TOKEN_PROGRAM_ID, 
-    TOKEN_PROGRAM_ID, 
-    getAssociatedTokenAddress 
-} from '@solana/spl-token';
-import * as borsh from "borsh";
-import { Buffer } from "buffer";
-
-
-const TOKEN_METADATA_PROGRAM_ID = new PublicKey(
-    "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
-);
-
-
-function createKeypairFromFile(path: string): Keypair {
-    return Keypair.fromSecretKey(
-        Buffer.from(JSON.parse(require('fs').readFileSync(path, "utf-8")))
-    )
-};
-
-
-describe("mint-token", () => {
-
-    const connection = new Connection(`http://api.devnet.solana.com/`, 'confirmed');
-    const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
-    const program = createKeypairFromFile('./program/target/so/program-keypair.json');
-
-    class Assignable {
-        constructor(properties) {
-            Object.keys(properties).map((key) => {
-                return (this[key] = properties[key]);
-            });
-        };
-    };
-
-    class TokenMetadata extends Assignable {
-        toBuffer() {
-            return Buffer.from(borsh.serialize(TokenMetadataSchema, this));
-        }
-    };
-
-    const TokenMetadataSchema = new Map([
-        [
-            TokenMetadata, {
-                kind: 'struct',
-                fields: [
-                    ['title', 'string'],
-                    ['symbol', 'string'],
-                    ['uri', 'string'],
-                ]
-            }
-        ]
-    ]);
-
-
-    const mintKeypair: Keypair = Keypair.generate();
-    console.log(`New token: ${mintKeypair.publicKey}`);
-
-    const metadata = new TokenMetadata({
-        title: "Solana Gold",
-        symbol: "GOLDSOL",
-        uri: "https://raw.githubusercontent.com/solana-developers/program-examples/main/nfts/nft_metadata.json",
-    });
-  
-    it("Mint!", async () => {
-
-        const metadataAddress = (await PublicKey.findProgramAddress(
-            [
-              Buffer.from("metadata"),
-              TOKEN_METADATA_PROGRAM_ID.toBuffer(),
-              mintKeypair.publicKey.toBuffer(),
-            ],
-            TOKEN_METADATA_PROGRAM_ID
-        ))[0];
-
-        const tokenAddress = await getAssociatedTokenAddress(
-            mintKeypair.publicKey,
-            payer.publicKey
-        );
-
-        let ix = new TransactionInstruction({
-            keys: [
-                // Metadata account
-                {
-                    pubkey: metadataAddress,
-                    isSigner: false,
-                    isWritable: true,
-                },
-                // Mint account
-                {
-                    pubkey: mintKeypair.publicKey,
-                    isSigner: true,
-                    isWritable: true,
-                },
-                // Associated token account
-                {
-                    pubkey: tokenAddress,
-                    isSigner: false,
-                    isWritable: true,
-                },
-                // Mint Authority
-                {
-                    pubkey: payer.publicKey,
-                    isSigner: true,
-                    isWritable: false,
-                },
-                // Rent account
-                {
-                    pubkey: SYSVAR_RENT_PUBKEY,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // System program
-                {
-                    pubkey: SystemProgram.programId,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Token program
-                {
-                    pubkey: TOKEN_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Associated program
-                {
-                    pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Token metadata program
-                {
-                    pubkey: TOKEN_METADATA_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-            ],
-            programId: program.publicKey,
-            data: metadata.toBuffer(),
-        });
-
-        await sendAndConfirmTransaction(
-            connection, 
-            new Transaction().add(ix),
-            [payer, mintKeypair]
-        );
-    });
-  });
-  

+ 0 - 6
nfts/nft_metadata.json

@@ -1,6 +0,0 @@
-{
-    "name": "Solana Platinum NFT",
-    "symbol": "SOLP",
-    "description": "Solana NFT - Platinum",
-    "image": "https://pbs.twimg.com/profile_images/1440155120788918286/HKyfyx-i_400x400.png"
-}

+ 6 - 0
reset.sh

@@ -0,0 +1,6 @@
+for x in $(solana program show --programs | awk 'RP==0 {print $1}'); do 
+    if [[ $x != "Program" ]]; 
+    then 
+        solana program close $x;
+    fi
+done

+ 12 - 1
tokens/README.md

@@ -13,4 +13,15 @@ How they work:
 - :apple: `Mint Account` - stores information about the token.
 - :handbag: `Associated Token Account` - stores a specific balance of the Mint Account (this is essentially a counter).
 
-> You can read all about tokens in [Solana's official SPL Token documentation](https://spl.solana.com/token).
+> You can read all about tokens in [Solana's official SPL Token documentation](https://spl.solana.com/token).
+
+### This Folder
+
+All examples in this folder demonstrate the following:
+- How to create a new token mint.
+- How to mint some amount of this token to a wallet.
+- How to transfer this token to a wallet.
+Each example differs in a few key aspects:
+- `mint-1` - The **Mint** and the **Mint Authority** are generated keypairs.
+- `mint-2` - The **Mint** is a generated keypair. The **Mint Authority** is a Program Derived Address (PDA).
+- `mint-3` - The **Mint** and the **Mint Authority** are Program Derived Addresses (PDAs).

+ 0 - 0
tokens/mint-to/README.md → tokens/mint-2/README.md


+ 1 - 1
nfts/mint/anchor/Anchor.toml → tokens/mint-2/anchor/Anchor.toml

@@ -1,7 +1,7 @@
 [features]
 seeds = false
 [programs.devnet]
-mint_nft = "AaWo2HWYXs5YtZoV4mPN1ZA8e8gb3wHqrXxQRxTWBJBC"
+mint_2 = "8vbaY8zv9r3AgeLjyAr7LEprJwLN5Jjus97crJBD2AV2"
 
 [registry]
 url = "https://anchor.projectserum.com"

+ 0 - 0
nfts/mint/anchor/Cargo.toml → tokens/mint-2/anchor/Cargo.toml


+ 0 - 0
nfts/mint/anchor/package.json → tokens/mint-2/anchor/package.json


+ 4 - 4
tokens/mint/anchor/programs/mint-token/Cargo.toml → tokens/mint-2/anchor/programs/mint-2/Cargo.toml

@@ -1,12 +1,12 @@
 [package]
-name = "mint-token"
+name = "mint-2"
 version = "0.1.0"
 description = "Created with Anchor"
 edition = "2021"
 
 [lib]
 crate-type = ["cdylib", "lib"]
-name = "mint_token"
+name = "mint_2"
 
 [features]
 no-entrypoint = []
@@ -16,6 +16,6 @@ cpi = ["no-entrypoint"]
 default = []
 
 [dependencies]
-anchor-lang = "0.24.2"
-anchor-spl = "0.24.2"
+anchor-lang = "0.25.0"
+anchor-spl = "0.25.0"
 mpl-token-metadata = { version="1.2.5", features = [ "no-entrypoint" ] }

+ 0 - 0
nfts/mint/anchor/programs/mint-nft/Xargo.toml → tokens/mint-2/anchor/programs/mint-2/Xargo.toml


+ 0 - 0
tokens/mint-to/anchor/programs/mint-token-to/src/instructions/create_token_mint.rs → tokens/mint-2/anchor/programs/mint-2/src/instructions/create_token_mint.rs


+ 17 - 25
tokens/mint-to/anchor/programs/mint-token-to/src/instructions/mint_to_wallet.rs → tokens/mint-2/anchor/programs/mint-2/src/instructions/mint_to_wallet.rs

@@ -14,25 +14,6 @@ pub fn mint_to_wallet(
     mint_authority_pda_bump: u8,
 ) -> Result<()> {
 
-    let mint_authority = &mut ctx.accounts.mint_authority;
-
-    msg!("Creating token account...");
-    msg!("Token Address: {}", &ctx.accounts.token_account.key());    
-    associated_token::create(
-        CpiContext::new(
-            ctx.accounts.associated_token_program.to_account_info(),
-            associated_token::Create {
-                payer: ctx.accounts.payer.to_account_info(),
-                associated_token: ctx.accounts.token_account.to_account_info(),
-                authority: ctx.accounts.payer.to_account_info(),
-                mint: ctx.accounts.mint_account.to_account_info(),
-                system_program: ctx.accounts.system_program.to_account_info(),
-                token_program: ctx.accounts.token_program.to_account_info(),
-                rent: ctx.accounts.rent.to_account_info(),
-            },
-        ),
-    )?;
-
     msg!("Minting token to token account...");
     msg!("Mint: {}", &ctx.accounts.mint_account.to_account_info().key());   
     msg!("Token Address: {}", &ctx.accounts.token_account.key());     
@@ -42,7 +23,7 @@ pub fn mint_to_wallet(
             token::MintTo {
                 mint: ctx.accounts.mint_account.to_account_info(),
                 to: ctx.accounts.token_account.to_account_info(),
-                authority: mint_authority.to_account_info(),
+                authority: ctx.accounts.mint_authority.to_account_info(),
             },
             &[&[
                 b"mint_authority_", 
@@ -62,17 +43,28 @@ pub fn mint_to_wallet(
 #[derive(Accounts)]
 #[instruction(amount: u64, mint_authority_pda_bump: u8)]
 pub struct MintToWallet<'info> {
-    #[account(mut)]
+    #[account(
+        mut,
+        mint::decimals = 9,
+        mint::authority = mint_authority.key(),
+    )]
     pub mint_account: Account<'info, token::Mint>,
     #[account(
         mut, 
-        seeds = [b"mint_authority_", mint_account.key().as_ref()],
+        seeds = [
+            b"mint_authority_", 
+            mint_account.key().as_ref()
+        ],
         bump = mint_authority_pda_bump
     )]
     pub mint_authority: Account<'info, MintAuthorityPda>,
-    /// CHECK: We're about to create this with Anchor
-    #[account(mut)]
-    pub token_account: UncheckedAccount<'info>,
+    #[account(
+        init,
+        payer = payer,
+        associated_token::mint = mint_account,
+        associated_token::authority = payer,
+    )]
+    pub token_account: Account<'info, token::TokenAccount>,
     #[account(mut)]
     pub payer: Signer<'info>,
     pub rent: Sysvar<'info, Rent>,

+ 7 - 0
tokens/mint-2/anchor/programs/mint-2/src/instructions/mod.rs

@@ -0,0 +1,7 @@
+pub mod create_token_mint;
+pub mod mint_to_wallet;
+pub mod transfer_to_wallet;
+
+pub use create_token_mint::*;
+pub use mint_to_wallet::*;
+pub use transfer_to_wallet::*;

+ 62 - 0
tokens/mint-2/anchor/programs/mint-2/src/instructions/transfer_to_wallet.rs

@@ -0,0 +1,62 @@
+use {
+    anchor_lang::prelude::*,
+    anchor_spl::{
+        token,
+        associated_token,
+    },
+};
+
+
+pub fn transfer_to_wallet(
+    ctx: Context<TransferToWallet>, 
+    amount: u64,
+) -> Result<()> {
+
+    msg!("Transferring {} tokens to new token account...", amount);
+    msg!("Mint: {}", &ctx.accounts.mint_account.to_account_info().key());   
+    msg!("Owner Token Address: {}", &ctx.accounts.owner_token_account.key());  
+    msg!("Recipient Token Address: {}", &ctx.accounts.recipient_token_account.key());
+    token::transfer(
+        CpiContext::new(
+            ctx.accounts.token_program.to_account_info(),
+            token::Transfer {
+                from: ctx.accounts.owner_token_account.to_account_info(),
+                to: ctx.accounts.recipient_token_account.to_account_info(),
+                authority: ctx.accounts.owner.to_account_info(),
+            },
+        ),
+        amount,
+    )?;
+
+    msg!("Tokens transferred to wallet successfully.");
+
+    Ok(())
+}
+
+
+#[derive(Accounts)]
+pub struct TransferToWallet<'info> {
+    #[account(mut)]
+    pub mint_account: Account<'info, token::Mint>,
+    #[account(
+        mut,
+        associated_token::mint = mint_account,
+        associated_token::authority = owner,
+    )]
+    pub owner_token_account: Account<'info, token::TokenAccount>,
+    #[account(
+        init,
+        payer = recipient,
+        associated_token::mint = mint_account,
+        associated_token::authority = recipient,
+    )]
+    pub recipient_token_account: Account<'info, token::TokenAccount>,
+    #[account(mut)]
+    pub owner: Signer<'info>,
+    #[account(mut)]
+    pub recipient: Signer<'info>,
+    pub rent: Sysvar<'info, Rent>,
+    pub system_program: Program<'info, System>,
+    pub token_program: Program<'info, token::Token>,
+    pub associated_token_program: Program<'info, associated_token::AssociatedToken>,
+}

+ 13 - 2
tokens/mint-to/anchor/programs/mint-token-to/src/lib.rs → tokens/mint-2/anchor/programs/mint-2/src/lib.rs

@@ -5,11 +5,11 @@ pub mod instructions;
 use instructions::*;
 
 
-declare_id!("86NFhnnuV8SNEuHdqNtjCFeGCknpjDXEbV7b3zBefJ11");
+declare_id!("8vbaY8zv9r3AgeLjyAr7LEprJwLN5Jjus97crJBD2AV2");
 
 
 #[program]
-pub mod mint_token_to {
+pub mod mint_2 {
     use super::*;
 
     pub fn create_token_mint(
@@ -41,4 +41,15 @@ pub mod mint_token_to {
             mint_authority_pda_bump,
         )
     }
+
+    pub fn transfer_to_wallet(
+        ctx: Context<TransferToWallet>, 
+        amount: u64,
+    ) -> Result<()> {
+
+        transfer_to_wallet::transfer_to_wallet(
+            ctx, 
+            amount,
+        )
+    }
 }

+ 44 - 12
tokens/mint-to/anchor/tests/test.ts → tokens/mint-2/anchor/tests/test.ts

@@ -1,5 +1,5 @@
 import * as anchor from "@project-serum/anchor";
-import { MintTokenTo } from "../target/types/mint_token_to";
+import { Mint2 } from "../target/types/mint_2";
 
 
 const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey(
@@ -12,11 +12,11 @@ describe("mint-token", () => {
   const provider = anchor.AnchorProvider.env();
   anchor.setProvider(provider);
   const payer = provider.wallet as anchor.Wallet;
-  const program = anchor.workspace.MintTokenTo as anchor.Program<MintTokenTo>;
+  const program = anchor.workspace.Mint2 as anchor.Program<Mint2>;
 
-  const testTokenTitle = "Solana Gold G";
+  const testTokenTitle = "Solana Gold";
   const testTokenSymbol = "GOLDSOL";
-  const testTokenUri = "https://raw.githubusercontent.com/solana-developers/program-examples/main/tokens/token_metadata.json";
+  const testTokenUri = "https://raw.githubusercontent.com/solana-developers/program-examples/main/tokens/mint-2/anchor/tests/token_metadata.json";
 
   const mintKeypair: anchor.web3.Keypair = anchor.web3.Keypair.generate();
   console.log(`New token: ${mintKeypair.publicKey}`);
@@ -30,17 +30,15 @@ describe("mint-token", () => {
       ],
       program.programId,
     );
-    console.log(`PDA: ${mintAuthorityPda}`);
-    console.log(`Bump: ${mintAuthorityPdaBump}`);
 
-    const [metadataAddress, metadataBump] = await anchor.web3.PublicKey.findProgramAddress(
+    const metadataAddress = (await anchor.web3.PublicKey.findProgramAddress(
       [
         Buffer.from("metadata"),
         TOKEN_METADATA_PROGRAM_ID.toBuffer(),
         mintKeypair.publicKey.toBuffer(),
       ],
       TOKEN_METADATA_PROGRAM_ID
-    );
+    ))[0];
 
     await program.methods.createTokenMint(
       testTokenTitle, testTokenSymbol, testTokenUri, mintAuthorityPdaBump
@@ -68,8 +66,6 @@ describe("mint-token", () => {
       ],
       program.programId,
     );
-    console.log(`PDA: ${mintAuthorityPda}`);
-    console.log(`Bump: ${mintAuthorityPdaBump}`);
 
     const amountToMint = 1;
 
@@ -77,7 +73,6 @@ describe("mint-token", () => {
         mint: mintKeypair.publicKey,
         owner: payer.publicKey
     });
-    console.log(`Token Address: ${tokenAddress}`);
 
     await program.methods.mintToWallet(
       new anchor.BN(amountToMint), mintAuthorityPdaBump
@@ -92,7 +87,44 @@ describe("mint-token", () => {
       tokenProgram: anchor.utils.token.TOKEN_PROGRAM_ID,
       associatedTokenProgram: anchor.utils.token.ASSOCIATED_PROGRAM_ID,
     })
-    // .signers([payer.payer])
+    .signers([payer.payer])
+    .rpc();
+  });
+
+  it("Transfer to a wallet!", async () => {
+
+    const recipientWallet = anchor.web3.Keypair.generate();
+    await provider.connection.confirmTransaction(
+        await provider.connection.requestAirdrop(recipientWallet.publicKey, 2 * anchor.web3.LAMPORTS_PER_SOL)
+    );
+    console.log(`Recipient Pubkey: ${recipientWallet.publicKey}`);
+
+    const amountToTransfer = 1;
+
+    const ownerTokenAddress = await anchor.utils.token.associatedAddress({
+        mint: mintKeypair.publicKey,
+        owner: payer.publicKey
+    });
+    const recipientTokenAddress = await anchor.utils.token.associatedAddress({
+        mint: mintKeypair.publicKey,
+        owner: recipientWallet.publicKey
+    });
+
+    await program.methods.transferToWallet(
+      new anchor.BN(amountToTransfer)
+    )
+    .accounts({
+      mintAccount: mintKeypair.publicKey,
+      ownerTokenAccount: ownerTokenAddress,
+      recipientTokenAccount: recipientTokenAddress,
+      owner: payer.publicKey,
+      recipient: recipientWallet.publicKey,
+      rent: anchor.web3.SYSVAR_RENT_PUBKEY,
+      systemProgram: anchor.web3.SystemProgram.programId,
+      tokenProgram: anchor.utils.token.TOKEN_PROGRAM_ID,
+      associatedTokenProgram: anchor.utils.token.ASSOCIATED_PROGRAM_ID,
+    })
+    .signers([payer.payer, recipientWallet])
     .rpc();
   });
 });

+ 0 - 0
tokens/token_metadata.json → tokens/mint-2/anchor/tests/token_metadata.json


+ 0 - 0
nfts/mint/anchor/tsconfig.json → tokens/mint-2/anchor/tsconfig.json


+ 0 - 0
nfts/mint/native/cicd.sh → tokens/mint-2/native/cicd.sh


+ 0 - 0
nfts/mint/native/package.json → tokens/mint-2/native/package.json


+ 0 - 0
nfts/mint/native/program/Cargo.toml → tokens/mint-2/native/program/Cargo.toml


+ 59 - 16
tokens/mint-to/native/program/src/instructions/create_mint.rs → tokens/mint-2/native/program/src/instructions/create_token_mint.rs

@@ -3,13 +3,16 @@ use {
         account_info::{next_account_info, AccountInfo}, 
         entrypoint::ProgramResult, 
         msg, 
-        program::invoke,
+        program::invoke_signed,
+        program_pack::Pack,
+        pubkey::Pubkey,
         rent::Rent,
         system_instruction,
         sysvar::Sysvar,
     },
     spl_token::{
         instruction as token_instruction,
+        state::Mint,
     },
     mpl_token_metadata::{
         instruction as mpl_instruction,
@@ -17,45 +20,73 @@ use {
 };
 
 
-pub fn create_mint(
+pub fn create_token_mint(
+    program_id: &Pubkey,
     accounts: &[AccountInfo],
     token_title: String,
     token_symbol: String,
     token_uri: String,
+    mint_authority_pda_bump: u8,
 ) -> ProgramResult {
 
-    const MINT_SIZE: u64 = 82;
-
     let accounts_iter = &mut accounts.iter();
 
     let mint_account = next_account_info(accounts_iter)?;
-    let metadata_account = next_account_info(accounts_iter)?;
     let mint_authority = next_account_info(accounts_iter)?;
+    let metadata_account = 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 system_program = next_account_info(accounts_iter)?;
     let token_program = next_account_info(accounts_iter)?;
     let token_metadata_program = next_account_info(accounts_iter)?;
+
+    msg!("Creating mint authority...");
+    msg!("Mint Authority: {}", mint_authority.key);
+    invoke_signed(
+        &system_instruction::create_account(
+            &payer.key,
+            &mint_authority.key,
+            (Rent::get()?).minimum_balance(8) as u64,
+            8,
+            &program_id,
+        ),
+        &[
+            payer.clone(),
+            mint_authority.clone(),
+            system_program.clone(),
+        ],
+        &[&[
+            b"mint_authority_", 
+            mint_account.key.as_ref(),
+            &[mint_authority_pda_bump],
+        ]]
+    )?;
     
     msg!("Creating mint account...");
     msg!("Mint: {}", mint_account.key);
-    invoke(
+    invoke_signed(
         &system_instruction::create_account(
-            &mint_authority.key,
+            &payer.key,
             &mint_account.key,
-            (Rent::get()?).minimum_balance(MINT_SIZE as usize),
-            MINT_SIZE,
+            (Rent::get()?).minimum_balance(Mint::LEN),
+            Mint::LEN as u64,
             &token_program.key,
         ),
         &[
             mint_account.clone(),
-            mint_authority.clone(),
+            payer.clone(),
             token_program.clone(),
-        ]
+        ],
+        &[&[
+            b"mint_authority_", 
+            mint_account.key.as_ref(),
+            &[mint_authority_pda_bump],
+        ]]
     )?;
 
     msg!("Initializing mint account...");
     msg!("Mint: {}", mint_account.key);
-    invoke(
+    invoke_signed(
         &token_instruction::initialize_mint(
             &token_program.key,
             &mint_account.key,
@@ -68,18 +99,23 @@ pub fn create_mint(
             mint_authority.clone(),
             token_program.clone(),
             rent.clone(),
-        ]
+        ],
+        &[&[
+            b"mint_authority_", 
+            mint_account.key.as_ref(),
+            &[mint_authority_pda_bump],
+        ]]
     )?;
 
     msg!("Creating metadata account...");
     msg!("Metadata account address: {}", metadata_account.key);
-    invoke(
+    invoke_signed(
         &mpl_instruction::create_metadata_accounts_v2(
             *token_metadata_program.key,
             *metadata_account.key,
             *mint_account.key,
             *mint_authority.key,
-            *mint_authority.key,
+            *payer.key,
             *mint_authority.key,
             token_title,
             token_symbol,
@@ -95,9 +131,15 @@ pub fn create_mint(
             metadata_account.clone(),
             mint_account.clone(),
             mint_authority.clone(),
+            payer.clone(),
             token_metadata_program.clone(),
             rent.clone(),
         ],
+        &[&[
+            b"mint_authority_", 
+            mint_account.key.as_ref(),
+            &[mint_authority_pda_bump],
+        ]]
     )?;
 
     msg!("Token mint created successfully.");
@@ -105,3 +147,4 @@ pub fn create_mint(
     Ok(())
 }
 
+pub struct MintAuthority {}

+ 19 - 10
tokens/mint-to/native/program/src/instructions/mint_to.rs → tokens/mint-2/native/program/src/instructions/mint_to_wallet.rs

@@ -3,7 +3,8 @@ use {
         account_info::{next_account_info, AccountInfo},
         entrypoint::ProgramResult, 
         msg, 
-        program::invoke,
+        program::{invoke, invoke_signed},
+        pubkey::Pubkey,
     },
     spl_token::{
         instruction as token_instruction,
@@ -14,16 +15,19 @@ use {
 };
 
 
-pub fn mint_to(
+pub fn mint_to_wallet(
+    _program_id: &Pubkey,
     accounts: &[AccountInfo],
     amount: u64,
+    mint_authority_pda_bump: u8,
 ) -> ProgramResult {
 
     let accounts_iter = &mut accounts.iter();
 
     let mint_account = next_account_info(accounts_iter)?;
-    let token_account = next_account_info(accounts_iter)?;
     let mint_authority = next_account_info(accounts_iter)?;
+    let token_account = 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)?;
@@ -33,23 +37,23 @@ pub fn mint_to(
     msg!("Token Address: {}", token_account.key);    
     invoke(
         &token_account_instruction::create_associated_token_account(
-            &mint_authority.key,
-            &mint_authority.key,
+            &payer.key,
+            &payer.key,
             &mint_account.key,
         ),
         &[
             mint_account.clone(),
             token_account.clone(),
-            mint_authority.clone(),
+            payer.clone(),
             token_program.clone(),
             associated_token_program.clone(),
         ]
     )?;
 
-    msg!("Minting token to token account...");
+    msg!("Minting {} tokens to token account...", amount);
     msg!("Mint: {}", mint_account.key);   
     msg!("Token Address: {}", token_account.key);
-    invoke(
+    invoke_signed(
         &token_instruction::mint_to(
             &token_program.key,
             &mint_account.key,
@@ -64,10 +68,15 @@ pub fn mint_to(
             token_account.clone(),
             token_program.clone(),
             rent.clone(),
-        ]
+        ],
+        &[&[
+            b"mint_authority_", 
+            mint_account.key.as_ref(),
+            &[mint_authority_pda_bump],
+        ]]
     )?;
 
-    msg!("Token minted to wallet successfully.");
+    msg!("Tokens minted to wallet successfully.");
 
     Ok(())
 }

+ 3 - 0
tokens/mint-2/native/program/src/instructions/mod.rs

@@ -0,0 +1,3 @@
+pub mod create_token_mint;
+pub mod mint_to_wallet;
+pub mod transfer_to_wallet;

+ 81 - 0
tokens/mint-2/native/program/src/instructions/transfer_to_wallet.rs

@@ -0,0 +1,81 @@
+use {
+    solana_program::{
+        account_info::{next_account_info, AccountInfo},
+        entrypoint::ProgramResult, 
+        msg, 
+        program::invoke,
+        pubkey::Pubkey,
+    },
+    spl_token::{
+        instruction as token_instruction,
+    },
+    spl_associated_token_account::{
+        instruction as token_account_instruction,
+    },
+};
+
+
+pub fn transfer_to_wallet(
+    _program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    amount: u64,
+) -> ProgramResult {
+
+    let accounts_iter = &mut accounts.iter();
+
+    let mint_account = next_account_info(accounts_iter)?;
+    let owner_token_account = next_account_info(accounts_iter)?;
+    let recipient_token_account = next_account_info(accounts_iter)?;
+    let owner = next_account_info(accounts_iter)?;
+    let recipient = next_account_info(accounts_iter)?;
+    let _system_program = next_account_info(accounts_iter)?;
+    let token_program = next_account_info(accounts_iter)?;
+    let associated_token_program = next_account_info(accounts_iter)?;
+
+    msg!("Creating token account for recipient...");
+    msg!("Recipient Token Address: {}", recipient_token_account.key); 
+    let create_recipient_token_account_ix = &token_account_instruction::create_associated_token_account(
+        &recipient.key,
+        &recipient.key,
+        &mint_account.key,
+    );
+    let create_recipient_token_account_accts = &[
+        mint_account.clone(),
+        recipient_token_account.clone(),
+        recipient.clone(),
+        token_program.clone(),
+        associated_token_program.clone(),
+    ];
+    match invoke(create_recipient_token_account_ix, create_recipient_token_account_accts) {
+        Ok(_) => msg!("Recipient token account created successfully."),
+        Err(_) => msg!("Recipient token account exists! Using..."),
+    }
+
+    msg!("Minting {} tokens to token account...", amount);
+    msg!("Mint: {}", mint_account.key);   
+    msg!("Owner Token Address: {}", owner_token_account.key);
+    msg!("Recipient Token Address: {}", recipient_token_account.key);
+    invoke(
+        &token_instruction::transfer(
+            &token_program.key,
+            &owner_token_account.key,
+            &recipient_token_account.key,
+            &owner.key,
+            &[&owner.key, &recipient.key],
+            amount,
+        )?,
+        &[
+            mint_account.clone(),
+            owner_token_account.clone(),
+            recipient_token_account.clone(),
+            owner.clone(),
+            recipient.clone(),
+            token_program.clone(),
+        ]
+    )?;
+
+    msg!("Tokens transferred to wallet successfully.");
+
+    Ok(())
+}
+

+ 2 - 2
tokens/mint-to/native/program/src/lib.rs → tokens/mint-2/native/program/src/lib.rs

@@ -14,10 +14,10 @@ entrypoint!(process_instruction);
 
 
 fn process_instruction(
-    _program_id: &Pubkey,
+    program_id: &Pubkey,
     accounts: &[AccountInfo],
     instruction_data: &[u8],
 ) -> ProgramResult {
 
-    processor::process_instruction(accounts, instruction_data)
+    processor::process_instruction(program_id, accounts, instruction_data)
 }

+ 53 - 0
tokens/mint-2/native/program/src/processor.rs

@@ -0,0 +1,53 @@
+use {
+    borsh::BorshDeserialize,
+    solana_program::{
+        account_info::AccountInfo, 
+        entrypoint::ProgramResult, 
+        program_error::ProgramError, 
+        pubkey::Pubkey,
+    },
+};
+
+use crate::instructions::{ create_token_mint, mint_to_wallet, transfer_to_wallet };
+use crate::state::mint_state::{ TokenMetadata, MintTokensTo, TransferTokensTo };
+
+
+pub fn process_instruction(
+    program_id: &Pubkey,
+    accounts: &[AccountInfo],
+    instruction_data: &[u8],
+) -> ProgramResult {
+
+    match TokenMetadata::try_from_slice(instruction_data) {
+        Ok(token_metadata_instruction) => return create_token_mint::create_token_mint(
+            program_id,
+            accounts,
+            token_metadata_instruction.title,
+            token_metadata_instruction.symbol,
+            token_metadata_instruction.uri,
+            token_metadata_instruction.mint_authority_pda_bump,
+        ),
+        Err(_) => {},
+    };
+
+    match MintTokensTo::try_from_slice(instruction_data) {
+        Ok(mint_to_wallet_instruction) => return mint_to_wallet::mint_to_wallet(
+            program_id,
+            accounts,
+            mint_to_wallet_instruction.amount,
+            mint_to_wallet_instruction.mint_authority_pda_bump,
+        ),
+        Err(_) => {},
+    };
+
+    match TransferTokensTo::try_from_slice(instruction_data) {
+        Ok(transfer_to_wallet_instruction) => return transfer_to_wallet::transfer_to_wallet(
+            program_id,
+            accounts,
+            transfer_to_wallet_instruction.amount,
+        ),
+        Err(_) => {},
+    };
+
+    Err(ProgramError::InvalidInstructionData)
+}

+ 8 - 1
tokens/mint-to/native/program/src/state/mint.rs → tokens/mint-2/native/program/src/state/mint_state.rs

@@ -6,9 +6,16 @@ pub struct TokenMetadata {
     pub title: String,
     pub symbol: String,
     pub uri: String,
+    pub mint_authority_pda_bump: u8,
 }
 
 #[derive(BorshSerialize, BorshDeserialize, Debug)]
-pub struct MintTokenTo {
+pub struct MintTokensTo {
+    pub amount: u64,
+    pub mint_authority_pda_bump: u8,
+}
+
+#[derive(BorshSerialize, BorshDeserialize, Debug)]
+pub struct TransferTokensTo {
     pub amount: u64,
 }

+ 1 - 0
tokens/mint-2/native/program/src/state/mod.rs

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

+ 240 - 0
tokens/mint-2/native/tests/test.ts

@@ -0,0 +1,240 @@
+import {
+    Connection,
+    Keypair,
+    PublicKey,
+    SystemProgram,
+    SYSVAR_RENT_PUBKEY,
+    TransactionInstruction,
+    Transaction,
+    sendAndConfirmTransaction,
+    LAMPORTS_PER_SOL,
+} from '@solana/web3.js';
+import {
+    ASSOCIATED_TOKEN_PROGRAM_ID,
+    getAssociatedTokenAddress,
+    TOKEN_PROGRAM_ID,
+} from '@solana/spl-token';
+import * as borsh from "borsh";
+import { Buffer } from "buffer";
+
+
+const TOKEN_METADATA_PROGRAM_ID = new PublicKey(
+    "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
+);
+
+
+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 TokenMetadata extends Assignable {
+    toBuffer() {
+        return Buffer.from(borsh.serialize(TokenMetadataSchema, this));
+    }
+};
+const TokenMetadataSchema = new Map([
+    [
+        TokenMetadata, {
+            kind: 'struct',
+            fields: [
+                ['title', 'string'],
+                ['symbol', 'string'],
+                ['uri', 'string'],
+                ['mint_authority_pda_bump', 'u8'],
+            ]
+        }
+    ]
+]);
+
+class MintTokensTo extends Assignable {
+    toBuffer() {
+        return Buffer.from(borsh.serialize(MintTokensToSchema, this));
+    }
+};
+const MintTokensToSchema = new Map([
+    [
+        MintTokensTo, {
+            kind: 'struct',
+            fields: [
+                ['amount', 'u64'],
+                ['mint_authority_pda_bump', 'u8'],
+            ]
+        }
+    ]
+]);
+
+class TransferTokensTo extends Assignable {
+    toBuffer() {
+        return Buffer.from(borsh.serialize(TransferTokensToSchema, this));
+    }
+};
+const TransferTokensToSchema = new Map([
+    [
+        TransferTokensTo, {
+            kind: 'struct',
+            fields: [
+                ['amount', 'u64'],
+            ]
+        }
+    ]
+]);
+
+
+describe("mint-token", async () => {
+
+    const connection = new Connection(`http://api.devnet.solana.com/`, 'confirmed');
+    const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
+    const program = createKeypairFromFile('./program/target/so/program-keypair.json');
+
+    const mintKeypair: Keypair = Keypair.generate();
+    console.log(`New token: ${mintKeypair.publicKey}`);
+
+    it("Mint!", async () => {
+
+        const [mintAuthorityPda, mintAuthorityPdaBump] = await PublicKey.findProgramAddress(
+            [
+              Buffer.from("mint_authority_"),
+              mintKeypair.publicKey.toBuffer(),
+            ],
+            program.publicKey,
+        );
+
+        const metadataAddress = (await PublicKey.findProgramAddress(
+            [
+              Buffer.from("metadata"),
+              TOKEN_METADATA_PROGRAM_ID.toBuffer(),
+              mintKeypair.publicKey.toBuffer(),
+            ],
+            TOKEN_METADATA_PROGRAM_ID
+        ))[0];
+        
+        const metadataInstructionData = new TokenMetadata({
+            title: "Solana Gold",
+            symbol: "GOLDSOL",
+            uri: "https://raw.githubusercontent.com/solana-developers/program-examples/main/tokens/mint-2/native/tests/token_metadata.json",
+            mint_authority_pda_bump: mintAuthorityPdaBump
+        });
+
+        let ix = new TransactionInstruction({
+            keys: [
+                { pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true },            // Mint account
+                { pubkey: mintAuthorityPda, isSigner: false, isWritable: true },                // Mint authority account
+                { pubkey: metadataAddress, isSigner: false, isWritable: true },                 // Metadata account
+                { pubkey: payer.publicKey, isSigner: true, isWritable: true },                  // Payer
+                { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },             // Rent account
+                { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },        // System program
+                { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },               // Token program
+                { pubkey: TOKEN_METADATA_PROGRAM_ID, isSigner: false, isWritable: false },      // Token metadata program
+            ],
+            programId: program.publicKey,
+            data: metadataInstructionData.toBuffer(),
+        });
+
+        await sendAndConfirmTransaction(
+            connection, 
+            new Transaction().add(ix),
+            [payer, mintKeypair]
+        );
+    });
+
+
+    it("Mint to a wallet!", async () => {
+
+        const [mintAuthorityPda, mintAuthorityPdaBump] = await PublicKey.findProgramAddress(
+            [
+              Buffer.from("mint_authority_"),
+              mintKeypair.publicKey.toBuffer(),
+            ],
+            program.publicKey,
+        );
+
+        const tokenAddress = await getAssociatedTokenAddress(
+            mintKeypair.publicKey,
+            payer.publicKey
+        );
+        console.log(`Token Address: ${tokenAddress}`);
+
+        const mintToInstructionData = new MintTokensTo({
+            amount: 1,
+            mint_authority_pda_bump: mintAuthorityPdaBump,
+        });
+
+        let ix = new TransactionInstruction({
+            keys: [
+                { pubkey: mintKeypair.publicKey, isSigner: false, isWritable: true },           // Mint account
+                { pubkey: mintAuthorityPda, isSigner: false, isWritable: false },               // Mint authority account
+                { pubkey: tokenAddress, isSigner: false, isWritable: true },                    // Token account
+                { pubkey: payer.publicKey, isSigner: true, isWritable: true },                  // Payer
+                { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },             // Rent account
+                { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },        // System program
+                { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },               // Token program
+                { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },    // Associated token program
+            ],
+            programId: program.publicKey,
+            data: mintToInstructionData.toBuffer(),
+        });
+
+        await sendAndConfirmTransaction(
+            connection, 
+            new Transaction().add(ix),
+            [payer]
+        );
+    });
+
+    it("Transfer to a wallet!", async () => {
+
+        const recipientWallet = Keypair.generate();
+        await connection.confirmTransaction(
+            await connection.requestAirdrop(recipientWallet.publicKey, 2 * LAMPORTS_PER_SOL)
+        );
+        console.log(`Recipient Pubkey: ${recipientWallet.publicKey}`);
+
+        const ownerTokenAddress = await getAssociatedTokenAddress(
+            mintKeypair.publicKey,
+            payer.publicKey
+        );
+        console.log(`Owner Token Address: ${ownerTokenAddress}`);
+        const recipientTokenAddress = await getAssociatedTokenAddress(
+            mintKeypair.publicKey,
+            recipientWallet.publicKey
+        );
+        console.log(`Recipient Token Address: ${recipientTokenAddress}`);
+
+        const transferToInstructionData = new TransferTokensTo({
+            amount: 1,
+        });
+
+        let ix = new TransactionInstruction({
+            keys: [
+                { pubkey: mintKeypair.publicKey, isSigner: false, isWritable: true },           // Mint account
+                { pubkey: ownerTokenAddress, isSigner: false, isWritable: true },               // Owner Token account
+                { pubkey: recipientTokenAddress, isSigner: false, isWritable: true },           // Recipient Token account
+                { pubkey: payer.publicKey, isSigner: true, isWritable: true },                  // Owner
+                { pubkey: recipientWallet.publicKey, isSigner: true, isWritable: true },        // Recipient
+                { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },        // System program
+                { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },               // Token program
+                { pubkey: ASSOCIATED_TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },    // Associated token program
+            ],
+            programId: program.publicKey,
+            data: transferToInstructionData.toBuffer(),
+        });
+
+        await sendAndConfirmTransaction(
+            connection, 
+            new Transaction().add(ix),
+            [payer, recipientWallet]
+        );
+    });
+  });
+  

+ 6 - 0
tokens/mint-2/native/tests/token_metadata.json

@@ -0,0 +1,6 @@
+{
+    "name": "Solana Gold",
+    "symbol": "GOLDSOL",
+    "description": "A gold Solana SPL token :)",
+    "image": "https://images.all-free-download.com/images/graphiclarge/solana_coin_sign_icon_shiny_golden_symmetric_geometrical_design_6919941.jpg"
+}

+ 1 - 1
nfts/mint/native/tsconfig.json → tokens/mint-2/native/tsconfig.json

@@ -5,6 +5,6 @@
     "lib": ["es2015"],
     "module": "commonjs",
     "target": "es6",
-    "esModuleInterop": true
+    "esModuleInterop": true,
   }
 }

+ 0 - 14
tokens/mint-to/anchor/Anchor.toml

@@ -1,14 +0,0 @@
-[features]
-seeds = false
-[programs.devnet]
-mint_token_to = "86NFhnnuV8SNEuHdqNtjCFeGCknpjDXEbV7b3zBefJ11"
-
-[registry]
-url = "https://anchor.projectserum.com"
-
-[provider]
-cluster = "devnet"
-wallet = "~/.config/solana/id.json"
-
-[scripts]
-test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

+ 0 - 13
tokens/mint-to/anchor/Cargo.toml

@@ -1,13 +0,0 @@
-[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

+ 0 - 14
tokens/mint-to/anchor/package.json

@@ -1,14 +0,0 @@
-{
-    "dependencies": {
-        "@project-serum/anchor": "^0.24.2"
-    },
-    "devDependencies": {
-        "@types/bn.js": "^5.1.0",
-        "@types/chai": "^4.3.0",
-        "@types/mocha": "^9.0.0",
-        "chai": "^4.3.4",
-        "mocha": "^9.0.3",
-        "ts-mocha": "^10.0.0",
-        "typescript": "^4.3.5"
-    }
-}

+ 0 - 21
tokens/mint-to/anchor/programs/mint-token-to/Cargo.toml

@@ -1,21 +0,0 @@
-[package]
-name = "mint-token-to"
-version = "0.1.0"
-description = "Created with Anchor"
-edition = "2021"
-
-[lib]
-crate-type = ["cdylib", "lib"]
-name = "mint_token_to"
-
-[features]
-no-entrypoint = []
-no-idl = []
-no-log-ix-name = []
-cpi = ["no-entrypoint"]
-default = []
-
-[dependencies]
-anchor-lang = "0.24.2"
-anchor-spl = "0.24.2"
-mpl-token-metadata = { version="1.2.5", features = [ "no-entrypoint" ] }

+ 0 - 2
tokens/mint-to/anchor/programs/mint-token-to/Xargo.toml

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

+ 0 - 5
tokens/mint-to/anchor/programs/mint-token-to/src/instructions/mod.rs

@@ -1,5 +0,0 @@
-pub mod create_token_mint;
-pub mod mint_to_wallet;
-
-pub use create_token_mint::*;
-pub use mint_to_wallet::*;

+ 0 - 10
tokens/mint-to/anchor/tsconfig.json

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

+ 0 - 8
tokens/mint-to/native/cicd.sh

@@ -1,8 +0,0 @@
-#!/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 --bpf-out-dir=./program/target/so
-solana program deploy ./program/target/so/program.so

+ 0 - 21
tokens/mint-to/native/package.json

@@ -1,21 +0,0 @@
-{
-  "scripts": {
-    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
-  },
-  "dependencies": {
-    "@solana/spl-token": "^0.2.0",
-    "@solana/web3.js": "^1.47.3",
-    "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"
-  }
-}

+ 0 - 15
tokens/mint-to/native/program/Cargo.toml

@@ -1,15 +0,0 @@
-[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" ] }
-mpl-token-metadata = { version="1.2.5", features = [ "no-entrypoint" ] }
-
-[lib]
-crate-type = ["cdylib", "lib"]

+ 0 - 2
tokens/mint-to/native/program/src/instructions/mod.rs

@@ -1,2 +0,0 @@
-pub mod create_mint;
-pub mod mint_to;

+ 0 - 38
tokens/mint-to/native/program/src/processor.rs

@@ -1,38 +0,0 @@
-use {
-    borsh::BorshDeserialize,
-    solana_program::{
-        account_info::AccountInfo, 
-        entrypoint::ProgramResult, 
-        program_error::ProgramError, 
-    },
-};
-
-use crate::instructions::{ create_mint, mint_to };
-use crate::state::mint::{ TokenMetadata, MintTokenTo };
-
-
-pub fn process_instruction(
-    accounts: &[AccountInfo],
-    instruction_data: &[u8],
-) -> ProgramResult {
-
-    match TokenMetadata::try_from_slice(instruction_data) {
-        Ok(token_metadata_instruction) => return create_mint::create_mint(
-                accounts,
-                token_metadata_instruction.title,
-                token_metadata_instruction.symbol,
-                token_metadata_instruction.uri,
-            ),
-        Err(_) => {},
-    };
-
-    match MintTokenTo::try_from_slice(instruction_data) {
-        Ok(mint_to) => return mint_to::mint_to(
-                accounts,
-                mint_to.amount
-            ),
-        Err(_) => {},
-    };
-
-    Err(ProgramError::InvalidInstructionData)
-}

+ 0 - 1
tokens/mint-to/native/program/src/state/mod.rs

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

+ 0 - 228
tokens/mint-to/native/tests/test.ts

@@ -1,228 +0,0 @@
-import {
-    Connection,
-    Keypair,
-    PublicKey,
-    SystemProgram,
-    SYSVAR_RENT_PUBKEY,
-    TransactionInstruction,
-    Transaction,
-    sendAndConfirmTransaction,
-} from '@solana/web3.js';
-import {
-    ASSOCIATED_TOKEN_PROGRAM_ID,
-    getAssociatedTokenAddress,
-    MINT_SIZE,
-    TOKEN_PROGRAM_ID,
-} from '@solana/spl-token';
-import * as borsh from "borsh";
-import { Buffer } from "buffer";
-
-
-const TOKEN_METADATA_PROGRAM_ID = new PublicKey(
-    "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
-);
-
-
-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 TokenMetadata extends Assignable {
-    toBuffer() {
-        return Buffer.from(borsh.serialize(TokenMetadataSchema, this));
-    }
-};
-const TokenMetadataSchema = new Map([
-    [
-        TokenMetadata, {
-            kind: 'struct',
-            fields: [
-                ['title', 'string'],
-                ['symbol', 'string'],
-                ['uri', 'string'],
-            ]
-        }
-    ]
-]);
-
-class MintTokenTo extends Assignable {
-    toBuffer() {
-        return Buffer.from(borsh.serialize(MintTokenToSchema, this));
-    }
-};
-const MintTokenToSchema = new Map([
-    [
-        MintTokenTo, {
-            kind: 'struct',
-            fields: [
-                ['amount', 'u64'],
-            ]
-        }
-    ]
-]);
-
-
-describe("mint-token", () => {
-
-    const connection = new Connection(`http://api.devnet.solana.com/`, 'confirmed');
-    const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
-    const program = createKeypairFromFile('./program/target/so/program-keypair.json');
-
-    const mintKeypair: Keypair = Keypair.generate();
-    console.log(`New token: ${mintKeypair.publicKey}`);
-
-    it("Mint!", async () => {
-
-        const metadataAddress = (await PublicKey.findProgramAddress(
-            [
-              Buffer.from("metadata"),
-              TOKEN_METADATA_PROGRAM_ID.toBuffer(),
-              mintKeypair.publicKey.toBuffer(),
-            ],
-            TOKEN_METADATA_PROGRAM_ID
-        ))[0];
-        const metadataInstructionData = new TokenMetadata({
-            title: "Solana Gold",
-            symbol: "GOLDSOL",
-            uri: "https://raw.githubusercontent.com/solana-developers/program-examples/main/tokens/token_metadata.json",
-        });
-
-        // Transact with the "create_mint" function in our on-chain program
-        //
-        let ix = new TransactionInstruction({
-            keys: [
-                // Mint account
-                {
-                    pubkey: mintKeypair.publicKey,
-                    isSigner: true,
-                    isWritable: true,
-                },
-                // Metadata account
-                {
-                    pubkey: metadataAddress,
-                    isSigner: false,
-                    isWritable: true,
-                },
-                // Mint Authority
-                {
-                    pubkey: payer.publicKey,
-                    isSigner: true,
-                    isWritable: false,
-                },
-                // Rent account
-                {
-                    pubkey: SYSVAR_RENT_PUBKEY,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // System program
-                {
-                    pubkey: SystemProgram.programId,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Token program
-                {
-                    pubkey: TOKEN_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Token metadata program
-                {
-                    pubkey: TOKEN_METADATA_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-            ],
-            programId: program.publicKey,
-            data: metadataInstructionData.toBuffer(),
-        });
-
-        await sendAndConfirmTransaction(
-            connection, 
-            new Transaction().add(ix),
-            [payer, mintKeypair]
-        );
-    });
-
-
-    it("Mint to a wallet!", async () => {
-
-        const tokenAddress = await getAssociatedTokenAddress(
-            mintKeypair.publicKey,
-            payer.publicKey
-        );
-        const mintToInstructionData = new MintTokenTo({
-            amount: 1,
-        });
-
-        // Transact with the "mint_to" function in our on-chain program
-        //
-        let ix = new TransactionInstruction({
-            keys: [
-                // Mint account
-                {
-                    pubkey: mintKeypair.publicKey,
-                    isSigner: true,
-                    isWritable: true,
-                },
-                // Token account
-                {
-                    pubkey: tokenAddress,
-                    isSigner: false,
-                    isWritable: true,
-                },
-                // Mint Authority
-                {
-                    pubkey: payer.publicKey,
-                    isSigner: true,
-                    isWritable: false,
-                },
-                // Rent account
-                {
-                    pubkey: SYSVAR_RENT_PUBKEY,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // System program
-                {
-                    pubkey: SystemProgram.programId,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Token program
-                {
-                    pubkey: TOKEN_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Associated token program
-                {
-                    pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-            ],
-            programId: program.publicKey,
-            data: mintToInstructionData.toBuffer(),
-        });
-
-        await sendAndConfirmTransaction(
-            connection, 
-            new Transaction().add(ix),
-            [payer, mintKeypair]
-        );
-    });
-  });
-  

+ 0 - 10
tokens/mint-to/native/tsconfig.json

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

+ 0 - 12
tokens/mint/README.md

@@ -1,12 +0,0 @@
-# Create a New SPL Token Mint
-
-This example demonstrates how to create an SPl Token on Solana with some metadata such as a token symbol and icon.
-
-### :key: Keys:
-
-- SPL Tokens by default have **9 decimals**, and **NFTs have 0 decimals**. "Decimals" here means the number of decimal; ie. a token with 3 decimals will be tracked in increments of 0.001.   
-- You can use [Metaplex's Token Metadata Program](https://docs.metaplex.com/) to create metadata for your token.
-- Steps:
-    1. Create an account for the Mint.
-    2. Initialize that account as a Mint Account.
-    3. Create a metadata account associated with that Mint Account.

+ 0 - 14
tokens/mint/anchor/Anchor.toml

@@ -1,14 +0,0 @@
-[features]
-seeds = false
-[programs.devnet]
-mint_token = "3hmFGLkjJc7TfSLdEYYYwGAz6KsrD8anYwtSkF6TYjBU"
-
-[registry]
-url = "https://anchor.projectserum.com"
-
-[provider]
-cluster = "devnet"
-wallet = "~/.config/solana/id.json"
-
-[scripts]
-test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"

+ 0 - 13
tokens/mint/anchor/Cargo.toml

@@ -1,13 +0,0 @@
-[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

+ 0 - 14
tokens/mint/anchor/package.json

@@ -1,14 +0,0 @@
-{
-    "dependencies": {
-        "@project-serum/anchor": "^0.24.2"
-    },
-    "devDependencies": {
-        "@types/bn.js": "^5.1.0",
-        "@types/chai": "^4.3.0",
-        "@types/mocha": "^9.0.0",
-        "chai": "^4.3.4",
-        "mocha": "^9.0.3",
-        "ts-mocha": "^10.0.0",
-        "typescript": "^4.3.5"
-    }
-}

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

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

+ 0 - 108
tokens/mint/anchor/programs/mint-token/src/lib.rs

@@ -1,108 +0,0 @@
-use {
-    anchor_lang::{
-        prelude::*,
-        solana_program::program::invoke,
-        system_program,
-    },
-    anchor_spl::token,
-    mpl_token_metadata::instruction as mpl_instruction,
-};
-
-
-declare_id!("3hmFGLkjJc7TfSLdEYYYwGAz6KsrD8anYwtSkF6TYjBU");
-
-
-#[program]
-pub mod mint_token {
-    use super::*;
-
-    pub fn mint_token(
-        ctx: Context<MintToken>, 
-        metadata_title: String, 
-        metadata_symbol: String, 
-        metadata_uri: String,
-    ) -> Result<()> {
-
-        const MINT_SIZE: u64 = 82;
-
-        msg!("Creating mint account...");
-        msg!("Mint: {}", &ctx.accounts.mint_account.key());
-        system_program::create_account(
-            CpiContext::new(
-                ctx.accounts.token_program.to_account_info(),
-                system_program::CreateAccount {
-                    from: ctx.accounts.mint_authority.to_account_info(),
-                    to: ctx.accounts.mint_account.to_account_info(),
-                },
-            ),
-            (Rent::get()?).minimum_balance(MINT_SIZE as usize),
-            MINT_SIZE,
-            &ctx.accounts.token_program.key(),
-        )?;
-
-        msg!("Initializing mint account...");
-        msg!("Mint: {}", &ctx.accounts.mint_account.key());
-        token::initialize_mint(
-            CpiContext::new(
-                ctx.accounts.token_program.to_account_info(),
-                token::InitializeMint {
-                    mint: ctx.accounts.mint_account.to_account_info(),
-                    rent: ctx.accounts.rent.to_account_info(),
-                },
-            ),
-            9,                                              // 9 Decimals
-            &ctx.accounts.mint_authority.key(),
-            Some(&ctx.accounts.mint_authority.key()),
-        )?;
-
-        msg!("Creating metadata account...");
-        msg!("Metadata account address: {}", &ctx.accounts.metadata_account.key());
-        invoke(
-            &mpl_instruction::create_metadata_accounts_v2(
-                ctx.accounts.token_metadata_program.key(),      // Program ID (the Token Metadata Program)
-                ctx.accounts.metadata_account.key(),            // Metadata account
-                ctx.accounts.mint_account.key(),                // Mint account
-                ctx.accounts.mint_authority.key(),              // Mint authority
-                ctx.accounts.mint_authority.key(),              // Payer
-                ctx.accounts.mint_authority.key(),              // Update authority
-                metadata_title,                                 // Name
-                metadata_symbol,                                // Symbol
-                metadata_uri,                                   // URI
-                None,                                           // Creators
-                0,                                              // Seller fee basis points
-                true,                                           // Update authority is signer
-                false,                                          // Is mutable
-                None,                                           // Collection
-                None,                                           // Uses
-            ),
-            &[
-                ctx.accounts.metadata_account.to_account_info(),
-                ctx.accounts.mint_account.to_account_info(),
-                ctx.accounts.mint_authority.to_account_info(),
-                ctx.accounts.token_metadata_program.to_account_info(),
-                ctx.accounts.rent.to_account_info(),
-            ],
-        )?;
-
-        msg!("Token mint process completed successfully.");
-
-        Ok(())
-    }
-}
-
-
-#[derive(Accounts)]
-pub struct MintToken<'info> {
-    /// CHECK: We're about to create this with Metaplex
-    #[account(mut)]
-    pub metadata_account: UncheckedAccount<'info>,
-    #[account(mut)]
-    pub mint_account: Signer<'info>,
-    #[account(mut)]
-    pub mint_authority: Signer<'info>,
-    pub rent: Sysvar<'info, Rent>,
-    pub system_program: Program<'info, System>,
-    pub token_program: Program<'info, token::Token>,
-    /// CHECK: Metaplex will check this
-    pub token_metadata_program: UncheckedAccount<'info>,
-}

+ 0 - 52
tokens/mint/anchor/tests/test.ts

@@ -1,52 +0,0 @@
-import * as anchor from "@project-serum/anchor";
-import { MintToken } from "../target/types/mint_token";
-
-
-const TOKEN_METADATA_PROGRAM_ID = new anchor.web3.PublicKey(
-  "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
-);
-
-
-describe("mint-token", () => {
-  
-  const provider = anchor.AnchorProvider.env();
-  anchor.setProvider(provider);
-  const payer = provider.wallet as anchor.Wallet;
-  const program = anchor.workspace.MintToken as anchor.Program<MintToken>;
-
-  it("Mint!", async () => {
-
-    const mintKeypair: anchor.web3.Keypair = anchor.web3.Keypair.generate();
-    console.log(`New token: ${mintKeypair.publicKey}`);
-
-    // Derive the metadata account's address and set the metadata
-    //
-    const metadataAddress = (await anchor.web3.PublicKey.findProgramAddress(
-      [
-        Buffer.from("metadata"),
-        TOKEN_METADATA_PROGRAM_ID.toBuffer(),
-        mintKeypair.publicKey.toBuffer(),
-      ],
-      TOKEN_METADATA_PROGRAM_ID
-    ))[0];
-    const testTokenTitle = "Solana Gold";
-    const testTokenSymbol = "GOLDSOL";
-    const testTokenUri = "https://raw.githubusercontent.com/solana-developers/program-examples/main/tokens/token_metadata.json";
-
-    // Transact with the "mint_token" function in our on-chain program
-    //
-    await program.methods.mintToken(
-      testTokenTitle, testTokenSymbol, testTokenUri
-    )
-    .accounts({
-      metadataAccount: metadataAddress,
-      mintAccount: mintKeypair.publicKey,
-      mintAuthority: payer.publicKey,
-      systemProgram: anchor.web3.SystemProgram.programId,
-      tokenProgram: anchor.utils.token.TOKEN_PROGRAM_ID,
-      tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
-    })
-    .signers([payer.payer, mintKeypair])
-    .rpc();
-  });
-});

+ 0 - 10
tokens/mint/anchor/tsconfig.json

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

+ 0 - 8
tokens/mint/native/cicd.sh

@@ -1,8 +0,0 @@
-#!/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 --bpf-out-dir=./program/target/so
-solana program deploy ./program/target/so/program.so

+ 0 - 21
tokens/mint/native/package.json

@@ -1,21 +0,0 @@
-{
-  "scripts": {
-    "test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
-  },
-  "dependencies": {
-    "@solana/spl-token": "^0.2.0",
-    "@solana/web3.js": "^1.47.3",
-    "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"
-  }
-}

+ 0 - 14
tokens/mint/native/program/Cargo.toml

@@ -1,14 +0,0 @@
-[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" ] }
-mpl-token-metadata = { version="1.2.5", features = [ "no-entrypoint" ] }
-
-[lib]
-crate-type = ["cdylib", "lib"]

+ 0 - 122
tokens/mint/native/program/src/lib.rs

@@ -1,122 +0,0 @@
-use {
-    borsh::{
-        BorshSerialize, BorshDeserialize,
-    },
-    solana_program::{
-        account_info::{next_account_info, AccountInfo}, 
-        entrypoint, 
-        entrypoint::ProgramResult, 
-        msg, 
-        program::invoke,
-        pubkey::Pubkey,
-        rent::Rent,
-        system_instruction,
-        sysvar::Sysvar,
-    },
-    spl_token::{
-        instruction as token_instruction,
-    },
-    mpl_token_metadata::{
-        instruction as mpl_instruction,
-    },
-};
-
-
-entrypoint!(process_instruction);
-
-
-fn process_instruction(
-    _program_id: &Pubkey,
-    accounts: &[AccountInfo],
-    instruction_data: &[u8],
-) -> ProgramResult {
-
-    const MINT_SIZE: u64 = 82;
-
-    let accounts_iter = &mut accounts.iter();
-
-    let mint_account = next_account_info(accounts_iter)?;
-    let metadata_account = next_account_info(accounts_iter)?;
-    let mint_authority = 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)?;
-    let token_metadata_program = next_account_info(accounts_iter)?;
-
-    let token_metadata = TokenMetadata::try_from_slice(instruction_data)?;
-    
-    msg!("Creating mint account...");
-    msg!("Mint: {}", mint_account.key);
-    invoke(
-        &system_instruction::create_account(
-            &mint_authority.key,
-            &mint_account.key,
-            (Rent::get()?).minimum_balance(MINT_SIZE as usize),
-            MINT_SIZE,
-            &token_program.key,
-        ),
-        &[
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_program.clone(),
-        ]
-    )?;
-
-    msg!("Initializing mint account...");
-    msg!("Mint: {}", mint_account.key);
-    invoke(
-        &token_instruction::initialize_mint(
-            &token_program.key,
-            &mint_account.key,
-            &mint_authority.key,
-            Some(&mint_authority.key),
-            9,                              // 9 Decimals
-        )?,
-        &[
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_program.clone(),
-            rent.clone(),
-        ]
-    )?;
-
-    msg!("Creating metadata account...");
-    msg!("Metadata account address: {}", metadata_account.key);
-    invoke(
-        &mpl_instruction::create_metadata_accounts_v2(
-            *token_metadata_program.key,    // Program ID (the Token Metadata Program)
-            *metadata_account.key,          // Metadata Account
-            *mint_account.key,              // Mint Account
-            *mint_authority.key,            // Mint Authority
-            *mint_authority.key,            // Payer
-            *mint_authority.key,            // Update Authority
-            token_metadata.title,           // Name
-            token_metadata.symbol,          // Symbol
-            token_metadata.uri,             // URI
-            None,                           // Creators
-            0,                              // Seller fee basis points
-            true,                           // Update authority is signer
-            false,                          // Is mutable
-            None,                           // Collection
-            None,                           // Uses
-        ),
-        &[
-            metadata_account.clone(),
-            mint_account.clone(),
-            mint_authority.clone(),
-            token_metadata_program.clone(),
-            rent.clone(),
-        ],
-    )?;
-
-    msg!("Token mint process completed successfully.");
-
-    Ok(())
-}
-
-#[derive(BorshSerialize, BorshDeserialize, Debug)]
-pub struct TokenMetadata {
-    title: String,
-    symbol: String,
-    uri: String,
-}

+ 0 - 140
tokens/mint/native/tests/test.ts

@@ -1,140 +0,0 @@
-import {
-    Connection,
-    Keypair,
-    PublicKey,
-    SystemProgram,
-    SYSVAR_RENT_PUBKEY,
-    TransactionInstruction,
-    Transaction,
-    sendAndConfirmTransaction,
-} from '@solana/web3.js';
-import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
-import * as borsh from "borsh";
-import { Buffer } from "buffer";
-
-
-const TOKEN_METADATA_PROGRAM_ID = new PublicKey(
-    "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
-);
-
-
-function createKeypairFromFile(path: string): Keypair {
-    return Keypair.fromSecretKey(
-        Buffer.from(JSON.parse(require('fs').readFileSync(path, "utf-8")))
-    )
-};
-
-
-describe("mint-token", () => {
-
-    const connection = new Connection(`http://api.devnet.solana.com/`, 'confirmed');
-    const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
-    const program = createKeypairFromFile('./program/target/so/program-keypair.json');
-
-    class Assignable {
-        constructor(properties) {
-            Object.keys(properties).map((key) => {
-                return (this[key] = properties[key]);
-            });
-        };
-    };
-
-    class TokenMetadata extends Assignable {
-        toBuffer() {
-            return Buffer.from(borsh.serialize(TokenMetadataSchema, this));
-        }
-    };
-
-    const TokenMetadataSchema = new Map([
-        [
-            TokenMetadata, {
-                kind: 'struct',
-                fields: [
-                    ['title', 'string'],
-                    ['symbol', 'string'],
-                    ['uri', 'string'],
-                ]
-            }
-        ]
-    ]);
-  
-    it("Mint!", async () => {
-
-        const mintKeypair: Keypair = Keypair.generate();
-        console.log(`New token: ${mintKeypair.publicKey}`);
-
-        // Derive the metadata account's address and set the metadata
-        //
-        const metadataAddress = (await PublicKey.findProgramAddress(
-            [
-              Buffer.from("metadata"),
-              TOKEN_METADATA_PROGRAM_ID.toBuffer(),
-              mintKeypair.publicKey.toBuffer(),
-            ],
-            TOKEN_METADATA_PROGRAM_ID
-        ))[0];
-        const metadata = new TokenMetadata({
-            title: "Solana Gold",
-            symbol: "GOLDSOL",
-            uri: "https://raw.githubusercontent.com/solana-developers/program-examples/main/tokens/token_metadata.json",
-        });
-
-        // Transact with the "mint_token" function in our on-chain program
-        //
-        let ix = new TransactionInstruction({
-            keys: [
-                // Mint account
-                {
-                    pubkey: mintKeypair.publicKey,
-                    isSigner: true,
-                    isWritable: true,
-                },
-                // Metadata account
-                {
-                    pubkey: metadataAddress,
-                    isSigner: false,
-                    isWritable: true,
-                },
-                // Mint Authority
-                {
-                    pubkey: payer.publicKey,
-                    isSigner: true,
-                    isWritable: false,
-                },
-                // Rent account
-                {
-                    pubkey: SYSVAR_RENT_PUBKEY,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // System program
-                {
-                    pubkey: SystemProgram.programId,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Token program
-                {
-                    pubkey: TOKEN_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-                // Token metadata program
-                {
-                    pubkey: TOKEN_METADATA_PROGRAM_ID,
-                    isSigner: false,
-                    isWritable: false,
-                },
-            ],
-            programId: program.publicKey,
-            data: metadata.toBuffer(),
-        });
-
-        await sendAndConfirmTransaction(
-            connection, 
-            new Transaction().add(ix),
-            [payer, mintKeypair]
-        );
-    });
-  });
-  

+ 0 - 10
tokens/mint/native/tsconfig.json

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