Token
Ano ang kailangan ko para makapagsimula sa SPL-Tokens?
Sa tuwing nakikipag-ugnayan ka sa mga token sa Solana, ikaw talaga nakikipag-ugnayan sa Solana Program Library Token, o SPL-Token pamantayan. Ang pamantayan ng SPL-Token ay nangangailangan ng isang partikular na library upang gamitin, na makikita mo sa ibaba batay sa iyong wika.
"@solana/spl-token": "^0.2.0"
Paano gumawa ng bagong Token
Ang paggawa ng mga token ay ginagawa sa pamamagitan ng paggawa ng tinatawag na "mint account". Ang mint account na ito ay ginamit sa ibang pagkakataon upang mag-mint ng mga token sa token account ng isang user.
import {
  clusterApiUrl,
  Connection,
  Keypair,
  Transaction,
  SystemProgram,
} from "@solana/web3.js";
import {
  createInitializeMintInstruction,
  TOKEN_PROGRAM_ID,
  MINT_SIZE,
  getMinimumBalanceForRentExemptMint,
  createMint,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  // 1) use build-in function
  let mintPubkey = await createMint(
    connection, // conneciton
    feePayer, // fee payer
    alice.publicKey, // mint authority
    alice.publicKey, // freeze authority (you can use `null` to disable it. when you disable it, you can't turn it on again)
    8 // decimals
  );
  console.log(`mint: ${mintPubkey.toBase58()}`);
  // or
  // 2) compose by yourself
  const mint = Keypair.generate();
  console.log(`mint: ${mint.publicKey.toBase58()}`);
  let tx = new Transaction().add(
    // create mint account
    SystemProgram.createAccount({
      fromPubkey: feePayer.publicKey,
      newAccountPubkey: mint.publicKey,
      space: MINT_SIZE,
      lamports: await getMinimumBalanceForRentExemptMint(connection),
      programId: TOKEN_PROGRAM_ID,
    }),
    // init mint account
    createInitializeMintInstruction(
      mint.publicKey, // mint pubkey
      8, // decimals
      alice.publicKey, // mint authority
      alice.publicKey // freeze authority (you can use `null` to disable it. when you disable it, you can't turn it on again)
    )
  );
  console.log(
    `txhash: ${await connection.sendTransaction(tx, [feePayer, mint])}`
  );
})();
// 1) use build-in function
let mintPubkey = await createMint(
  connection, // conneciton
  feePayer, // fee payer
  alice.publicKey, // mint authority
  alice.publicKey, // freeze authority (you can use `null` to disable it. when you disable it, you can't turn it on again)
  8 // decimals
);
// or
// 2) compose by yourself
let tx = new Transaction().add(
  // create mint account
  SystemProgram.createAccount({
    fromPubkey: feePayer.publicKey,
    newAccountPubkey: mint.publicKey,
    space: MINT_SIZE,
    lamports: await getMinimumBalanceForRentExemptMint(connection),
    programId: TOKEN_PROGRAM_ID,
  }),
  // init mint account
  createInitializeMintInstruction(
    mint.publicKey, // mint pubkey
    8, // decimals
    alice.publicKey, // mint authority
    alice.publicKey // freeze authority (you can use `null` to disable it. when you disable it, you can't turn it on again)
  )
);
Paano makakuha ng token mint
Upang makuha ang kasalukuyang supply, awtoridad, o mga decimal na mayroon ang isang token, kakailanganin mong makuha ang impormasyon ng account para sa token mint.
import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
import { getMint } from "@solana/spl-token";
(async () => {
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  const mintAccountPublicKey = new PublicKey("8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV");
  let mintAccount = await getMint(connection, mintAccountPublicKey);
  console.log(mintAccount);
  /*
  {
    address: PublicKey {
      _bn: <BN: 7351e5e067cc7cfefef42e78915d3c513edbb8adeeab4d9092e814fe68c39fec>
    },
    mintAuthority: PublicKey {
      _bn: <BN: df30e6ca0981c1a677eed6f7cb46b2aa442ca9b7a10a10e494badea4b9b6944f>
    },
    supply: 0n,
    decimals: 8,
    isInitialized: true,
    freezeAuthority: PublicKey {
      _bn: <BN: df30e6ca0981c1a677eed6f7cb46b2aa442ca9b7a10a10e494badea4b9b6944f>
    }
  }
  */
})();
let mintAccount = await getMint(connection, mintAccountPublicKey);
Paano gumawa ng token account
Ang isang token account ay kinakailangan para sa isang user na humawak ng mga token.
Ang isang user ay magkakaroon ng kahit isang token account para sa bawat uri ng token na pagmamay-ari nila.
Ang Mga Kaugnay na Token Account ay tiyak na nilikha account para sa bawat keypair. Ang mga ATA ay ang inirerekomendang paraan ng pamamahala ng mga token account.
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
  SystemProgram,
} from "@solana/web3.js";
import {
  createAssociatedTokenAccount,
  getAssociatedTokenAddress,
  createAssociatedTokenAccountInstruction,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const mintPubkey = new PublicKey(
    "2SKpuBU9ksneBZD4nqbZkw75NE11HsSHsGRtW2BZh5aQ"
  );
  // 1) use build-in function
  {
    let ata = await createAssociatedTokenAccount(
      connection, // connection
      feePayer, // fee payer
      mintPubkey, // mint
      alice.publicKey // owner,
    );
    console.log(`ATA: ${ata.toBase58()}`);
  }
  // or
  // 2) composed by yourself
  {
    // calculate ATA
    let ata = await getAssociatedTokenAddress(
      mintPubkey, // mint
      alice.publicKey // owner
    );
    console.log(`ATA: ${ata.toBase58()}`);
    // if your wallet is off-curve, you should use
    // let ata = await getAssociatedTokenAddress(
    //   mintPubkey, // mint
    //   alice.publicKey // owner
    //   true, // allowOwnerOffCurve
    // );
    let tx = new Transaction().add(
      createAssociatedTokenAccountInstruction(
        feePayer.publicKey, // payer
        ata, // ata
        alice.publicKey, // owner
        mintPubkey // mint
      )
    );
    console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
  }
})();
// 1) use build-in function
{
  let ata = await createAssociatedTokenAccount(
    connection, // connection
    feePayer, // fee payer
    mintPubkey, // mint
    alice.publicKey // owner,
  );
}
// or
// 2) composed by yourself
{
  let tx = new Transaction().add(
    createAssociatedTokenAccountInstruction(
      feePayer.publicKey, // payer
      ata, // ata
      alice.publicKey, // owner
      mintPubkey // mint
    )
  );
}
Paano makakuha ng Token Account
Ang bawat token account ay may impormasyon sa token tulad ng may-ari, mint, halaga(balanse), at mga decimal.
import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
import { getAccount } from "@solana/spl-token";
(async () => {
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  const tokenAccountPubkey = new PublicKey(
    "2XYiFjmU1pCXmC2QfEAghk6S7UADseupkNQdnRBXszD5"
  );
  let tokenAccount = await getAccount(connection, tokenAccountPubkey);
  console.log(tokenAccount);
  /*
  {
    address: PublicKey {
      _bn: <BN: 16aef79dfadb39ffedb3b6f77688b8c162b18bb9cba2ffefe152303629ae3030>
    },
    mint: PublicKey {
      _bn: <BN: 7351e5e067cc7cfefef42e78915d3c513edbb8adeeab4d9092e814fe68c39fec>
    },
    owner: PublicKey {
      _bn: <BN: df30e6ca0981c1a677eed6f7cb46b2aa442ca9b7a10a10e494badea4b9b6944f>
    },
    amount: 0n,
    delegate: null,
    delegatedAmount: 0n,
    isInitialized: true,
    isFrozen: false,
    isNative: false,
    rentExemptReserve: null,
    closeAuthority: null
  }
  */
})();
let tokenAccount = await getAccount(connection, tokenAccountPubkey);
Paano makakuha ng balanse ng token account
Ang token account ay may balanse ng token, na maaaring makuha gamit ang a iisang tawag.
import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
(async () => {
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  const tokenAccount = new PublicKey(
    "FWZedVtyKQtP4CXhT7XDnLidRADrJknmZGA2qNjpTPg8"
  );
  let tokenAmount = await connection.getTokenAccountBalance(tokenAccount);
  console.log(`amount: ${tokenAmount.value.amount}`);
  console.log(`decimals: ${tokenAmount.value.decimals}`);
})();
let tokenAmount = await connection.getTokenAccountBalance(tokenAccount);
use solana_client::rpc_client::RpcClient;
use solana_program::pubkey::Pubkey;
use solana_sdk::commitment_config::CommitmentConfig;
use std::str::FromStr;
fn main() {
    let rpc_url = String::from("https://api.devnet.solana.com");
    let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
    let token_account = Pubkey::from_str("FWZedVtyKQtP4CXhT7XDnLidRADrJknmZGA2qNjpTPg8").unwrap();
    let balance = connection
        .get_token_account_balance(&token_account)
        .unwrap();
    println!("amount: {}, decimals: {}", balance.amount, balance.decimals);
}
let balance = connection
        .get_token_account_balance(&token_account)
        .unwrap();
