如何提升Solana交易性能

  • QuickNode
  • 发布于 2024-04-02 14:50
  • 阅读 17

文章介绍了如何通过优先费用和计算单元优化来提高Solana区块链上交易被确认的可能性,并提供了具体的代码示例和工具使用指南。

概述

最近(2024年第一季度),对Solana区块空间的需求增加,导致网络流量增加和交易减少。这主要是因为对Solana的优先费用系统和交易调度的压力测试(计划在2024年4月进行的升级预计将解决这些问题)。尽管面临这些挑战,网络仍然在不断产生区块并处理交易。不过,仍然可以在自己的应用程序中采用一些工具来提高性能,并增加交易被纳入区块的可能性。在本指南中,我们将讨论两种可以考虑在交易组装中使用的方法,以提高交易在链上结算的可能性:

  • 实现优先费用
  • 优化计算单位

让我们开始吧!

在跳入指南之前,如果你更喜欢视频演示?跟随Sahil一起学习如何使用优先费用和QuickNode SDK优化你的交易。

订阅我们的YouTube频道以获取更多视频! 订阅

优先费用

Solana的费用优先系统允许你在交易基础费用上设置额外费用,这会使你的交易在领导者的队列中具有更高的优先级。通过为优先状态出价更多,你的交易更有可能被网络快速确认。更高的优先费用不能保证你的交易被纳入区块,但它确实使交易在同一线程中被处理的其他交易中获得优先权。如今,大多数交易都利用了优先费用,因此忽略它们可能会导致交易被丢弃。

我们有一份指南, 如何在Solana上使用优先费用。现在,我们将重点讨论如何为你的业务需求确定适当的优先费用水平。

QuickNode提供 优先费用API,它将获取整个网络或特定程序账户在最近(最多)100个区块中支付的优先费用。方法 qn_estimatePriorityFees 以5%的百分位数和方便的范围(低、中、高、极端和推荐)返回优先费用。以下是如何在你的TypeScript应用程序中获取最新费用的示例:

import { Transaction, ComputeBudgetProgram } from "@solana/web3.js";
import { RequestPayload, ResponseData, EstimatePriorityFeesParams } from "./types";

async function fetchEstimatePriorityFees({
    last_n_blocks,
    account,
    api_version,
    endpoint
}: EstimatePriorityFeesParams): Promise<ResponseData> {
    const params: any = {};
    if (last_n_blocks !== undefined) {
        params.last_n_blocks = last_n_blocks;
    }
    if (account !== undefined) {
        params.account = account;
    }
    if (api_version !== undefined) {
        params.api_version = api_version;
    }

    const payload: RequestPayload = {
        method: 'qn_estimatePriorityFees',
        params,
        id: 1,
        jsonrpc: '2.0',
    };

    const response = await fetch(endpoint, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
    });

    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data: ResponseData = await response.json();
    return data;
}

你可以通过在我们的 示例库 中引用来将类型添加到你的项目。

响应示例:

{
    "jsonrpc": "2.0",
    "result": {
        "context": {
            "slot": 254387670
        },
        "per_compute_unit": {
            "extreme": 1686993,
            "high": 260140,
            "low": 10714,
            "medium": 50000,
            "percentiles": {
                "5": 100,
                "10": 827,
                "15": 2000,
                // ...
                "90": 510498,
                "95": 1686993,
                "100": 20000000000,
            }
        },
        "per_transaction": {
            "extreme": 4290114,
            "high": 500000,
            "low": 50000,
            "medium": 149999,
            "percentiles": {
                "5": 700,
                "10": 2000,
                "15": 9868,
                // ...
                "90": 1250000,
                "95": 4290114,
                "100": 20000000000,
            }
        },
        "recommended": 400251
    },
    "id": 1
}

你现在可以选择适合你业务需求的优先费水平。现在让我们看看计算单位优化,然后我们将讨论如何在交易组装中使用这两种方法。

计算单位优化

每个在Solana上的交易都使用计算单位(CU)进行处理。交易越复杂,消耗的计算单位就越多。网络对单个区块中可以处理的计算单位数量有限制。如果你的交易超过此限制,它将被丢弃。

