玩轉 Solana 上的 Defi 模組 - Token Extension(下)

閱讀時間約 21 分鐘



raw-image


Token Extension的主角之一 Transfer Fee

目前官方釋出的代幣擴充功能總共 14 項,其中又以 Transfer fee 這個擴充為最多人使用。從 Dune 的數據可看出Transfer fee 幾乎成了整個token extension 的主要應用,Transfer fee 嚴格規範了每筆轉帳交易的手續費,讓代幣的發行者擁有更好手續費來源,同時也保障 NFT 創作者的版稅收益。

Token Extension stat - Dune

Token Extension stat - Dune


為了更深入了解 Transfer fee,以下將介紹 Transfer fee 的具體創建及應用:


(一)package 安裝與基本設定


今天的教程裡,我們將會用到 Bun 作為我們套件管理工具和執行環境,不只處理速度上非常快,我們也能省去不少轉譯的時間,最後一行則是安裝 Solana 常見的兩個 package 。

打開你習慣的編輯器,輸入以下指令

mkdir token-extension-transfer-fees

cd token-extension-transfer-fees/

bun init -y

bun add @solana/web3.js @solana/spl-token


安裝完成 package 之後,我們接著將
1. 建立一個與Devnet 連結的 Connection(我們將會都在 Devnet 進行交易)

  1. 建立一個 Solana 帳戶,同時將私鑰儲存在地端的 secret.txt文件
  2. 成功建立帳戶後,空投 SOL 到上面的帳戶裡,作為接下來交易的手續費

將如下的程式碼複製到你的 Bun 替你建立好的 index.ts 文件裡,複製成功後

可在終端機輸入 bun run index.ts 檢查是否成功建立 Solana 帳號,並成功獲得的空投作為進行交易的手續費

import {
clusterApiUrl,
Connection,
Keypair,
LAMPORTS_PER_SOL,
} from "@solana/web3.js";

// 1. create Connection with Devnet
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const FILE_PATH = "./secret.txt";

// 2. create payer account
const secretFileIsExist = await Bun.file(FILE_PATH).exists();
if (!secretFileIsExist) {
const payer = Keypair.generate();
await Bun.write(FILE_PATH, payer.secretKey);
}

const secret = await Bun.file(FILE_PATH)
.arrayBuffer()
.then((buffer) => new Uint8Array(buffer));
const payer = Keypair.fromSecretKey(secret);
console.log("🚀 Payer: ", payer.publicKey.toString());

// 3. request Airdrop 1 SOL
const accountBalance = await connection.getBalance(payer.publicKey);
console.log("🚀 account balance:", accountBalance);
if (accountBalance == 0) {
const airdropSig = await connection.requestAirdrop(
payer.publicKey,
LAMPORTS_PER_SOL,
);
await connection.confirmTransaction({
signature: airdropSig,
...(await connection.getLatestBlockhash()),
});

console.log("aridrop to: ", payer.publicKey);
}

// 完成後將會看類似如下的資訊​
// 🚀 Payer: Du9vC64s1ZJRY1i7qfA1CWvt6hWMwEeguebifqsjztcC
// 🚀 account balance: 978490640



(二)建立 Mint Account & 相關 Config


成功請求 SOL 後,我們就可以開始進行打包交易了。這邊我們會先試著建立一個全新的 token,並設定一些 transfer fee 所需要的config,例如手續費的收取%數、手續費的最高酌收數量以及一些正常 token account 會需要的一些 metadata, ex: decimals.

1. 建立所需要的帳戶(在 Solana 上如果要儲存任何資訊,需要建立 Account 作為儲存資料的最小單位)

  1. 設定 token 資訊以及 transfer fee hook 的 config(要注意到的是 transfer fee 所支援的 fee % 數是用 bps, 萬分之一下去算的。因此我們要酌收0.5% (50/10000) 的手續費的話,需要輸入 ”50“)
  2. 計算帳戶所需要的空間與租金。(在創立Account的同時,為了避免浪費空間的使用以及閒置數據的佔用,影響鏈上的儲存空間與效率,我們需要再建立 Account 的同時宣告佔用的大小以及維持儲存空間的租金)
  3. 建立所需的指令( Instructions ):在這裡我們建立了三個不同的指令:建立 Mint Account 、初始化和設定 Config 變數、初始化和設定 Mint Account(要注意,由於區塊鏈在執行交易時是按照順序進行執行,不同指令的前後關係會影響鏈上執行的結果。舉例來說,我們如果再打包交易時將 initializeMintInstruction 這筆指令擺在創造帳戶的指令 createAccountInstruction 前面,會造成交易失敗,因為要設定 mint Account 時,這個 Account 尚未被建立)
  4. 打包所有指令並送出交易
