Web3新玩法:SolanaNonceAccount让你交易无忧想在Web3世界玩出新花样?Solana的交易速度快到飞起,但你有没有遇到过这样的烦恼:交易刚签名,转眼就因区块哈希过期失效?别急,SolanaNonceAccount来了!它就像一个“交易时间胶囊”,让你随时签名
想在 Web3 世界玩出新花样?Solana 的交易速度快到飞起,但你有没有遇到过这样的烦恼:交易刚签名,转眼就因区块哈希过期失效?别急,Solana Nonce Account 来了!它就像一个“交易时间胶囊”,让你随时签名、随时提交,再也不用担心时间限制。本文将带你揭开这个 Web3 新玩法的面纱,手把手教你如何用它让交易无忧,轻松迈入 Solana 开发前沿!
在 Solana 区块链中,Nonce Account 是一个隐藏的“交易神器”。Nonce Account(nonce 账户) 是一种特殊的账户类型,用于支持 Durable Nonce(持久化 nonce) 机制。它用一个持久化的 nonce 值替代短命的区块哈希,让你的交易签名可以“长寿”无忧,随时提交不失效。本文不仅深入讲解了 Nonce Account 的原理和特性,还通过代码实战演示了如何创建、签名和发送持久化交易。对比传统方式,你会发现它的妙处:离线签名、定时转账,统统不在话下。无论你是 Web3 新手还是 Solana 开发者,这篇指南都能让你快速上手,玩转交易新姿势!
Nonce Account 是 Solana 系统程序(System Program)拥有的一种账户,用于存储一个 nonce 值(一个唯一的标识符,通常是一个 32 字节的哈希值)。这个 nonce 值可以替代常规交易中的 recent blockhash(最近区块哈希),从而实现 持久化交易(Durable Transactions),也就是允许交易在签名后延迟提交而不失效。
存储内容:
Nonce 值: 一个唯一的哈希值,替代交易中的 recent blockhash。
Authority(授权者): 一个公钥,负责管理该 Nonce Account(例如推进 nonce 或提取资金)。
状态: 表示账户是否已初始化。
租免(Rent-Exempt):
prepareAccount
代码export function prepareAccount(params: any) {
const {
authorAddress,
nonceAccountAddress,
recentBlockhash,
minBalanceForRentExemption,
privs,
} = params;
const authorPrivateKey = privs?.find(
(ele: { address: any }) => ele.address === authorAddress
)?.key;
if (!authorPrivateKey) throw new Error("authorPrivateKey 为空");
const nonceAcctPrivateKey = privs?.find(
(ele: { address: any }) => ele.address === nonceAccountAddress
)?.key;
if (!nonceAcctPrivateKey) throw new Error("nonceAcctPrivateKey 为空");
const author = Keypair.fromSecretKey(
new Uint8Array(Buffer.from(authorPrivateKey, "hex"))
);
const nonceAccount = Keypair.fromSecretKey(
new Uint8Array(Buffer.from(nonceAcctPrivateKey, "hex"))
);
const tx = new Transaction();
tx.add(
SystemProgram.createAccount({
fromPubkey: author.publicKey,
newAccountPubkey: nonceAccount.publicKey,
lamports: minBalanceForRentExemption,
space: NONCE_ACCOUNT_LENGTH,
programId: SystemProgram.programId,
}),
SystemProgram.nonceInitialize({
noncePubkey: nonceAccount.publicKey,
authorizedPubkey: author.publicKey,
})
);
tx.recentBlockhash = recentBlockhash;
tx.sign(author, nonceAccount);
return tx.serialize().toString("base64");
}
{
"jsonrpc": "2.0",
"id": 1,
"method": "getLatestBlockhash",
"params": [
{
"commitment": "processed"
}
]
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"context": {
"apiVersion": "2.1.11",
"slot": 361716547
},
"value": {
"blockhash": "7kcpQ8Hfpi35gTKtmkVW5XBdYH5Zrw4e9Pg27YyCxkcP",
"lastValidBlockHeight": 349703424
}
}
}
test('prepareAccount test', async () => {
const params = {
authorAddress: from,
nonceAccountAddress: nonce_account_addr,
recentBlockhash: "7kcpQ8Hfpi35gTKtmkVW5XBdYH5Zrw4e9Pg27YyCxkcP",
minBalanceForRentExemption: 1647680,
privs: [
{
address: from,
key: fromPrivateKey
},
{
address: nonce_account_addr,
key: noncePrivateKey
}
]
}
let tx_msg = await prepareAccount(params)
console.log("prepareAccount-tx_msg===", tx_msg)
});
console.log
prepareAccount-tx_msg=== AovVQR0MBuqhv9g/Z13s7ZxLGWUJJT3Oo93lbpmuv9f/liETgjOJVoJyRGRnwp3lo+rb45SCPzcoubMn4we/mwNNRDoya6WDYE9FkcZOGZAgLHSJ8+e0+H5D8pDxHAEnHgDCqWPguVrIyTulfaDxplezPdql6xQHFT9ggyzc9EgPAgADBVDS9aJBo99CnaEp9zsUQTrBn951FTSzXyb0W7DUWub2xEp9ziCqAhF18Ho7eXUKwhKbLjja+jESCZydfVfC/UsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAan1RcZLFaO4IqEX3PSl4jPA1wxRbIas0TYBi6pQAAABqfVFxksXFEhjMlMPUrxf1ja7gibof1E49vZigAAAABkUphSZcxpdk94aUysDsPylqN3s1PWrP/RYWsLIxSGGAICAgABNAAAAABAJBkAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAwEDBCQGAAAAUNL1okGj30KdoSn3OxRBOsGf3nUVNLNfJvRbsNRa5vY=
{
"method": "sendTransaction",
"params": [
"AovVQR0MBuqhv9g/Z13s7ZxLGWUJJT3Oo93lbpmuv9f/liETgjOJVoJyRGRnwp3lo+rb45SCPzcoubMn4we/mwNNRDoya6WDYE9FkcZOGZAgLHSJ8+e0+H5D8pDxHAEnHgDCqWPguVrIyTulfaDxplezPdql6xQHFT9ggyzc9EgPAgADBVDS9aJBo99CnaEp9zsUQTrBn951FTSzXyb0W7DUWub2xEp9ziCqAhF18Ho7eXUKwhKbLjja+jESCZydfVfC/UsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAan1RcZLFaO4IqEX3PSl4jPA1wxRbIas0TYBi6pQAAABqfVFxksXFEhjMlMPUrxf1ja7gibof1E49v...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!