TIP
Ang isang token account ay maaari lamang magkaroon ng isang uri ng mint. Kapag tinukoy mo ang isang token account, tukoy ka rin ng mint.
Paano mag-mint ng mga token
Kapag nag-mint ka ng mga token, dinadagdagan mo ang supply at inilipat mo ang mga bagong token sa isang partikular na token account.
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
} from "@solana/web3.js";
import {
  createMintToCheckedInstruction,
  mintToChecked,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const mintPubkey = new PublicKey(
    "8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV"
  );
  const tokenAccountPubkey = new PublicKey(
    "2XYiFjmU1pCXmC2QfEAghk6S7UADseupkNQdnRBXszD5"
  );
  // 1) use build-in function
  {
    let txhash = await mintToChecked(
      connection, // connection
      feePayer, // fee payer
      mintPubkey, // mint
      tokenAccountPubkey, // receiver (should be a token account)
      alice, // mint authority
      1e8, // amount. if your decimals is 8, you mint 10^8 for 1 token.
      8 // decimals
    );
    console.log(`txhash: ${txhash}`);
    // if alice is a multisig account
    // let txhash = await mintToChecked(
    //   connection, // connection
    //   feePayer, // fee payer
    //   mintPubkey, // mint
    //   tokenAccountPubkey, // receiver (should be a token account)
    //   alice.publicKey, // !! mint authority pubkey !!
    //   1e8, // amount. if your decimals is 8, you mint 10^8 for 1 token.
    //   8, // decimals
    //   [signer1, signer2 ...],
    // );
  }
  // or
  // 2) compose by yourself
  {
    let tx = new Transaction().add(
      createMintToCheckedInstruction(
        mintPubkey, // mint
        tokenAccountPubkey, // receiver (should be a token account)
        alice.publicKey, // mint authority
        1e8, // amount. if your decimals is 8, you mint 10^8 for 1 token.
        8 // decimals
        // [signer1, signer2 ...], // only multisig account will use
      )
    );
    console.log(
      `txhash: ${await connection.sendTransaction(tx, [
        feePayer,
        alice /* fee payer + mint authority */,
      ])}`
    );
  }
})();
// 1) use build-in function
{
  let txhash = await mintToChecked(
    connection, // connection
    feePayer, // fee payer
    mintPubkey, // mint
    tokenAccountPubkey, // receiver (should be a token account)
    alice, // mint authority
    1e8, // amount. if your decimals is 8, you mint 10^8 for 1 token.
    8 // decimals
  );
}
// or
// 2) compose by yourself
{
  let tx = new Transaction().add(
    createMintToCheckedInstruction(
      mintPubkey, // mint
      tokenAccountPubkey, // receiver (should be a token account)
      alice.publicKey, // mint authority
      1e8, // amount. if your decimals is 8, you mint 10^8 for 1 token.
      8 // decimals
      // [signer1, signer2 ...], // only multisig account will use
    )
  );
}
Paano maglipat ng mga token
Maaari kang maglipat ng mga token mula sa isang token account patungo sa isa pang token account.
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
} from "@solana/web3.js";
import {
  createTransferCheckedInstruction,
  TOKEN_PROGRAM_ID,
  transferChecked,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const mintPubkey = new PublicKey(
    "8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV"
  );
  const tokenAccountXPubkey = new PublicKey(
    "2XYiFjmU1pCXmC2QfEAghk6S7UADseupkNQdnRBXszD5"
  );
  const tokenAccountYPubkey = new PublicKey(
    "GMxZfDmpR1b3vdJYXHzdF5noVLQogZuUAsDHHQ3ytPfV"
  );
  // 1) use build-in function
  {
    let txhash = await transferChecked(
      connection, // connection
      feePayer, // payer
      tokenAccountXPubkey, // from (should be a token account)
      mintPubkey, // mint
      tokenAccountYPubkey, // to (should be a token account)
      alice, // from's owner
      1e8, // amount, if your deciamls is 8, send 10^8 for 1 token
      8 // decimals
    );
    console.log(`txhash: ${txhash}`);
  }
  // or
  // 2) compose by yourself
  {
    let tx = new Transaction().add(
      createTransferCheckedInstruction(
        tokenAccountXPubkey, // from (should be a token account)
        mintPubkey, // mint
        tokenAccountYPubkey, // to (should be a token account)
        alice.publicKey, // from's owner
        1e8, // amount, if your deciamls is 8, send 10^8 for 1 token
        8 // decimals
      )
    );
    console.log(
      `txhash: ${await connection.sendTransaction(tx, [
        feePayer,
        alice /* fee payer + owner */,
      ])}`
    );
  }
})();
// 1) use build-in function
{
  let txhash = await transferChecked(
    connection, // connection
    feePayer, // payer
    tokenAccountXPubkey, // from (should be a token account)
    mintPubkey, // mint
    tokenAccountYPubkey, // to (should be a token account)
    alice, // from's owner
    1e8, // amount, if your deciamls is 8, send 10^8 for 1 token
    8 // decimals
  );
}
// or
// 2) compose by yourself
{
  let tx = new Transaction().add(
    createTransferCheckedInstruction(
      tokenAccountXPubkey, // from (should be a token account)
      mintPubkey, // mint
      tokenAccountYPubkey, // to (should be a token account)
      alice.publicKey, // from's owner
      1e8, // amount, if your deciamls is 8, send 10^8 for 1 token
      8 // decimals
    )
  );
}
Paano magsunog ng mga token
Maaari kang magsunog ng token kung ikaw ang may-ari ng token.
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
} from "@solana/web3.js";
import {
  burnChecked,
  createBurnCheckedInstruction,
  TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const mintPubkey = new PublicKey(
    "8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV"
  );
  const tokenAccountPubkey = new PublicKey(
    "2XYiFjmU1pCXmC2QfEAghk6S7UADseupkNQdnRBXszD5"
  );
  // 1) use build-in function
  {
    let txhash = await burnChecked(
      connection, // connection
      feePayer, // payer
      tokenAccountPubkey, // token account
      mintPubkey, // mint
      alice, // owner
      1e8, // amount, if your deciamls is 8, 10^8 for 1 token
      8
    );
    console.log(`txhash: ${txhash}`);
  }
  // or
  // 2) compose by yourself
  {
    let tx = new Transaction().add(
      createBurnCheckedInstruction(
        tokenAccountPubkey, // token account
        mintPubkey, // mint
        alice.publicKey, // owner of token account
        1e8, // amount, if your deciamls is 8, 10^8 for 1 token
        8 // decimals
      )
    );
    console.log(
      `txhash: ${await connection.sendTransaction(tx, [
        feePayer,
        alice /* fee payer + token authority */,
      ])}`
    );
  }
})();
// 1) use build-in function
{
  let txhash = await burnChecked(
    connection, // connection
    feePayer, // payer
    tokenAccountPubkey, // token account
    mintPubkey, // mint
    alice, // owner
    1e8, // amount, if your deciamls is 8, 10^8 for 1 token
    8
  );
}
// or
// 2) compose by yourself
{
  let tx = new Transaction().add(
    createBurnCheckedInstruction(
      tokenAccountPubkey, // token account
      mintPubkey, // mint
      alice.publicKey, // owner of token account
      1e8, // amount, if your deciamls is 8, 10^8 for 1 token
      8 // decimals
    )
  );
}
Paano isara ang mga token account
Maaari mong isara ang isang token account kung ayaw mo na itong gamitin. Mayroong dalawang sitwasyon:
- Nakabalot na SOL - Ang pagsasara ng mga nagpalit na Nakabalot na SOL sa SOL
- Iba pang mga Token - Maaari mo lamang itong isara kung ang balanse ng token account ay 0.
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
} from "@solana/web3.js";
import { closeAccount, createCloseAccountInstruction } from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const tokenAccountPubkey = new PublicKey(
    "2XYiFjmU1pCXmC2QfEAghk6S7UADseupkNQdnRBXszD5"
  );
  // 1) use build-in function
  {
    let txhash = await closeAccount(
      connection, // connection
      feePayer, // payer
      tokenAccountPubkey, // token account which you want to close
      alice.publicKey, // destination
      alice // owner of token account
    );
    console.log(`txhash: ${txhash}`);
  }
  // or
  // 2) compose by yourself
  {
    let tx = new Transaction().add(
      createCloseAccountInstruction(
        tokenAccountPubkey, // token account which you want to close
        alice.publicKey, // destination
        alice.publicKey // owner of token account
      )
    );
    console.log(
      `txhash: ${await connection.sendTransaction(tx, [
        feePayer,
        alice /* fee payer + owner */,
      ])}`
    );
  }
})();
// 1) use build-in function
{
  let txhash = await closeAccount(
    connection, // connection
    feePayer, // payer
    tokenAccountPubkey, // token account which you want to close
    alice.publicKey, // destination
    alice // owner of token account
  );
}
// or
// 2) compose by yourself
{
  let tx = new Transaction().add(
    createCloseAccountInstruction(
      tokenAccountPubkey, // token account which you want to close
      alice.publicKey, // destination
      alice.publicKey // owner of token account
    )
  );
}
Paano magtakda ng awtoridad sa mga token account o mints
Maaari mong itakda/i-update ang awtoridad. Mayroong 4 na uri:
- MintTokens (mint account)
- FreezeAccount (mint account)
- AccountOwner (token account)
- CloseAccount (token account)
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
} from "@solana/web3.js";
import {
  AuthorityType,
  createSetAuthorityInstruction,
  setAuthority,
  TOKEN_PROGRAM_ID,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const randomGuy = Keypair.generate();
  console.log(`random guy: ${randomGuy.publicKey.toBase58()}`);
  const mintPubkey = new PublicKey(
    "8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV"
  );
  // authority type
  // 1) for mint account
  // AuthorityType.MintTokens
  // AuthorityType.FreezeAccount
  // 2) for token account
  // AuthorityType.AccountOwner
  // AuthorityType.CloseAccount
  // 1) use build-in function
  {
    let txhash = await setAuthority(
      connection, // connection
      feePayer, // payer
      mintPubkey, // mint account || token account
      alice, // current authority
      AuthorityType.MintTokens, // authority type
      randomGuy.publicKey // new authority (you can pass `null` to close it)
    );
    console.log(`txhash: ${txhash}`);
  }
  // or
  // 2) compose by yourself
  {
    let tx = new Transaction().add(
      createSetAuthorityInstruction(
        mintPubkey, // mint acocunt || token account
        alice.publicKey, // current auth
        AuthorityType.MintTokens, // authority type
        feePayer.publicKey // new auth (you can pass `null` to close it)
      )
    );
    console.log(
      `txhash: ${await connection.sendTransaction(tx, [
        feePayer,
        alice /* fee payer + origin auth */,
      ])}`
    );
  }
})();
// 1) use build-in function
{
  let txhash = await setAuthority(
    connection, // connection
    feePayer, // payer
    mintPubkey, // mint account || token account
    alice, // current authority
    AuthorityType.MintTokens, // authority type
    randomGuy.publicKey // new authority (you can pass `null` to close it)
  );
}
// or
// 2) compose by yourself
{
  let tx = new Transaction().add(
    createSetAuthorityInstruction(
      mintPubkey, // mint acocunt || token account
      alice.publicKey, // current auth
      AuthorityType.MintTokens, // authority type
      randomGuy.publicKey // new auth (you can pass `null` to close it)
    )
  );
}
Paano mag-apruba ng token delegate
Maaari kang magtakda ng delegado na may pinapayagang halaga. Pagkatapos mong magtakda, ang delegado ay parang isa pang may-ari ng iyong token account. Ang isang token account ay maaari lamang magtalaga sa isang account sa parehong oras
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
} from "@solana/web3.js";
import {
  approveChecked,
  createApproveCheckedInstruction,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const randomGuy = Keypair.generate();
  const mintPubkey = new PublicKey(
    "8mAKLjGGmjKTnmcXeyr3pr7iX13xXVjJJiL6RujDbSPV"
  );
  const tokenAccountPubkey = new PublicKey(
    "GMxZfDmpR1b3vdJYXHzdF5noVLQogZuUAsDHHQ3ytPfV"
  );
  // 1) use build-in function
  {
    let txhash = await approveChecked(
      connection, // connection
      feePayer, // fee payer
      mintPubkey, // mint
      tokenAccountPubkey, // token account
      randomGuy.publicKey, // delegate
      alice, // owner of token account
      1e8, // amount, if your deciamls is 8, 10^8 for 1 token
      8 // decimals
    );
    console.log(`txhash: ${txhash}`);
  }
  // or
  // 2) compose by yourself
  {
    let tx = new Transaction().add(
      createApproveCheckedInstruction(
        tokenAccountPubkey, // token account
        mintPubkey, // mint
        randomGuy.publicKey, // delegate
        alice.publicKey, // owner of token account
        1e8, // amount, if your deciamls is 8, 10^8 for 1 token
        8 // decimals
      )
    );
    console.log(
      `txhash: ${await connection.sendTransaction(tx, [
        feePayer,
        alice /* fee payer + owner */,
      ])}`
    );
  }
})();
// 1) use build-in function
{
  let txhash = await approveChecked(
    connection, // connection
    feePayer, // fee payer
    mintPubkey, // mint
    tokenAccountPubkey, // token account
    randomGuy.publicKey, // delegate
    alice, // owner of token account
    1e8, // amount, if your deciamls is 8, 10^8 for 1 token
    8 // decimals
  );
}
// or
// 2) compose by yourself
{
  let tx = new Transaction().add(
    createApproveCheckedInstruction(
      tokenAccountPubkey, // token account
      mintPubkey, // mint
      randomGuy.publicKey, // delegate
      alice.publicKey, // owner of token account
      1e8, // amount, if your deciamls is 8, 10^8 for 1 token
      8 // decimals
    )
  );
}
Paano bawiin ang isang token delegate
Itatakda ng pagbawi ang delegado sa null at itatakda ang delegadong halaga sa 0.
import {
  clusterApiUrl,
  Connection,
  PublicKey,
  Keypair,
  Transaction,
} from "@solana/web3.js";
import { createRevokeInstruction, revoke } from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  const tokenAccountPubkey = new PublicKey(
    "DRS5CSgPQp4uvPPcUA34tckfYFNUPNBJi77fVbnSfQHr"
  );
  // 1) use build-in function
  {
    let txhash = await revoke(
      connection, // connection
      feePayer, // payer
      tokenAccountPubkey, // token account
      alice // owner of token account
    );
    console.log(`txhash: ${txhash}`);
  }
  // or
  // 2) compose by yourself
  {
    let tx = new Transaction().add(
      createRevokeInstruction(
        tokenAccountPubkey, // token account
        alice.publicKey // owner of token account
      )
    );
    console.log(
      `txhash: ${await connection.sendTransaction(tx, [
        feePayer,
        alice /* fee payer + origin auth */,
      ])}`
    );
  }
})();
// 1) use build-in function
{
  let txhash = await revoke(
    connection, // connection
    feePayer, // payer
    tokenAccountPubkey, // token account
    alice // owner of token account
  );
}
// or
// 2) compose by yourself
{
  let tx = new Transaction().add(
    createRevokeInstruction(
      tokenAccountPubkey, // token account
      alice.publicKey // owner of token account
    )
  );
}
Paano i-manage ang wrapped SOL
Nakabalot na SOL tulad ng ibang token mint. Ang pagkakaiba ay gumagamit ng syncNative at paggawa ng mga token account partikular sa NATIVE_MINT na address.
Lumikha ng Token Account
Tulad ng Gumawa ng Token Account ngunit palitan ang mint ng NATIVE_MINT
import { NATIVE_MINT } from "@solana/spl-token";
Magdagdag ng Balanse
Mayroong dalawang paraan upang magdagdag ng balanse para sa Wrapped SOL
1. Sa pamamagitan ng SOL Transfer
import {
  clusterApiUrl,
  Connection,
  Keypair,
  Transaction,
  SystemProgram,
} from "@solana/web3.js";
import {
  NATIVE_MINT,
  getAssociatedTokenAddress,
  createSyncNativeInstruction,
  createAccount,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  // remember to create ATA first
  let ata = await getAssociatedTokenAddress(
    NATIVE_MINT, // mint
    alice.publicKey // owner
  );
  let amount = 1 * 1e9; /* Wrapped SOL's decimals is 9 */
  let tx = new Transaction().add(
    // trasnfer SOL
    SystemProgram.transfer({
      fromPubkey: alice.publicKey,
      toPubkey: ata,
      lamports: amount,
    }),
    // sync wrapped SOL balance
    createSyncNativeInstruction(ata)
  );
  console.log(
    `txhash: ${await connection.sendTransaction(tx, [feePayer, alice])}`
  );
})();
let tx = new Transaction().add(
  // trasnfer SOL
  SystemProgram.transfer({
    fromPubkey: alice.publicKey,
    toPubkey: ata,
    lamports: amount,
  }),
  // sync wrapped SOL balance
  createSyncNativeInstruction(ata)
);
2. By Token Transfer
import {
  clusterApiUrl,
  Connection,
  Keypair,
  Transaction,
  SystemProgram,
} from "@solana/web3.js";
import {
  TOKEN_PROGRAM_ID,
  NATIVE_MINT,
  getMinimumBalanceForRentExemptAccount,
  getAssociatedTokenAddress,
  ACCOUNT_SIZE,
  createInitializeAccountInstruction,
  createTransferInstruction,
  closeAccountInstructionData,
  createCloseAccountInstruction,
} from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  // 5YNmS1R9nNSCDzb5a7mMJ1dwK9uHeAAF4CmPEwKgVWr8
  const feePayer = Keypair.fromSecretKey(
    bs58.decode(
      "588FU4PktJWfGfxtzpAAXywSNt74AvtroVzGfKkVN1LwRuvHwKGr851uH8czM5qm4iqLbs1kKoMKtMJG4ATR7Ld2"
    )
  );
  // G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY
  const alice = Keypair.fromSecretKey(
    bs58.decode(
      "4NMwxzmYj2uvHuq8xoqhY8RXg63KSVJM1DXkpbmkUY7YQWuoyQgFnnzn6yo3CMnqZasnNPNuAT2TLwQsCaKkUddp"
    )
  );
  // remember to create ATA first
  let ata = await getAssociatedTokenAddress(
    NATIVE_MINT, // mint
    alice.publicKey // owner
  );
  let auxAccount = Keypair.generate();
  let amount = 1 * 1e9; /* Wrapped SOL's decimals is 9 */
  let tx = new Transaction().add(
    // create token account
    SystemProgram.createAccount({
      fromPubkey: alice.publicKey,
      newAccountPubkey: auxAccount.publicKey,
      space: ACCOUNT_SIZE,
      lamports:
        (await getMinimumBalanceForRentExemptAccount(connection)) + amount, // rent + amount
      programId: TOKEN_PROGRAM_ID,
    }),
    // init token account
    createInitializeAccountInstruction(
      auxAccount.publicKey,
      NATIVE_MINT,
      alice.publicKey
    ),
    // transfer WSOL
    createTransferInstruction(
      auxAccount.publicKey,
      ata,
      alice.publicKey,
      amount
    ),
    // close aux account
    createCloseAccountInstruction(
      auxAccount.publicKey,
      alice.publicKey,
      alice.publicKey
    )
  );
  console.log(
    `txhash: ${await connection.sendTransaction(tx, [
      feePayer,
      auxAccount,
      alice,
    ])}`
  );
})();
let tx = new Transaction().add(
  // create token account
  SystemProgram.createAccount({
    fromPubkey: alice.publicKey,
    newAccountPubkey: auxAccount.publicKey,
    space: ACCOUNT_SIZE,
    lamports:
      (await getMinimumBalanceForRentExemptAccount(connection)) + amount, // rent + amount
    programId: TOKEN_PROGRAM_ID,
  }),
  // init token account
  createInitializeAccountInstruction(
    auxAccount.publicKey,
    NATIVE_MINT,
    alice.publicKey
  ),
  // transfer WSOL
  createTransferInstruction(auxAccount.publicKey, ata, alice.publicKey, amount),
  // close aux account
  createCloseAccountInstruction(
    auxAccount.publicKey,
    alice.publicKey,
    alice.publicKey
  )
);
Paano makuha ang lahat ng token account ng may-ari
Maaari kang kumuha ng mga token account ng may-ari. Mayroong dalawang paraan upang gawin ito.
- Kunin ang Lahat ng Token Account
import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  const owner = new PublicKey("G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY");
  let response = await connection.getParsedTokenAccountsByOwner(owner, {
    programId: TOKEN_PROGRAM_ID,
  });
  response.value.forEach((accountInfo) => {
    console.log(`pubkey: ${accountInfo.pubkey.toBase58()}`);
    console.log(`mint: ${accountInfo.account.data["parsed"]["info"]["mint"]}`);
    console.log(
      `owner: ${accountInfo.account.data["parsed"]["info"]["owner"]}`
    );
    console.log(
      `decimals: ${accountInfo.account.data["parsed"]["info"]["tokenAmount"]["decimals"]}`
    );
    console.log(
      `amount: ${accountInfo.account.data["parsed"]["info"]["tokenAmount"]["amount"]}`
    );
    console.log("====================");
  });
})();
let response = await connection.getParsedTokenAccountsByOwner(owner, {
  programId: TOKEN_PROGRAM_ID,
});
- Filter By Mint
import { clusterApiUrl, Connection, PublicKey } from "@solana/web3.js";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import * as bs58 from "bs58";
(async () => {
  // connection
  const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
  const owner = new PublicKey("G2FAbFQPFa5qKXCetoFZQEvF9BVvCKbvUZvodpVidnoY");
  const mint = new PublicKey("54dQ8cfHsW1YfKYpmdVZhWpb9iSi6Pac82Nf7sg3bVb");
  let response = await connection.getParsedTokenAccountsByOwner(owner, {
    mint: mint,
  });
  response.value.forEach((accountInfo) => {
    console.log(`pubkey: ${accountInfo.pubkey.toBase58()}`);
    console.log(`mint: ${accountInfo.account.data["parsed"]["info"]["mint"]}`);
    console.log(
      `owner: ${accountInfo.account.data["parsed"]["info"]["owner"]}`
    );
    console.log(
      `decimals: ${accountInfo.account.data["parsed"]["info"]["tokenAmount"]["decimals"]}`
    );
    console.log(
      `amount: ${accountInfo.account.data["parsed"]["info"]["tokenAmount"]["amount"]}`
    );
    console.log("====================");
  });
})();
let response = await connection.getParsedTokenAccountsByOwner(owner, {
  mint: mint,
});