...

// 1. create required accounts
const mintAuthority = Keypair.generate();
const mintKeypair = Keypair.generate();
const mint = mintKeypair.publicKey; // mint account responsible for token mint/burn & token metadata
const transferFeeConfigAuthority = Keypair.generate(); // the authority is assigned cofig to
const withdrawWithheldAuthority = Keypair.generate(); // account that can withdraw the withheld token

// 2. setup token info
const TOKEN_DECIMALS = 9;
const FEE_BASIS_POINTS = 50; // 0.5%
const MAX_FEE = BigInt(5000); // Capped at 5K
const SCALING = BigInt(10_000); // per BPS

// 3. calculate storage lamports
const mintLen = getMintLen([ExtensionType.TransferFeeConfig]);
const lamports = await connection.getMinimumBalanceForRentExemption(mintLen);

// 4. create required instructions
const createAccountInstruction = SystemProgram.createAccount({
fromPubkey: payer.publicKey, // fee payer
newAccountPubkey: mint, // created account
space: mintLen, // allocated storage
lamports, // required rent lamports
programId: TOKEN_2022_PROGRAM_ID, // assigned programId
});
const initializeTransferFeeConfigInstruction =
createInitializeTransferFeeConfigInstruction(
mint,
transferFeeConfigAuthority.publicKey,
withdrawWithheldAuthority.publicKey,
FEE_BASIS_POINTS,
MAX_FEE,
TOKEN_2022_PROGRAM_ID,
);
const initializeMintInstruction = createInitializeMintInstruction(
mint,
TOKEN_DECIMALS,
mintAuthority.publicKey,
mintAuthority.publicKey,
TOKEN_2022_PROGRAM_ID,
);

// 5. batch and sent Tx
const tx = new Transaction().add(
createAccountInstruction,
initializeTransferFeeConfigInstruction,
initializeMintInstruction,
);
const txSig = await sendAndConfirmTransaction(
connection,
tx,
[payer, mintKeypair],
undefined,
);
console.log("🚀 MintAccointSig:", txSig);

// 完成後將會看類似如下的資訊​

// 🚀 Payer: Du9vC64s1ZJRY1i7qfA1CWvt6hWMwEeguebifqsjztcC
// 🚀 account balance: 978490640
// 🚀 MintAccointSig: 3P2Vs3TQ5nNG2CDjGKkFg7c5i1JoiBUYTk4ouvP5UoxNEMuQALQUuEhNervVBXSxsmPKuuv8QddCMCf85rFKF6TX

成功後可以,可以前往 solana explorer 輸入交易的簽名,查看交易的細節與情況。

可以看到交易按照順序顯示了我們剛打包好的三筆指令,同時第二筆設定 transfer fee Config 這邊顯示了我們剛剛設定的 5% 手續費以及最高手續費5000

initializ mint - Sol explorer

initializ mint - Sol explorer


(三)執行轉帳並收取手續費

成功創立 Mint Account 之後,我們將可以透過這個 Mint account 鑄造代幣,進行相關的代幣轉帳。

  1. 創立 owner 帳號(這個帳號將會持有兩個不同代幣帳號,作為轉帳用途)
  2. 鑄造代幣到一個 Token Account,作為轉帳帳戶
  3. 建立另一個 Token Account 作為收款帳戶
  4. 發起轉帳交易,同時額外計算被徵收的手續費(轉帳金額設定為 1,000,000,並酌收 5000 手續費)
...


// 1. create account to own 2 different token accounts
const owner = Keypair.generate();
const sourceAccount = await createAccount(
connection,
payer,
mint,
owner.publicKey,
undefined,
undefined,
TOKEN_2022_PROGRAM_ID,
);

// 2. mint tokens to source token account
const mintAmount = BigInt(10 ** 9);
await mintTo( // topup source Account
connection,
payer,
mint,
sourceAccount,
mintAuthority,
mintAmount,
[],
undefined,
TOKEN_2022_PROGRAM_ID,
);

// 3. create recipient token account
const recipient = Keypair.generate();
const recipientAccount = await createAccount(
connection,
payer,
mint,
owner.publicKey,
recipient,
undefined,
TOKEN_2022_PROGRAM_ID,
);

