Web3 新手系列:現在升級 @solana/web3.js 2.x 開啟函數式編程

您所尋找的語言內容尚未提供。

Solana Web3.js 是一個功能非常豐富的 JavaScript 庫,在今年11月正式發布了 2.x 版本。相比 1.x,新版本變化比較大,這篇文章嘗試對其主要變化做一些概括。

目前由於 2.x 版本剛發布,使用量並不高,很多使用量很高的庫也沒有切換。不過我們可以先了解一下,為以後的遷移做好準備。

版本對比

不得不承認,舊版本使用起來其實更加簡單。首先,舊版實際上只有一個包:@solana/web3.js 所有內容都在它裏面。並且它基於類,封裝了大量常用的操作。例如 Connection 類,它帶有幾十種方法,基本將開發者所想要的功能涵蓋了。而且 Solana cookbook 中提供了大量的示例代碼,開發者總能從這裏找到自己需要的東西。

但是,這也造成了另一些問題:雖然開發者實際上使用到的功能,往往只占其中的很小一部分,但是最終整個代碼庫都會被下載到用戶的設備上。由於整個庫的代碼量很大,這可能會持續一小段時間。

反觀 2.x 版本,官方團隊將原有的代碼庫拆分為了幾個很小的模塊組成,例如 @solana/accounts、@solana/codecs、@solana/rpc、@solana/signers、@solana/transactions 等。並且放棄了基於類的實現,更多的采用單個函數,這在 JavaScript 代碼構建時的優化很有幫助,dapp 沒有使用到的代碼將會被刪除,實際上不會被下載到用戶設備上。據官方文檔的統計,使用新版的 dapp 基本都能得到 30% 的尺寸優化,如果只用到了很小一部分功能,那麽能得到更高的優化比例(https://solana-labs.github.io/solana-web3.js/#statistics)。

這就對 Solana 團隊的文檔水平帶來了考驗,如何讓開發者迅速找到需要的功能,將是一個重要的事項。不過目前看來,至少包名具有不錯的語義性,從名字上就能大概知道它們可以被用來做什麽。這應該能從一定程度上減少開發者遷移的難度。

當然,由於其剛發布不久,所以很多項目還沒有進行遷移。Solana Cookbook 上,2.x 版本的示例也比較少。並且由於新版本傾向於使用運行時內置功能(例如生成密鑰對),文檔中卻缺失對這裏的描述,導致有些地方讓開發者有些無所適從。

2.x 還有一個很重要的特點:零依賴。這一點可能對很多用戶來說並不重要,但是從今年 12 月初發生在 @solana/web3.js 1.95.5 和 1.95.6 版本上的供應鏈攻擊來看,更多的外部輸入和依賴會急速增加安全事件發生的可能。而隨著 2.x 版本的發布,Web3.js 的開發團隊決定應該更多的使用本機的功能,而取消外部依賴和 Polyfills 的引入。以後可能會有變化,但至少目前來說,2.x 版本消除了所有外部依賴。

重要變更點

連接

如上文所介紹的,1.x 有大量方法通過 Connection 來提供。不過其最主要的功能,還是用於通過配置 rpc 請求地址,創建一個請求發送器。然後通過它來發送各種請求。

在 2.x 中,則是通過更加函數式的方式來實現:

const rpc = createSolanaRpc(HTTPS);
const rpcSubscriptions = createSolanaRpcSubscriptions(WSS);

const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
  rpc,
  rpcSubscriptions,
});

以上代碼中,當我們調用sendAndConfirmTransaction來發送交易時,會自動發起 https 請求,並且建立一個 wss 連接,訂閱交易狀態,在交易被確認後返回交易hash。

密鑰對

公鑰和私鑰相關的地方也有很大變化。在 1.x 版本最常用的 Keypair 和 PublicKey 兩個類不存在了,被成一些函數替代。

例如可以使用await generateKeyPair()生成密鑰對,在之前則是直接通過Keypair.generate()生成一個密鑰對。

你可能註意到新的 generateKeyPair 返回了 Promise,而不是想之前那樣,可以直接返回需要的密鑰對。這是由於新的實現盡可能的利用了 JavaScript 的 Web Crypto API,使用了原生的 Ed25519 實現。Web Crypto API 的很多方法都是異步的。不過這一點變化倒是並非不能接受,在2024年即將結束的今天,JavaScript 開發者們早已將 Promise 看作非常熟悉的朋友了。