截至2024年3月,以下是现行限制/默认值:

  • 每个区块最大计算:4800万CU(在竞争期间,此限制通常会达到)
  • 每个账户每个区块最大计算:1200万CU
  • 每个交易最大计算:140万CU
  • 交易默认计算:20万CU
  • 每个交易费用:每个签名5000 lamports(可通过 getFeeForMessage RPC方法获取)
  • 每个CU的增量成本:0(未来可能会改变)

由于没有收取计算单位费用的历史,优化发送到网络的交易的动机或需求很少。这意味着许多应用程序使用默认的每个交易20万CU或最大值(以避免交易错误)。这在高网络流量时期不是理想选择,因为这可能导致交易被丢弃。

幸运的是,你可以在将交易发送到集群之前对其进行模拟,以确定它消耗的计算单位。这样,你就可以用尽可能少的计算单位将交易发送到集群,提高交易被纳入区块的可能性。

要计算你的交易的计算单位,请使用Solana Web3.js库中的 simulateTransaction 方法。以下是如何在你的TypeScript应用程序中使用此方法的示例:

async getSimulationUnits(
    connection: Connection,
    instructions: TransactionInstruction[],
    payer: PublicKey
): Promise<number | undefined> {

    const testInstructions = [\
        ComputeBudgetProgram.setComputeUnitLimit({ units: 1_400_000 }),\
        ...instructions,\
    ];

    const testVersionedTxn = new VersionedTransaction(
        new TransactionMessage({
            instructions: testInstructions,
            payerKey: payer,
            recentBlockhash: PublicKey.default.toString(),
        }).compileToV0Message()
    );

    const simulation = await connection.simulateTransaction(testVersionedTxn, {
        replaceRecentBlockhash: true,
        sigVerify: false,
    });

    if (simulation.value.err) {
        return undefined;
    }

    return simulation.value.unitsConsumed;
}

关于我们功能的一几点说明:

  • 确保在你的测试指令中包含一个 setComputeUnitLimit 指令。因为我们的交易需要该指令来更新计算单位限制。你可以在模拟时使用最大值,因为我们只关注消耗的计算单位数量。
  • 如果你使用优先费用,请确保在你的 instructions 数组中包含优先费用指令。我们将在下面的示例中做到这一点。

现在,我们有了一种方法来计算我们的交易将消耗的计算单位数量。让我们利用这一点,结合我们的 fetchEstimatePriorityFees 方法,创建一个交易组装,它将考虑最近的网络费用和我们的交易将消耗的计算单位数量。

优化交易组装

现在我们有了获取近期优先费用和计算我们的交易将消耗的计算单位数量的工具,我们可以利用这些工具创建一个交易组装,增加我们的交易被纳入区块的可能性。

以下是如何在你的TypeScript应用程序中利用这些工具的示例:

import { Connection, Keypair, Transaction, ComputeBudgetProgram } from "@solana/web3.js";
import { fetchEstimatePriorityFees, getSimulationUnits } from "./helpers"; // 更新为你方法的路径

const endpoint = YOUR_QUICKNODE_ENDPOINT; // 替换为你的QuickNode端点
const keyPair = Keypair.generate(); // 从秘密钥派生你的密钥对

async function main(){
    // 1. 建立与Solana集群的连接
    const connection = new Connection(endpoint);

    // 2. 创建你的交易
    const transaction = new Transaction();
    // ... 向交易中添加指令

    // 3. 获取近期的优先费用
    const { result } = await fetchEstimatePriorityFees({ endpoint });
    const priorityFee = result.recommended; // 根据你的业务要求替换为你的优先费用水平,例如 result.per_compute_unit['high']

    // 4. 创建一个优先费用指令并添加到交易中
    const priorityFeeInstruction = ComputeBudgetProgram.setComputeUnitPrice({
        microLamports: priorityFee,
    });
    transaction.add(priorityFeeInstruction);

    // 5. 模拟交易并向交易中添加计算单位限制指令
    let [units, recentBlockhash] =
        await Promise.all([\
            getSimulationUnits(\
                connection,\
                transaction.instructions,\
                keyPair.publicKey\
            ),\
            connection.getLatestBlockhash(),\
        ]);
    if (units) {
        units = Math.ceil(units * 1.05); // 容错率
        transaction.add(ComputeBudgetProgram.setComputeUnitLimit({ units }));
    }

    // 6. 签名并发送交易
    transaction.feePayer = keyPair.publicKey;
    transaction.recentBlockhash = recentBlockhash.blockhash;
    transaction.sign(keyPair);

    const hash = await connection.sendRawTransaction(
        transaction.serialize(),
        { skipPreflight: true, maxRetries: 0 }
    );

    return hash;
}