// 4. transfer and calculate the required fee amt
const transferAmount = BigInt(10 ** 6);
const feeAmount = (transferAmount * BigInt(FEE_BASIS_POINTS)) / SCALING;// calculate the charged fee when we execture transfer tx; otherwise the tx would fail
const transferSig = await transferCheckedWithFee(
connection,
payer,
sourceAccount,
mint,
recipientAccount,
owner,
transferAmount,
TOKEN_DECIMALS,
feeAmount,
[],
undefined,
TOKEN_2022_PROGRAM_ID,
);

console.log("🚀 TransferSig:", transferSig);

// 完成後將會看類似如下的資訊​

// 🚀 Payer: Du9vC64s1ZJRY1i7qfA1CWvt6hWMwEeguebifqsjztcC
// 🚀 account balance: 978490640
// 🚀 MintAccointSig: Jtc2hMbqymcZySmpvuqCtgNyZ5cdBKnffMAXScJ64AJQ2KjMydA7tyZQ1hty9rr5zUNPdDPykaLmSn2F1xBNnZg
// 🚀 TransferSig: NkQpF5KMjNpN7yQPbbGAaXTXxvcPRrbdf4hCmjae7tC65LET7nrTNkocv2AdqyXqpcqqP9HRKJCqy6cwDCqDqM2

同樣前往 solana explorer 查看交易的細節與情況。

我們可以看到轉帳成功的交易以及被酌收的手續費。

轉帳金額為 1,000,000 以及徵收的 5% 手續費 1,000,000 * 5% = 5000。

destination account

destination account


transfer tx - Sol explorer

transfer tx - Sol explorer


(四)提領手續費

在每一筆轉帳交易後都會存有額外的手續費 Withheld Amount 存在獨立的 token account 裡。假使要提領出來的話,我們會需要把每個token account 的資訊撈出來,確認是否有閒置的手續費尚未領取。


  1. 找出所有在Mint account 底下的 token account
  2. 根據我們的邏輯去撈出指定的帳戶(我們這邊撈出尚未被領取的手續費的帳號 withheldAmount > 0 )
  3. 送出交易
...

// 1. find all token accounts under Mint account
const allAccounts = await connection.getProgramAccounts(TOKEN_2022_PROGRAM_ID, {
commitment: "confirmed",
filters: [
{
memcmp: {
offset: 0,
bytes: mint.toString(),
},
},
],
});

// 2. filter out the accounts with withheld tokens
const accounsWithWithheldToken = allAccounts
.filter((acc) => {
const data = unpackAccount(acc.pubkey, acc.account, TOKEN_2022_PROGRAM_ID);
const feeAmt = getTransferFeeAmount(data);

return feeAmt && feeAmt.withheldAmount > 0;
})
.map((acc) => acc.pubkey);

// 3. sedn withdraw tx
const withdrawSig = await withdrawWithheldTokensFromAccounts(
connection,
payer,
mint,
recipientAccount,
withdrawWithheldAuthority,
[],
accounsWithWithheldToken,
undefined,
TOKEN_2022_PROGRAM_ID,
);

console.log("🚀 WithdrawSig:", withdrawSig);

// 完成後將會看類似如下的資訊​

// 🚀 Payer: Du9vC64s1ZJRY1i7qfA1CWvt6hWMwEeguebifqsjztcC
// 🚀 account balance: 978490640
// 🚀 MintAccointSig: rZUTtGkwRKieJB3bX8Br6MpgVs1GR8W6jqed1qbGeJcPJYaBtkwXCUzKAKE9nE8UE158FBr89gdyDe7tGRajkTw
// 🚀 TransferSig: 3Bv5s6yzmmfcgLggd6Cjo2myX9ZM4CpLUHfS9VkcumkfPVMvHjxJsL932c9LXeyG1cMy2Z9PrancqHyuhZwxfirA
// 🚀 TransferSig: 3Kwu5TEURuCRiKH4bDjVyHVwhyML9VKWdJ5biG3EaBh7srUuZEE36Tww6SJowz8PUDJkttNsDQNdkseoTbRVKDwJ

solana explorer 確認交易是否成功,可以看見我們確實提領出了 5000 token

withdraw tx

withdraw tx


以上便是這次的 Transfer Fee 手把手教學,可以發現 Transfer Fee 這個擴充功能並沒有讓前端額外增加許多負擔,很多的功能以及函式呼叫基本上都已經打包好,只需要計算手續費以及額外輸入 Account 進行交易即可,十分方便 🚀


Token Extension的詳細介紹請參考上篇


