閱讀時間 19 分鐘
本指南提供 Solana Web3.js(舊版 v 1.x)和 Solana Kit(v 2.x)兩種版本。請選擇相應的分頁,以查看您偏好的函式庫所對應的程式碼片段和操作說明:
- Solana 套件
- Solana Web3.js(舊版)
概覽
傳送 Solana 程式庫(SPL)代幣是 Solana 開發中的關鍵機制。無論您是向社群空投白名單代幣、批量將 NFT 傳送至其他錢包,還是管理託管帳戶之間的代幣流動,都不可避免地需要能夠轉移 SPL 代幣。轉移 SPL 代幣與傳送 SOL 略有不同,因此在您的 Solana 開發過程中,了解其運作原理至關重要。
您將負責的工作內容
在本指南中,您將使用 TypeScript 撰寫一個腳本,將 SPL 代幣從一個帳戶轉移到另一個帳戶,操作環境為 Solana 的開發網。
如果您想了解如何在使用 Anchor Framework 的程式中轉移 SPL 代幣和 SOL,請參閱我們的指南:《如何使用 Anchor 轉移 SOL 和 SPL 代幣》 。
想看影片教學嗎?跟著 Sahil 一起學習如何在 Solana Devnet 上轉移 SPL 代幣。
您需要準備的物品
SPL 代幣帳戶概覽
在開始之前,了解 Solana 代幣計畫帳戶中的幾個組成部分——鑄造 ID 和相關聯的代幣帳戶——是如何運作的,將有所幫助。
Mint ID
每個 SPL 代幣都有一個唯一的鑄造 ID,可用於將其與任何其他類型的代幣區分開來。 例如,$USDC SPL 代幣的鑄造 ID 為EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,而 $SAMO 的鑄造 ID 則為7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU。
值得注意的是,每個 NFT 都有一個獨一無二的鑄造地址(這正是使其具有不可替代性的部分原因)。例如, 「Famous Fox #4679」的鑄造 ID 為GS2AtoEoL9DgaYg9xC7cUumftB7vb2CPMrczZCKgJv1Y,而「Famous Fox #6562」的鑄造 ID 則為7FTdQdMqkk5Xc2oFsYR88BuJt2yyCPReTpqr3viH6b6C。 正如您稍後將看到的,這正是這兩枚代幣之間的一項重要區別。
若想進一步了解如何鑄造 SPL 代幣,請參閱我們的指南: 《如何使用新的 Metaplex 代幣標準創建可互換的 SPL 代幣》 以及 《如何在 Solana 上鑄造 NFT》。
相關代幣帳戶
Solana 代幣計畫會「根據用戶的主要系統帳戶地址和代幣鑄造地址,生成一個代幣帳戶金鑰,讓用戶能夠為其持有的每種代幣建立一個主要代幣帳戶」(來源:spl.solana.com)。該帳戶被稱為「關聯代幣帳戶」(Associated Token Account,簡稱 ATA)。實際上,ATA 是一個與用戶及特定代幣鑄造相關聯的唯一帳戶。 舉例來說,假設我是帳號「DEMO...1234」的所有者。我可以擁有多個 ATA——每個 ATA 對應我持有的每種代幣鑄造(例如,每個 $USDC、$SAMO 等代幣各對應一個唯一的 ATA,如下圖所示)。

代幣轉帳必須始終發生在兩個與同一鑄幣地址相關聯的 ATA 之間。這意味著我們無法將 $USDC 從我的 ATA 轉帳至您的 $SAMO ATA(參見下方範例)。

正如您稍後將在我們的程式碼中看到的,並非每個帳戶都已針對每個鑄幣廠擁有 ATA。如果使用者先前未曾與某個代幣進行過互動,發送者必須「建立」該 ATA,並存入必要的租金,以維持該帳戶的活躍狀態。
這個概念起初可能有些棘手,但非常重要,所以請花點時間確保自己確實理解!我發現透過 Solana Explorer 瀏覽我的錢包,並查看代幣詳細資訊頁面(https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?display=detail)會很有幫助。你可以在該頁面看到你擁有的每枚 ATA、其帳戶 ID 以及對應的鑄造 ID:

