Skip to main content

Solana高级概念: 版本化交易

鱼雪

版本化交易是新的交易格式,允许在Solana运行时中添加功能,包括地址查找表。 虽然链上程序无需更改即可支持版本化交易的新功能(或保持向后兼容性), 但开发人员需要更新客户端代码,以防止由于不同交易版本导致的错误。

当前交易版本

Solana运行时支持两种交易版本

  • legacy - 较旧的交易格式,没有额外的好处
  • 0 - 添加了对地址查找表的支持

支持的最大交易版本

所有返回交易的RPC请求都应使用maxSupportedTransactionVersion选项指定应用程序支持的最高交易版本, 包括getBlockgetTransaction

如果返回的版本化交易高于设置的maxSupportedTransactionVersion, RPC请求将失败(例如,如果选择了legacy版本但返回了0版本的交易)。

warning

如果未设置maxSupportedTransactionVersion值,则RPC响应中只允许legacy交易。 因此,如果返回任何0版本交易,您的RPC请求将失败。

如何设置支持的最大版本

您可以使用@solana/web3.js库和直接发送到RPC端点的JSON格式请求来设置maxSupportedTransactionVersion

使用web3.js

使用@solana/web3.js库,您可以获取最近的区块或特定交易

// 连接到`devnet`集群并获取当前`slot`
const connection = new web3.Connection(web3.clusterApiUrl("devnet"));
const slot = await connection.getSlot();

// 获取最新的区块(允许v0交易)
const block = await connection.getBlock(slot, {
maxSupportedTransactionVersion: 0,
});

// 获取特定交易(允许v0交易)
const getTx = await connection.getTransaction(
"3jpoANiFeVGisWRY5UP648xRXs3iQasCHABPWRWnoEjeA93nc79WrnGgpgazjq4K9m8g2NJoyKoWBV1Kx5VmtwHQ",
{
maxSupportedTransactionVersion: 0,
},
);

向RPC发送JSON请求

使用标准的JSON格式POST请求,您可以在检索特定区块时设置maxSupportedTransactionVersion

curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d \
'{"jsonrpc": "2.0", "id":1, "method": "getBlock", "params": [430, {
"encoding":"json",
"maxSupportedTransactionVersion":0,
"transactionDetails":"full",
"rewards":false
}]}'

如何创建版本化交易

版本化交易的创建方式与旧方法类似,但在使用某些库时有些不同。

以下是使用@solana/web3.js库创建版本化交易的示例,用于在两个账户之间进行SOL转账。

注意事项

  • payer是一个有效的Keypair钱包,已经有SOL资金
  • toAccount是一个有效的Keypair

首先,导入web3.js库并创建到所需集群的连接(connection)。

然后定义我们将需要的最近区块哈希(blockhash)和最小租金(minRent):

const web3 = require("@solana/web3.js");

// 连接到集群并获取租金豁免状态的最低租金
const connection = new web3.Connection(web3.clusterApiUrl("devnet"));
let minRent = await connection.getMinimumBalanceForRentExemption(0);
let blockhash = await connection
.getLatestBlockhash()
.then(res => res.blockhash);

创建一个包含所有所需指令(instructions)的数组(array)。

在下面的示例中,我们创建一个简单的SOL转账指令:

// 创建一个包含所需指令的数组
const instructions = [
web3.SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: toAccount.publicKey,
lamports: minRent,
}),
];

接下来,使用所需的指令构建一个MessageV0格式的交易消息

// 创建v0兼容的消息
const messageV0 = new web3.TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions,
}).compileToV0Message();

然后,创建一个新的VersionedTransaction,传入我们的v0兼容消息:

const transaction = new web3.VersionedTransaction(messageV0);

// 使用所需的签名者签署交易
transaction.sign([payer]);

您可以通过以下方式签署交易

  • 将签名数组传递给VersionedTransaction方法,或
  • 调用transaction.sign()方法,传递所需签名者的数组
info

调用transaction.sign()方法后,所有先前的交易签名将被提供的签名者的新签名完全替换

在所有必要账户对您的 VersionedTransaction 进行签名之后, 您可以将其发送到集群并等待(await)响应:

// 发送我们的v0交易到集群
const txId = await connection.sendTransaction(transaction);
console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`);
note

legacy交易不同, 通过sendTransaction发送版本化交易不支持通过传递签名者数组作为第二个参数进行交易签名。 您需要在调用connection.sendTransaction()之前签署交易。

版本化交易总结

版本化交易是Solana的新交易格式, 提供了包括地址查找表在内的附加功能。 开发者需要更新客户端代码,以避免因不同交易版本导致的错误。

  1. 当前交易版本 Solana运行时支持两种交易版本:
  • legacy:旧的交易格式,没有额外的功能。
  • 0:新增了对地址查找表的支持。
  1. 设置最大支持的交易版本 在所有返回交易的RPC请求中,应使用maxSupportedTransactionVersion选项指定应用程序支持的最高交易版本。
  • 如果返回的交易版本高于设置的maxSupportedTransactionVersion,RPC请求将失败。
  • 如果未设置maxSupportedTransactionVersion值,则RPC响应中只允许legacy交易。
  1. 设置方法 通过@solana/web3.js库或直接向RPC端点发送JSON格式的请求来设置maxSupportedTransactionVersion