1會員
7內容數
Rita is awesome 🐰🐰🐰
留言0
查看全部
發表第一個留言支持創作者!
Web 3.0 BAO DAO 的其他內容
今年一月正式推出的 Solana 上的新標準 Token Extension,重塑了之前 Solana 所使用的 token 協議,替 Solana的鏈上資產解放更多潛力。資產之間的交互將變得更靈活,除了讓帳戶之間的轉帳更有保障之外,也在 Defi 未來的結構性商品上產生了更多的想像空間。
什麼是 PayPal PYUSD? 作為 Web2 網路支付的佼佼者,PayPal 於 2023 年與穩定發行商 Paxos 合作推出了穩定幣—PYUSD,試圖將其觸角伸入虛擬貨幣,透過虛擬貨幣驗證用戶餘額、即時結算等天生優勢,開創更多可能的應用場景及更傑出的用戶體驗。
如今,PYUSD 於全球第三大、2024 年最受歡迎的區塊鏈生態 Solana 上線。PYUSD 作為穩定幣有哪些優勢?未來應用場景有哪些想像?
Solana 如何驅動 DID 重塑鏈上鏈下身份信任? Solana 便宜且高效率的特性,滿足了 DID 鏈上驗證的可行性,並提供了 ZK 證明絕佳的去處 一旦我們將數據自主權完全回歸用戶本身,幾乎所有的現今網路世界驗證問題自然迎刃而解了。例如實體身分證的需要以及跨平台的身份資格確認與數據共享。
現今是數位身分正面臨什麼問題? 在現今的網路世界裡,大部分的個人數據都由第三方控制 ,這毫無疑問是錯的。
Blink,是 Solana 所開發的一種鏈上操作轉化為前端頁面的創新技術。這個功能可以將交易、投票等操作轉換成可分享的連結或二維碼,讓用戶可以直接在社交媒體上完成鏈上操作。
今年一月正式推出的 Solana 上的新標準 Token Extension,重塑了之前 Solana 所使用的 token 協議,替 Solana的鏈上資產解放更多潛力。資產之間的交互將變得更靈活,除了讓帳戶之間的轉帳更有保障之外,也在 Defi 未來的結構性商品上產生了更多的想像空間。
什麼是 PayPal PYUSD? 作為 Web2 網路支付的佼佼者,PayPal 於 2023 年與穩定發行商 Paxos 合作推出了穩定幣—PYUSD,試圖將其觸角伸入虛擬貨幣,透過虛擬貨幣驗證用戶餘額、即時結算等天生優勢,開創更多可能的應用場景及更傑出的用戶體驗。
如今,PYUSD 於全球第三大、2024 年最受歡迎的區塊鏈生態 Solana 上線。PYUSD 作為穩定幣有哪些優勢?未來應用場景有哪些想像?
Solana 如何驅動 DID 重塑鏈上鏈下身份信任? Solana 便宜且高效率的特性,滿足了 DID 鏈上驗證的可行性,並提供了 ZK 證明絕佳的去處 一旦我們將數據自主權完全回歸用戶本身,幾乎所有的現今網路世界驗證問題自然迎刃而解了。例如實體身分證的需要以及跨平台的身份資格確認與數據共享。
現今是數位身分正面臨什麼問題? 在現今的網路世界裡,大部分的個人數據都由第三方控制 ,這毫無疑問是錯的。
Blink,是 Solana 所開發的一種鏈上操作轉化為前端頁面的創新技術。這個功能可以將交易、投票等操作轉換成可分享的連結或二維碼,讓用戶可以直接在社交媒體上完成鏈上操作。
你可能也想看
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
Dynamic Metadata NFTs 是區塊鏈技術中的一大創新,特別是在遊戲領域,能提供更大的靈活性
你有聽過Solana上新推出的超強功能 「Token Extension」嗎?有了Token Extension,工程師能夠更快速的在Solana上建立專案,並且大幅增強了各個專案之間融合的便利性。如果你還不知道什麼是Token Extension,這篇文章你必須看完!
Token Extension Standard 是 Solana 區塊鏈上的一個代幣標準, 基於原始的 SPL(Solana Program Library)代幣標準進行構建。 具有增強的安全性和功能、改進的代幣處理能力, 如多重簽名和時間鎖定、設計 用於支持更複雜的代幣操作和使用案例
Thumbnail
前言 本篇要用 Token-2022 和 solana cli 來鑄造一個新的代幣叫做TYC。 如前篇所述,Token-2022 與 Spl Token 是不同的 Program,所以在呼叫的時候要特別註明以示明區別。 Token-2022 Program ID 地址: TokenzQdBNb
Thumbnail
公链Solana于今(15)晨突破185美元、且生态的DEX交易量自去年12月起,已连续四个月超越以太坊,位于各大公链榜首,更多详细资讯请看下面正文 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码: R851UX3N 老牌公
Thumbnail
现在USDT代币已经被大多数大型交易所采用,能够作为主要的交易对,很多投资者想要知道USDT转账要手续费吗?下面就让小编为大家带来USDT转账手续费明细一览 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码: R851UX3N
Thumbnail
前兩篇講了SPL Token與Account Model,現在要正式介紹token extension。 Token Extension Program(以下簡稱TEP) 原名 Token 2022,是一個基於原本Token Prgram(以下簡稱TP)的擴充版本。TEP被部署到的地
Thumbnail
从12月初开始,Meme币、Jito空投和SOL自身不断上涨的价格推动了Solana区块链上去中心化金融(DeFi)活动的激增,更多详细资讯请看下面正文 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码: R851UX3N J
,發揮創意「Token Extension Standard | 代幣擴充標準」這個主題,聚焦於 Solana 區塊鏈上代幣功能的擴展與創新。這是一個極具潛力的領域,有許多值得深入探討的方向。潛在的寫作方向以下是一些你可以深入探討的方向,希望能激發你的寫作靈感: 1. NFT 的多樣化應用與標
Thumbnail
1.加權指數與櫃買指數 週五的加權指數在非農就業數據開出來後,雖稍微低於預期,但指數仍向上噴出,在美股開盤後於21500形成一個爆量假突破後急轉直下,就一路收至最低。 台股方面走勢需觀察週一在斷頭潮出現後,週二或週三開始有無買單進場支撐,在沒有明確的反轉訊號形成前,小夥伴盡量不要貿然抄底,或是追空
Thumbnail
近期的「貼文發佈流程 & 版型大更新」功能大家使用了嗎? 新版式整體視覺上「更加凸顯圖片」,為了搭配這次的更新,我們推出首次貼文策展 ❤️ 使用貼文功能並完成這次的指定任務,還有機會獲得富士即可拍,讓你的美好回憶都可以用即可拍珍藏!
Thumbnail
Dynamic Metadata NFTs 是區塊鏈技術中的一大創新,特別是在遊戲領域,能提供更大的靈活性
你有聽過Solana上新推出的超強功能 「Token Extension」嗎?有了Token Extension,工程師能夠更快速的在Solana上建立專案,並且大幅增強了各個專案之間融合的便利性。如果你還不知道什麼是Token Extension,這篇文章你必須看完!
Token Extension Standard 是 Solana 區塊鏈上的一個代幣標準, 基於原始的 SPL(Solana Program Library)代幣標準進行構建。 具有增強的安全性和功能、改進的代幣處理能力, 如多重簽名和時間鎖定、設計 用於支持更複雜的代幣操作和使用案例
Thumbnail
前言 本篇要用 Token-2022 和 solana cli 來鑄造一個新的代幣叫做TYC。 如前篇所述,Token-2022 與 Spl Token 是不同的 Program,所以在呼叫的時候要特別註明以示明區別。 Token-2022 Program ID 地址: TokenzQdBNb
Thumbnail
公链Solana于今(15)晨突破185美元、且生态的DEX交易量自去年12月起,已连续四个月超越以太坊,位于各大公链榜首,更多详细资讯请看下面正文 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码: R851UX3N 老牌公
Thumbnail
现在USDT代币已经被大多数大型交易所采用,能够作为主要的交易对,很多投资者想要知道USDT转账要手续费吗?下面就让小编为大家带来USDT转账手续费明细一览 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码: R851UX3N
Thumbnail
前兩篇講了SPL Token與Account Model,現在要正式介紹token extension。 Token Extension Program(以下簡稱TEP) 原名 Token 2022,是一個基於原本Token Prgram(以下簡稱TP)的擴充版本。TEP被部署到的地
Thumbnail
从12月初开始,Meme币、Jito空投和SOL自身不断上涨的价格推动了Solana区块链上去中心化金融(DeFi)活动的激增,更多详细资讯请看下面正文 🚀 币安 - 全球最大加密货币交易所 💥 独家优惠 💥 💰 注册即享 20% 手续费返佣 🔑 专属邀请码: R851UX3N J
,發揮創意「Token Extension Standard | 代幣擴充標準」這個主題,聚焦於 Solana 區塊鏈上代幣功能的擴展與創新。這是一個極具潛力的領域,有許多值得深入探討的方向。潛在的寫作方向以下是一些你可以深入探討的方向,希望能激發你的寫作靈感: 1. NFT 的多樣化應用與標