让我们分析一下示例中的步骤:

  1. 我们建立与Solana集群的连接。
  2. 我们创建交易。这是你将向交易添加指令的地方。
  3. 我们使用 fetchEstimatePriorityFees 方法获取近期的优先费用。
  4. 我们创建优先费用指令并将其添加到交易中。你可以根据业务需求自定义你的优先费用水平。
  5. 我们模拟交易并将计算单位限制指令添加到交易中。我们使用 getSimulationUnits 方法来计算我们的交易将消耗的计算单位数量。我们还为我们的交易获取了一个最近的区块哈希。
  6. 我们将交易签名并发送到Solana集群。

就这样,你现在拥有一个针对优先费用和计算单位优化的交易。这将增加你的交易被纳入区块的可能性!随意修改这些功能以满足你的需求!

QuickNode SDK

如果你想简化这个过程,可以使用 QuickNode SDK 来创建和发送优化交易!注意:你将需要 Solana优先费用附加组件 来使用SDK中的相关方法。

要使用SDK,你需要在项目中安装它:

npm i @quicknode/sdk # 或者 yarn add @quicknode/sdk

SDK中有三个相关方法可用于创建和发送优化交易:

  • sendSmartTransaction - 此方法会创建并发送一笔具有优先费用和优化计算单位的交易,以及给定的密钥对。
  • prepareSmartTransaction - 此方法将准备一笔具有优先费用和优化计算单位的交易。
  • fetchEstimatePriorityFees - 此方法将使用 qn_estimatePriorityFees 附加方法获取最近的优先费用。

以下是如何使用SDK向Solana集群发送“智能”交易的示例:

import { solanaWeb3, Solana } from "@quicknode/sdk";
const { Transaction, SystemProgram, Keypair, PublicKey } = solanaWeb3;

const mainSecretKey = Uint8Array.from([\
    // 替换为你的秘密钥\
]);
const sender = Keypair.fromSecretKey(mainSecretKey);
const receiver = new PublicKey("YOUR_RECEIVER_ADDRESS");
const senderPublicKey = sender.publicKey;

const endpoint = new Solana({
  endpointUrl:
    "https://some-cool-name.solana-mainnet.quiknode.pro/redacted",
});

const transaction = new Transaction();

// 为每个接收者添加指令
transaction.add(
  SystemProgram.transfer({
    fromPubkey: senderPublicKey,
    toPubkey: receiver,
    lamports: 10,
  })
);

(async () => {
  // 必须将终端节点添加到优先费用API才能做到这一点
  const signature = await endpoint.sendSmartTransaction({
    transaction,
    keyPair: sender,
    feeLevel: "recommended"
  });
  console.log(signature);
})().catch(console.error);

在这个例子中,我们使用 sendSmartTransaction 方法创建并发送一笔具有优先费用和优化计算单位的交易。我们还使用 SystemProgram.transfer 指令从发送者转移lamports到接收者。你可以根据业务需求自定义 feeLevel。就是这样!

开始使用QuickNode

通过你的QuickNode端点连接到Solana集群

要在Solana上构建,你需要一个API端点来与网络连接。你可以使用公共节点或自行部署和管理基础设施;不过,如果你希望8倍的响应速度,你可以把繁重的工作交给我们。

看看为什么超过50%的Solana项目选择了QuickNode,并在这里注册一个免费帐户。我们将会使用一个SolanaMainnet端点。

复制HTTP提供程序链接:

总结

在Solana 1.18升级推出之前,完成交易可能会更具挑战性。然而,通过实现优先费用和优化交易的计算单位,你可以增加交易被纳入区块的可能性。

查看 QuickNode市场 以集成我们的 Solana优先费用附加组件 并探索其他工具,以改善你的业务运营。

如果你有想要分享的问题或者想法,请在 DiscordTwitter 上告诉我们!

我们 ❤️ 反馈!

让我们知道 如果你有任何反馈或新主题请求。我们期待你的来信。

资源

  • 原文链接: quicknode.com/guides/sol...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。