若您想進一步了解 Solana SPL 代幣計畫函式庫,請前往spl.solana.com。
準備好開始寫程式了嗎?我也是!
設定您的專案
- Solana 套件
- Solana Web3.js(舊版)
請在終端機中使用以下指令建立一個新的專案目錄:
mkdir spl-transfer-kit
cd spl-transfer-kit
為您的應用程式建立一個名為app.ts 的檔案:
echo > app.ts
請使用「yes」參數初始化您的專案,以便為新套件採用預設值:
yarn init --yes
#或
npm init --yes
建立一個採用現代模組解析方式的tsconfig.json檔案:
tsc --init
請將您的tsconfig.json更新為以下內容:
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noEmit": true,
"target": "ESNext"
}
}
安裝 Solana Kit 的依賴項
在本次練習中,我們需要安裝 Solana Kit 以及 Token 程式庫。請在終端機中輸入:
yarn add @solana/kit @solana-program/token
#或
npm install @solana/kit @solana-program/token
請在終端機中使用以下指令建立一個新的專案目錄:
mkdir spl-transfer
cd spl-transfer
為您的應用程式建立一個名為app.ts 的檔案:
echo > app.ts
請使用「yes」參數初始化您的專案,以便為新套件採用預設值:
yarn init --yes
#或
npm init --yes
建立一個已啟用 .json 匯入功能的tsconfig.json檔案:
tsc -init --resolveJsonModule true
安裝 Solana Web3 依賴項
在本次練習中,我們需要加入 Solana Web3 和 SPL Token 函式庫。請在終端機中輸入:
yarn add @solana/web3.js@1 @solana/spl-token
#或
npm install @solana/web3.js@1 @solana/spl-token
建立錢包並領取 SOL 空投
- Solana 套件
- Solana Web3.js(舊版)
我們首先需要完成的任務,是建立一個附帶錢包的帳戶,並為其充值。我們將使用下方的便捷工具,自動生成一個新錢包,並向其中空投 1 SOL。
注意:若過於頻繁地發送空投請求,可能會觸發 429(請求過多)錯誤。
成功產生金鑰對後,您會發現有兩個新的常數: 秘密 以及 FROM_KEYPAIR, 一組金鑰對。該 秘密 是一個 32 位元組的陣列,用於產生公鑰和私鑰。該 FROM_KEYPAIR 這是一個用於簽署交易的 Keypair 實例(我們已空投了一些開發網 SOL 來支付 gas 費用)。若您尚未將其加入程式碼中,請務必在其他常數下方將其加入。
在您的 `imports` 下方,貼上您的新秘密陣列:
const secret = [0,...,0]; // 👈 請替換為您的密鑰
我們首先需要完成的任務,是建立一個附帶錢包的帳戶並為其充值。我們將使用下方的便捷工具,自動生成一個新錢包,並向其中空投 1 SOL。(您也可以透過 Keypair.generate() 以及 requestAirdrop() (若您偏好更為手動的方式,也可使用這些函式)。
注意:若過於頻繁地發送空投請求,可能會觸發 429(請求過多)錯誤。
成功產生金鑰對後,您會發現有兩個新的常數: 秘密 以及 FROM_KEYPAIR, 一組金鑰對。該 秘密 是一個 32 位元組的陣列,用於產生公鑰和私鑰。該 FROM_KEYPAIR 這是一個用於簽署交易的 Keypair 實例(我們已空投了一些開發網 SOL 來支付 gas 費用)。若您尚未將其加入程式碼中,請務必在其他常數下方將其加入。
在您的 `import` 語句下方,貼上新的密鑰,並加入:
import { Keypair } from "@solana/web3.js";
const secret = [0,...,0]; // 👈 Replace with your secret
const FROM_KEYPAIR = Keypair.fromSecretKey(new Uint8Array(secret));
console.log(`My public key is: ${FROM_KEYPAIR.publicKey.toString()}.`);
鑄造或空投一些 SPL 代幣
要完成本指南,您需要在 Devnet 上取得一些 SPL 代幣。取得 Devnet SPL 代幣的方法有幾種——以下列舉其中幾種。
- 發行您自己的可互換代幣(指南:如何使用新的 Metaplex 代幣標準創建可互換的 SPL 代幣)。
- 使用 Candy Machine 鑄造一個或多個 NFT(指南:《如何使用 Sugar(Candy Machine)在 Solana 上部署 NFT 系列》)。
- 向SPL 代幣水龍頭申請 $DUMMY 代幣空投。*
- 如果您已在其他錢包中持有 Devnet SPL 代幣,您可以透過 Phantom 或其他錢包介面將其轉出。*
在繼續之前,您應能前往 Solana 區塊鏈瀏覽器,並確認您的錢包在開發網(devnet)上擁有 SOL 餘額以及至少一種 SPL 代幣(https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?cluster=devnet)。畫面應類似如下:

我們開始吧。
設定您的應用程式
匯入必要的依賴項
- Solana 套件
- Solana Web3.js(舊版)
開啟app.ts 檔案,並將以下導入語句貼到第 1 行:
import {
createSolanaRpc,
createSolanaRpcSubscriptions,
address,
pipe,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstruction,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
airdropFactory,
lamports,
getSignatureFromTransaction,
createKeyPairFromBytes,
createSignerFromKeyPair
} from '@solana/kit';
import {
TOKEN_PROGRAM_ADDRESS,
fetchToken,
getTransferInstruction,
findAssociatedTokenPda,
getCreateAssociatedTokenIdempotentInstruction
} from '@solana-program/token';
除了在上一步驟中建立的錢包之外,我們還從 Solana Kit 和 Token 程式庫中導入了必要的方法和類別。
開啟app.ts 檔案,並將以下導入語句貼到第 1 行:
import { getOrCreateAssociatedTokenAccount, createTransferInstruction } from "@solana/spl-token";
import { Connection, Keypair, ParsedAccountData, PublicKey, sendAndConfirmTransaction, Transaction } from "@solana/web3.js";
除了在上一步驟中建立的錢包之外,我們還將從 Solana Web3 函式庫中導入幾個必備的方法和類別。
設定您的 Quicknode 端點
- Solana 套件
- Solana Web3.js(舊版)
若要在 Solana 上進行開發,您需要一個 API 端點來連線至網路。您可以使用公開節點,或自行部署並管理基礎架構;不過,若您希望將回應時間縮短 8 倍,不妨將繁重的工作交給我們處理。了解為何超過 50% 的 Solana 專案選擇 Quicknode,並在此註冊帳號。我們將使用一個 Solana Devnet 節點。
複製 HTTP 提供者連結:

在app.ts檔案中,於 import 語句下方宣告您的 RPC,並建立與 Solana 的連線:
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';
const QUICKNODE_RPC_SUBSCRIPTIONS = 'wss://example.solana-devnet.quiknode.pro/0123456/';
const rpc = createSolanaRpc(QUICKNODE_RPC);
const rpcSubscriptions = createSolanaRpcSubscriptions(QUICKNODE_RPC_SUBSCRIPTIONS);
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
請務必將 QUICKNODE_RPC 以及 QUICKNODE_RPC_SUBSCRIPTIONS 請填入您實際的 Quicknode 端點網址(來自 Quicknode 儀表板的 https 和 wss 連結)。
若要在 Solana 上進行開發,您需要一個 API 端點來連線至網路。您可以使用公開節點,或自行部署並管理基礎架構;不過,若您希望將回應時間縮短 8 倍,不妨將繁重的工作交給我們處理。了解為何超過 50% 的 Solana 專案選擇 Quicknode,並在此註冊帳號。我們將使用一個 Solana Devnet 節點。
複製 HTTP 提供者連結:

在app.ts檔案中,於 import 語句下方,宣告您的 RPC 並建立與 Solana 的連線:
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/0123456/';
const SOLANA_CONNECTION = new Connection(QUICKNODE_RPC);
宣告變數
- Solana 套件
- Solana Web3.js(舊版)
要執行您的腳本,您需要宣告幾個變數:目標帳戶(您希望將代幣轉帳給的持有者)、您要轉帳的代幣的鑄造地址,以及要轉帳的代幣數量。請在 RPC 設定下方加入以下宣告:
const DESTINATION_WALLET = 地址('DemoKMZWkk483hX4mUrcJoo3zVvsKhm8XXs28TuwZw9H');
const MINT_ADDRESS = 地址('DoJuta7joTSuuoozqQtjtnASRYiVsT435gh4srh5LLGK'); //您必須變更此值!
const TRANSFER_AMOUNT = 1n; // 使用 BigInt 來精確表示代幣金額
替換 MINT_ADDRESS 並填入您打算發送的代幣的鑄造地址。如果您不知道該代幣的鑄造地址,可以前往 https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?cluster=devnet 然後點擊 複製 圖示以擷取您的 Mint 地址。將其貼上至 MINT_ADDRESS 變數。

注意:您也可以更新您的 DESTINATION_WALLET 地址及 TRANSFER_AMOUNT ,但在此範例中,這兩種數值皆可正常運作。
要執行您的腳本,您需要宣告幾個變數:目標帳戶(您希望將代幣轉帳給的持有者)、您要轉帳的代幣的鑄造地址,以及要轉帳的代幣數量。請在下方加入以下宣告 SOLANA_CONNECTION:
const DESTINATION_WALLET = 'DemoKMZWkk483hX4mUrcJoo3zVvsKhm8XXs28TuwZw9H';
const MINT_ADDRESS = 'DoJuta7joTSuuoozqQtjtnASRYiVsT435gh4srh5LLGK'; //您必須修改此值!
const TRANSFER_AMOUNT = 1;
替換 MINT_ADDRESS 並填入您打算發送的代幣的鑄造地址。如果您不知道該代幣的鑄造地址,可以前往 https://explorer.solana.com/address/YOUR_WALLET_ADDRESS/tokens?cluster=devnet 然後點擊 複製 圖示以擷取您的 Mint 地址。將其貼上至 MINT_ADDRESS 變數。

注意:您也可以更新您的 DESTINATION_WALLET 地址及 TRANSFER_AMOUNT ,但在此範例中,這兩種數值皆可正常運作。
取得小數位數
- Solana 套件
- Solana Web3.js(舊版)
如果您之前曾創建過可互換的 SPL 代幣,您就會知道小數位數至關重要。 由於區塊鏈將代幣供應量以整數值表示,我們必須根據代幣元數據中分配的小數位數來轉換代幣數量(例如,若鑄造時設定了三位小數,則必須傳送 1,000 單位才能有效轉移一個代幣 [1,000 / 10**3])。
要取得小數資料,我們將呼叫rpc實例上的getAccountInfo 函式,並解析 mint 帳戶資料。請在宣告語句下方加入此函式:
async function getNumberDecimals(mintAddress) {
// getAccountInfo defaults to binary, using `jsonParsed` lets us read parsed.info.decimals without manual byte offsets.
const accountInfo = await rpc.getAccountInfo(mintAddress, { encoding: 'jsonParsed' }).send();
const data = accountInfo.value?.data;
if (!data || !('parsed' in data) || !data.parsed?.info) {
throw new Error('Failed to find mint account');
}
return (data.parsed.info as { decimals: number }).decimals;
}
嚴格來說,如果你知道代幣鑄造時的小數位數(可在 Solana Explorer 的代幣頁面中查閱),其實就不需要這個參數。不過,我們還是希望將其納入,因為這樣一來,你就能在處理不同鑄造時修改程式碼,而無需變更其他變數。
現在就來談談有趣的部分吧!
如果您之前曾創建過可互換的 SPL 代幣,您就會知道小數位數至關重要。 由於區塊鏈將代幣供應量以整數值表示,我們必須根據代幣元數據中分配的小數位數來轉換代幣數量(例如,若鑄造時設定了三位小數,則必須傳送 1,000 單位才能有效轉移一個代幣 [1,000 / 10**3])。
要擷取小數資料,我們將呼叫SOLANA_CONNECTION上的getParsedAccountInfo方法,並傳入 tokenMINT_ADDRESS。由於該方法可能傳回多種資料型別,我們需要將資料型別宣告為ParsedAccountData,才能有效解析資料。請在宣告區塊下方加入此函式:
async function getNumberDecimals(mintAddress: string):Promise<number> {
const info = await SOLANA_CONNECTION.getParsedAccountInfo(new PublicKey(MINT_ADDRESS));
const result = (info.value?.data as ParsedAccountData).parsed.info.decimals as number;
return result;
}
嚴格來說,如果你知道代幣鑄造時的小數位數(可在 Solana Explorer 的代幣頁面中查閱),其實就不需要這個參數。不過,我們還是希望將其納入,因為這樣一來,你就能在處理不同鑄造時修改程式碼,而無需變更其他變數。
現在就來談談有趣的部分吧!
建立傳遞函數
- Solana 套件
- Solana Web3.js(舊版)
建立一個新的非同步函式sendTokens:
async 函式 sendTokens() {
}
首先,我們需要根據秘密陣列建立簽署金鑰對,並為其注入 SOL。在 `sendTokens` 函式內部,新增步驟 1:
console.log(`Sending ${TRANSFER_AMOUNT} ${MINT_ADDRESS} to ${DESTINATION_WALLET}.`)
//Step 1
console.log(`1 - Creating keypair and funding with SOL`);
const keyPair = await createKeyPairFromBytes(new Uint8Array(secret));
const FROM_KEYPAIR = await createSignerFromKeyPair(keyPair);
// Fund the keypair with SOL for transaction fees
// (you can skip this step if you already have devnet SOL in your FROM_KEYPAIR)
await airdropFactory({ rpc, rpcSubscriptions })({
recipientAddress: FROM_KEYPAIR.address,
lamports: lamports(1_000_000_000n), // 1 SOL
commitment: 'confirmed',
});
console.log(` From wallet: ${FROM_KEYPAIR.address}`);
注意:在正式環境中,您應使用
generateKeyPairFromBytes(new Uint8Array(secret))請使用您實際的密鑰,而非產生一個新的密鑰。
接下來,我們將為來源帳戶和目的地帳戶推導出「關聯代幣帳戶」(「ATA」)。請記住,每個帳戶都必須有一個 ATA,用以將錢包與鑄造方關聯起來;一個 ATA 只能持有單一鑄造方的代幣;且發送方與接收方的關聯代幣帳戶所對應的鑄造方必須相同。新增步驟 2:
//Step 2
console.log(`2 - Deriving Associated Token Accounts`);
const [sourceTokenAccount] = await findAssociatedTokenPda({
owner: FROM_KEYPAIR.address,
mint: MINT_ADDRESS,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
const [destinationTokenAccount] = await findAssociatedTokenPda({
owner: DESTINATION_WALLET,
mint: MINT_ADDRESS,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
console.log(` Source Token Account: ${sourceTokenAccount}`);
console.log(` Destination Token Account: ${destinationTokenAccount}`);
接下來,我們需要檢查目標代幣帳戶是否存在,並在必要時建立該帳戶。新增步驟 3:
console.log(`3 - Checking Destination Token Account`);
let needsDestinationAccount = false;
try {
await rpc.getAccountInfo(destinationTokenAccount).send();
} catch (error) {
needsDestinationAccount = true;
}
if (needsDestinationAccount) {
console.log(` Destination token account does not exist, will create it`);
} else {
console.log(` Destination token account exists`);
}
為了正確計算金額,讓我們取得小數位數。新增步驟 4:
//Step 4
console.log(`4 - Fetching Number of Decimals for Mint: ${MINT_ADDRESS}`);
const numberDecimals = await getNumberDecimals(MINT_ADDRESS);
console.log(` Number of Decimals: ${numberDecimals}`);
const transferAmountWithDecimals = TRANSFER_AMOUNT * BigInt(Math.pow(10, numberDecimals));
最後,我們需要使用 Solana Kit 的函式式編程方法來組裝並發送交易。新增步驟 5:
//Step 5
console.log(`5 - Creating and Sending Transaction`);
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(FROM_KEYPAIR, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => {
// Add create ATA instruction if needed
if (needsDestinationAccount) {
return appendTransactionMessageInstruction(
getCreateAssociatedTokenIdempotentInstruction({
payer: FROM_KEYPAIR,
ata: destinationTokenAccount,
owner: DESTINATION_WALLET,
mint: MINT_ADDRESS,
}),
tx
);
}
return tx;
},
(tx) => appendTransactionMessageInstruction(
getTransferInstruction({
source: sourceTokenAccount,
destination: destinationTokenAccount,
authority: FROM_KEYPAIR,
amount: transferAmountWithDecimals,
}),
tx
)
);
const signedTransaction = await signTransactionMessageWithSigners(transactionMessage);
await sendAndConfirmTransaction(signedTransaction, { commitment: 'confirmed' });
const signature = await getSignatureFromTransaction(signedTransaction);
console.log(
'\x1b[32m', //Green Text
` Transaction Success!🎉`,
`\n https://explorer.solana.com/tx/${signature}?cluster=devnet`
);
建立一個新的非同步函式sendTokens:
async 函式 sendTokens() {
}
首先,我們需要取得來源帳戶與目的地帳戶的「關聯代幣帳戶」(「ATA」)。請注意,每個帳戶都必須擁有一個 ATA,用以將錢包與鑄造廠關聯起來;一個 ATA 只能持有單一鑄造廠的代幣;且發送方與接收方的關聯代幣帳戶所屬鑄造廠必須相同。
我們將使用getOrCreateAssociatedTokenAccount來為這筆交易的每一方取得 ATA(若不存在則建立)。由於我們可能需要為這些交易建立關聯帳戶,因此付款方可能必須向新的 ATA 存入少量 SOL 以支付租金。 在`sendTokens` 函式內部,請在您的程式碼中加入步驟 1,以取得來源帳戶(嚴格來說,由於我們已知持有 SPL 代幣——也就是說我們已經擁有 ATA,因此也可以使用`getAssociatedTokenAddress`):
console.log(`Sending ${TRANSFER_AMOUNT} ${(MINT_ADDRESS)} from ${(FROM_KEYPAIR.publicKey.toString())} to ${(DESTINATION_WALLET)}.`)
//Step 1
console.log(`1 - Getting Source Token Account`);
let sourceAccount = await getOrCreateAssociatedTokenAccount(
SOLANA_CONNECTION,
FROM_KEYPAIR,
new PublicKey(MINT_ADDRESS),
FROM_KEYPAIR.publicKey
);
console.log(` Source Account: ${sourceAccount.address.toString()}`);
我們將對「目的地帳戶」執行相同的操作。請參照以下第 2 步,以取得或建立我們的「目的地帳戶」(即代幣將被傳送至的收件者 ATA):
//Step 2
console.log(`2 - Getting Destination Token Account`);
let destinationAccount = await getOrCreateAssociatedTokenAccount(
SOLANA_CONNECTION,
FROM_KEYPAIR,
new PublicKey(MINT_ADDRESS),
new PublicKey(DESTINATION_WALLET)
);
console.log(` Destination Account: ${destinationAccount.address.toString()}`);
要完成這筆交易,還需要一項資訊。還記得我們之前建立的getNumberDecimals函式嗎?現在就呼叫該函式,並將回傳的值儲存到一個名為numberDecimals 的常數中:
//Step 3
console.log(`3 - Fetching Number of Decimals for Mint: ${MINT_ADDRESS}`);
const numberDecimals = await getNumberDecimals(MINT_ADDRESS);
console.log(` Number of Decimals: ${numberDecimals}`);
最後,我們需要組裝並發送這筆交易。請在「步驟 3」下方加入以下指令組:
//步驟 4
控制台.log(`4 - 建立並傳送交易`);
const tx = new Transaction();
tx.add(建立轉帳指示(
sourceAccount.地址,
destinationAccount.地址,
FROM_KEYPAIR.publicKey,
TRANSFER_AMOUNT * Math.pow(10, numberDecimals)
))
- Solana 套件
- Solana Web3.js(舊版)
我們在此要做的,是指示我們的應用程式將TRANSFER_AMOUNT個代幣(請注意,必須乘以 10 的numberDecimals 次方)從sourceTokenAccount轉移至destinationTokenAccount。
Solana Kit 的做法採用函式式程式設計風格,並結合了 管子 函式,用於逐步組建交易。這能提供更好的類型安全性,並使交易建構過程更加明確。此外,若目標 ATA 不存在,我們也會在同一筆交易中透過幂等指令來建立它;此指令即使帳戶已存在也不會失敗。
別在意那個 console.log——那只是個小技巧,用來讓成功訊息以綠色文字顯示。
我們在此要做的,是指示我們的應用程式將TRANSFER_AMOUNT個代幣(請注意,我們必須將該數值乘以 10 的numberDecimals 次方)從我們取得來源帳戶(sourceAccount)轉移至我們取得目標帳戶(destinationAccount)。
根據最佳實務,我們應在傳送交易前先取得最新的區塊哈希值。請將以下程式碼片段新增至您的 `sendTokens` 函式中「步驟 4」的結尾處:
const latestBlockHash = await SOLANA_CONNECTION.getLatestBlockhash('confirmed');
tx.recentBlockhash = await latestBlockHash.blockhash;
const signature = await sendAndConfirmTransaction(SOLANA_CONNECTION,tx,[FROM_KEYPAIR]);
console.log(
'\x1b[32m', //Green Text
` Transaction Success!🎉`,
`\n https://explorer.solana.com/tx/${signature}?cluster=devnet`
);
別在意那個 console.log——那只是個小技巧,用來讓成功訊息以綠色文字顯示。
🏃♂️ 執行您的程式碼
- Solana 套件
- Solana Web3.js(舊版)
最後,在程式碼結尾處呼叫sendTokens:
sendTokens().catch(控制台.error);
在終端機中,輸入以下指令來執行您的程式碼:
ts-node app.ts
恭喜!如果您已按照上述步驟操作,應該會看到類似以下的內容:

最後,在程式碼結尾處呼叫sendTokens:
sendTokens();
在終端機中,輸入以下指令來執行您的程式碼:
ts-node app.ts
恭喜!如果您已按照上述步驟操作,應該會看到類似以下的內容:

後續步驟與總結
太棒了!現在你已經知道如何將 SPL 代幣從一位使用者轉移給另一位使用者了!想更進一步嗎?以下提供幾個建議,讓你能將這項功能發揮得更徹底:
-
你能寫一個腳本,將你所有的 NFT 轉移到另一個錢包嗎?(提示:你可能需要先研究一下如何取得使用者錢包中的所有代幣)。
-
你能撰寫一個腳本,將 SPL 代幣透過 Airdrop 發放給一批錢包嗎?這些錢包可能與你的鑄造相關聯,也可能沒有。(提示:不妨參考我們關於批量發送 SOL 分發的指南,以獲取靈感)。
如果你願意試試看,或者有任何問題想問我們,請告訴我們!歡迎在Discord和Twitter 上找到我們!
我們 ❤️ 您的回饋!
如果您有任何意見回饋或對新主題的建議,請告訴我們。我們非常樂意聽取您的意見。
