简介
@solana/web3.js 差异和适配器
@solana/web3.js 库目前在 Solana 生态系统中广泛使用,并为 Publickeys、Transactions、Instructions 等定义了自己的类型。
在创建 Umi 时,我们希望摆脱 @solana/web3.js 中定义的基于类的类型。不幸的是,这意味着虽然具有相同或相似的导入名称,但 @solana/web3.js 的所有类型并不都与 Umi 提供的类型兼容,反之亦然。
为了解决这个问题,Umi 提供了一组适配器,允许将类型与其 Web3.js 对应物相互解析,它们可以在 @metaplex-foundation/umi-web3js-adapters 包中找到。
必需的包和导入
umi-web3js-adapters 包包含在 Umi 和 Web3.js 类型之间转换所需的所有辅助方法。
虽然在安装 @metaplex-foundation/umi 包时已经包含了它,但您也可以使用以下命令单独安装:
npm i @metaplex-foundation/umi-web3js-adapters
以下是您可以访问的导入:
import {
// 密钥对
fromWeb3JsKeypair, toWeb3JsKeypair,
// 公钥
fromWeb3JsPublicKey, toWeb3JsPublicKey,
// 指令
fromWeb3JsInstruction, toWeb3JsInstruction,
// 旧版交易
fromWeb3JsLegacyTransaction, toWeb3JsLegacyTransaction,
// 版本化交易
fromWeb3JsTransaction, toWeb3JsTransaction,
// 消息
fromWeb3JsMessage, toWeb3JsMessage, toWeb3JsMessageFromInput
} from '@metaplex-foundation/umi-web3js-adapters';
公钥
生成公钥乍一看可能很相似,但包之间存在一些细微差异。Web3Js 使用大写 P 并需要 new,而 Umi 版本使用小写 p。
Umi
import { publicKey } from '@metaplex-foundation/umi';
// 生成新的 Umi 公钥
const umiPublicKey = publicKey("11111111111111111111111111111111");
Web3Js
import { PublicKey } from '@solana/web3.js';
// 生成新的 Web3Js 公钥
const web3jsPublickey = new PublicKey("1111111111111111111111111111111111111111");
接下来,让我们看看如何使用适配器。
从 Web3Js 到 Umi
import { PublicKey } from '@solana/web3.js';
import { fromWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的公钥
const web3jsPublickey = new PublicKey("1111111111111111111111111111111111111111");
// 使用 UmiWeb3jsAdapters 包进行转换
const umiPublicKey = fromWeb3JsPublicKey(web3jsPublickey);
从 Umi 到 Web3Js
import { publicKey } from '@metaplex-foundation/umi';
import { toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的公钥
const umiPublicKey = publicKey("11111111111111111111111111111111");
// 使用 UmiWeb3jsAdapters 包进行转换
const web3jsPublickey = toWeb3JsPublicKey(umiPublicKey);
密钥对
生成密钥对是 Web3Js 和 Umi 差异增加的地方。使用 Web3Js,您可以简单地使用 Keypair.generate(),但是在 Umi 中,您首先需要创建一个 Umi 实例,您将在大多数 Umi 和 Metaplex 相关操作中使用它。
Umi
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { generateSigner, createSignerFromKeypair } from '@metaplex-foundation/umi'
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com')
// 生成新的 Umi 密钥对
const umiKeypair = generateSigner(umi)
// 或使用现有的
const umiKeypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(walletFile));
Web3Js
import { Keypair } from '@solana/web3.js';
// 生成新的 Web3Js 密钥对
const web3jsKeypair = Keypair.generate();
// 或使用现有的
const web3jsKeypair = Keypair.fromSecretKey(new Uint8Array(walletFile));
接下来,让我们看看如何使用适配器。
从 Umi 到 Web3Js
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { generateSigner } from '@metaplex-foundation/umi'
import { toWeb3JsKeypair } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com')
// 生成新的密钥对
const umiKeypair = generateSigner(umi)
// 使用 UmiWeb3jsAdapters 包进行转换
const web3jsKeypair = toWeb3JsKeypair(umiKeypair);
从 Web3Js 到 Umi
import { Keypair } from '@solana/web3.js';
import { fromWeb3JsKeypair } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的密钥对
const web3jsKeypair = Keypair.generate();
// 使用 UmiWeb3jsAdapters 包进行转换
const umiKeypair = fromWeb3JsKeypair(web3jsKeypair);
指令
创建指令时,与 Umi 的关键区别在于您必须首先创建一个 Umi 实例(与 Keypairs 一样)。此外,getInstructions() 返回指令数组而不是单个指令。
对于大多数用例,处理单个指令无论如何都不是必需的,因为这可以使用其他辅助函数和交易构建器简化。
Umi
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// 创建新指令(如 core nft 转移)
// get instructions 将给您一个指令数组
const umiInstructions = transferSol(umi, {...TransferParams}).getInstructions();
Web3Js
import { SystemProgram } from '@solana/web3.js';
// 创建新指令(如 lamport 转移)
const web3jsInstruction = SystemProgram.transfer({...TransferParams})
接下来,让我们看看如何使用适配器。
从 Umi 到 Web3Js
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
import { toWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// 创建新指令(如 core nft 转移)
const umiInstruction = transferSol(umi, {...TransferParams}).getInstructions();
// 使用 UmiWeb3jsAdapters 包进行转换
const web3jsInstruction = umiInstruction.map(toWeb3JsInstruction);
从 Web3Js 到 Umi
import { SystemProgram } from '@solana/web3.js';
import { fromWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com')
// 创建新指令(如 lamport 转移)
const web3jsInstruction = SystemProgram.transfer({...TransferParams})
// 使用 UmiWeb3jsAdapters 包进行转换
const umiInstruction = fromWeb3JsInstruction(web3jsInstruction);
交易
Solana 运行时支持两种交易版本:
- 旧版交易:较旧的交易格式,没有额外优势
- 0 / 版本化交易:添加了对地址查找表的支持
注意:如果您不熟悉版本化交易的概念,请在此处阅读更多信息
对于 umi 和 umi-web3js-adapters,我们添加了对两种交易类型的支持!
Umi
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// 创建新的 Umi 旧版交易
const umiTransaction = transferSol(umi, {...TransferParams}).useLegacyVersion();
// 创建新的 Umi 版本化交易
const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV0().build(umi)
Web3Js
import { Transaction, VersionedTransaction, TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
// 创建新的 Web3Js 旧版交易
const web3jsTransaction = new Transaction().add(SystemProgram.transfer({...TransferParams}));
// 创建新的 Web3Js 版本化交易
const instructions = [SystemProgram.transfer({...TransferParams})];
const connection = new Connection(clusterApiUrl("devnet"));
const blockhash = await connection.getLatestBlockhash().then(res => res.blockhash);
const messageV0 = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions,
}).compileToV0Message();
const web3jsVersionedTransaction = new VersionedTransaction(messageV0);
接下来,让我们看看如何使用适配器。
从 Umi 到 Web3Js
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
import { toWeb3JsLegacyTransaction, toWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// 创建新的旧版交易
const umiTransaction = transferSol(umi, {...TransferParams}).useLegacyVersion();
// 使用 UmiWeb3jsAdapters 包进行转换
const web3jsTransaction = toWeb3JsTransaction(umiTransaction);
/// 版本化交易 ///
// 创建新的版本化交易
const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV0().build(umi)
// 使用 UmiWeb3jsAdapters 包进行转换
const web3jsVersionedTransaction = toWeb3JsTransaction(umiVersionedTransaction);
从 Web3Js 到 Umi
import { Transaction, VersionedTransaction, TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
import { fromWeb3JsLegacyTransaction, fromWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters';
// 创建新的旧版交易
const web3jsTransaction = new Transaction().add(SystemProgram.transfer({...TransferParams}));
// 使用 UmiWeb3jsAdapters 包进行转换
const umiTransaction = fromWeb3JsLegacyTransaction(web3jsTransaction);
/// 版本化交易 ///
// 创建新的版本化交易
const web3jsVersionedTransaction = new VersionedTransaction(...messageV0Params);
// 使用 UmiWeb3jsAdapters 包进行转换
const umiVersionedTransaction = fromWeb3JsTransaction(web3jsVersionedTransaction);
消息
我们已经在版本化交易创建期间涵盖了创建消息。让我们再次回顾一下。
Umi
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transfer, mplCore } from '@metaplex-foundation/mpl-core'
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// 创建新的 Umi 消息
const blockhash = await umi.rpc.getLatestBlockhash()
const instructions = transfer(umi, {...TransferParams}).getInstructions()
const umiVersionedTransaction = umi.transactions.create({
version: 0,
payer: frontEndSigner.publicKey,
instructions,
blockhash: blockhash.blockhash,
});
const umiMessage = umiVersionedTransaction.message
Web3Js
import { TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
// 创建新的 Web3Js 消息
const connection = new Connection(clusterApiUrl("devnet"));
const minRent = await connection.getMinimumBalanceForRentExemption(0);
const blockhash = await connection.getLatestBlockhash().then(res => res.blockhash);
const instructions = [SystemProgram.transfer({...TransferParams})];
const Web3JsMessage = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions,
}).compileToV0Message();
接下来,让我们看看如何使用适配器。
从 Umi 到 Web3Js
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { toWeb3JMessage } from '@metaplex-foundation/umi-web3js-adapters';
// 生成新的 Umi 实例
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// 创建新的版本化交易
const umiMessage = umi.transactions.create({...createParams}).message;
// 使用 UmiWeb3jsAdapters 包进行转换
const web3jsMessage = toWeb3JMessage(umiMessage);
从 Web3Js 到 Umi
import { TransactionMessage } from '@solana/web3.js';
import { fromWeb3JMessage } from '@metaplex-foundation/umi-web3js-adapters';
// 创建新的版本化交易
const Web3JsMessage = new TransactionMessage({...createMessageParams}).compileToV0Message();
// 使用 UmiWeb3jsAdapters 包进行转换
const umiMessage = fromWeb3JMessage(Web3JsMessage);