發送交易

1.x 的用戶應該很熟悉 Transaction和VersionedTransaction兩個類,最開始了解 Solana 時,它們之間的關系也曾讓我非常疑惑。

在 2.x 版本中,同樣不再有這兩個類。

舊版本中提供的 System Program 相關方法也不再繼續存在,所以SystemProgram類上的靜態方法都需要從另外的地方引入。

例如transfer指令,需要調用@solana-program/system中的getTransferSolInstruction函數。

由於不再提供 class,Web3.js 提供了函數式編程的能力中常用的 pipe 形式。下面通過pipe函數來實現原本 1.x 的轉賬功能:

const LAMPORTS_PER_SOL = BigInt(1_000_000_000);
const rpc = createSolanaRpc(`https://api.zan.top/node/v1/solana/devnet/${YOUR_ZAN_API_KEY}`);
const rpcSubscriptions = createSolanaRpcSubscriptions(`wss://api.zan.top/node/v1/solana/devnet/${YOUR_ZAN_API_KEY}`);

const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
  rpc,
  rpcSubscriptions,
});

const onTransfer = async () => {
  const keypair = await createKeyPairFromPrivateKeyBytes(YOUR_PRIV_KEY_BYTES);
  const signer = await createSignerFromKeyPair(theKeypair);

  const toAddress = address("4Nu34Lrv9Wv4fX1zA7xTNy8Z4bTKcB9oL8ZMbZV9CNUz");

  const { value: blockhashValue } = await rpc.getLatestBlockhash().send();

  const transactionMessage = pipe(
    createTransactionMessage({ version: 0 }),
    (tx) => setTransactionMessageFeePayer(signer.address, tx),
    (tx) => setTransactionMessageLifetimeUsingBlockhash(blockhashValue, tx),
    (tx) =>
      appendTransactionMessageInstruction(
        getTransferSolInstruction({
          source: signer,
          destination: toAddress,
          amount: lamports(LAMPORTS_PER_SOL / BigInt(10)),
        }),
        tx
      )
  );

  const signedTx = await signTransactionMessageWithSigners(
    transactionMessage
  );
  const signature = getSignatureFromTransaction(signedTx);
  console.log('transaction signature:', signature);

  await sendAndConfirmTransaction(signedTx, { commitment: "confirmed" });
};

能夠發現交易不再通過 Connection 來發起,而是通過我們定義的 RPC Provider,生成一個特有的函數,然後調用該函數來發起交易。相對 1.x 版本來說,代碼量有些增加,不過優點是可定製性更強了。

交易通過 HTTPS RPC 發起,然後通過訂閱 WSS RPC 來確認交易結果。可以感受到新的方式非常依賴 WSS,相信以後 WSS 的應用將會越加廣泛,這也確實對 RPC 供應商的服務穩定性提出了更高的要求。如果你正在尋找一個可靠的 WSS 節點供應商,ZAN Node 是一個不錯的選擇。作為 Solana 在亞太地區的領先服務商,我們致力於提供穩定、高效的連接性能。除了 Ethereum 和 Solana 等熱門鏈外,我們還支持超過 20 條主流鏈的 RPC 服務,以滿足不同場景的需求。

React

有趣的是,@solana/web3.js 項目中還包含了一個名為 @solana/react 的庫,提供了一些 React Hook,內置了諸如 signIn 等功能。

總結

@solana/web3.js 2.x 版本的發布,充分體現了 Solana 團隊對於不斷發展和改進的承諾。為開發人員提供一個高效、靈活、可定製的與 Solana 網絡進行交互的方式,並有助於推動該平臺的采用和發展。

關於 ZAN

ZAN 是螞蟻數科旗下 Web3 科技品牌,致力於 Web3 應用優化--降低成本、增強安全和提升效能,圍繞 Web3 應用全生命週期,提供可靠、穩定安全、客製化的產品和服務。依托 AntChain OpenLabs 的 TrustBase 開源開放技術體系,ZAN 擁有 Web3 領域獨特的優勢和創新能力,為 Web3 社群的區塊鏈應用開發、企業和開發者的 Web3 應用提供了全面的技術產品和服務,其中包括節點服務(ZAN Node Service)zk 加速(ZAN PowerZebra)身分驗證eKYC(ZAN Identity)以及智慧合約稽核(ZAN Smart Contract Review)等。

聯絡我們

WebsiteXDiscordTelegram