JavaScript 不可用。

我们检测到浏览器禁用了 JavaScript。请启用 JavaScript 或改用支持的浏览器来继续访问

Solana raydiumV4 swap 调用

作者:Anban Chu

发表日期:2024年12月06日

所属目录:Soalna 网络的应用开发

标签:
Solana 

需求

  1. 调用 raydiumV4 swap指令,其中 1% 币本位手续费
  2. 手续费可配置
  3. 内置白名单地址,可以指定 (地址-币本位手续费),用于VIP用户收取不同手续费率

演示Swap:https://github.com/chainstacklabs/raydium-sdk-swap-example-typescript

说明

在Solana中,程序之间的调用机制与以太坊的智能合约调用有些不同。在Solana中,每个程序都运行在独立的账户空间中,并通过“调用程序”机制进行交互。这种交互是通过invoke和invoke_signed指令来实现的。invoke和invoke_signed指令允许一个Solana程序调用另一个程序的功能。

Solana程序调用其他程序的基本步骤

  • 创建目标程序的账户和结构: 目标程序必须已经部署,并且在调用时可以通过指定该程序的公钥来进行访问。
  • 构造调用参数:调用目标程序时需要传递必要的参数(例如,交易数据、账户信息等),这些参数会通过账户传递给目标程序。
  • 使用 invoke 或 invoke_signed 指令: Solana提供了这两种指令来允许一个程序调用另一个程序。
    • invoke:普通程序调用。用于一般的程序调用,所有账户和签名都由调用者提供。
    • invoke_signed:这是签名调用,通常用于需要授权的情况,或者在程序调用时需要用到特定的签名。
      • 通常用于调用涉及多个权限或签名的操作。
  • 处理返回值: 调用其他程序后,目标程序会返回相应的结果,这些结果可以用来继续处理后续逻辑。

示例:如何调用另一个Solana程序

假设你有两个程序,Program A 和 Program B,并且你想在Program A中调用Program B的某个功能。

use solana_program::{
    account_info::AccountInfo,
    entrypoint::ProgramResult,
    pubkey::Pubkey,
    program::{invoke, invoke_signed},
    sysvar::rent::Rent,
    msg,
};

pub fn process_instruction(
    program_id: &Pubkey, 
    accounts: &[AccountInfo], 
    instruction_data: &[u8],
) -> ProgramResult {
    // 程序A的逻辑
    msg!("Calling Program B...");

    let program_b_id = Pubkey::new_from_array([/* Program B 的公钥 */]);

    // 构造调用 Program B 所需的参数
    let accounts_to_pass = &[
        // 你需要传递的账户信息
    ];

    // 使用 invoke 调用 Program B
    invoke(
        &solana_program::instruction::Instruction {
            program_id: program_b_id,
            accounts: accounts_to_pass.to_vec(),
            data: instruction_data.to_vec(),
        },
        accounts, // 传递调用账户
    )?;

    msg!("Program B called successfully!");

    Ok(())
}

关键点说明

  • invokeinvoke_signed 的核心作用是允许一个程序调用另一个程序,传递所需的账户信息和数据。
  • accounts 参数是传递给目标程序的账户信息,通常包含源账户、目标账户等。
  • instruction_data 是要传递给目标程序的自定义数据(例如,目标程序的某个函数的参数)。
  • program_b_id 是目标程序 Program B 的公钥。

如果目标程序需要授权特定账户或要求额外的签名,你应该使用 invoke_signed,并提供相关的签名数据。

invoke_signed(
    &instruction,
    accounts,
    &[&[b"signer", &[nonce]]], // 提供签名数据
)?;

注意事项

  • 程序调用时的账户验证: 在调用其他程序时,必须确保传递给目标程序的账户是有效的,并且程序能够正确验证这些账户的状态。
  • 目标程序的验证: 目标程序会根据传入的参数和账户来验证请求是否合法。如果目标程序期望特定的数据结构或账户状态,调用时需要严格遵守这些要求。

测试

相关地址:

内部逻辑

process_swap_base_out_with_user_account:RouteSwapBaseOutArgs { max_amount_in: 5170758, amount_out: 1000000 }

调用 raydium swap 方法

编写Solana程序,核心是调用Raydium的Swap方法,我们需要了解几个关键组件和概念。

Raydium 是一个在 Solana 网络上运行的去中心化交易所(DEX),它利用了 Solana 的高速交易特性,并且和 Serum 的订单簿系统集成。Raydium的 swap 方法实际上是在执行一个交易操作,在不同的市场池之间进行代币的交换。

实现目标

  • 通过 Solana 程序调用 Raydium 的 Swap 方法。
  • 调用时需要传入必要的参数,如交易所的池地址、代币的源和目标账户等。
  • 利用 Solana 的 invokeinvoke_signed 指令调用 Raydium 的智能合约(这个合约通常是由 Raydium 提供的)。

关键概念

  1. Raydium Swap:Raydium 提供了 swap 方法来进行代币交换,涉及从一个代币池中提取代币并向另一个代币池存入代币。

  2. Token Swap 流程:需要理解代币池地址,输入代币账户、输出代币账户,池地址等信息。

  3. 调用 Raydium 合约:Raydium 的交易实现是在 Solana 程序中通过合约调用实现的,通常会通过特定的程序 ID 来调用 Raydium 的合约。

步骤概览

  1. 准备 Raydium 合约的程序 ID 和池地址。
  2. 获取并传递必要的账户信息:源代币账户、目标代币账户、Raydium池地址等。
  3. 使用 invokeinvoke_signed 调用 Raydium 的 Swap 方法。

Solana 程序示例:调用 Raydium Swap

use solana_program::{
    account_info::AccountInfo,
    entrypoint::ProgramResult,
    pubkey::Pubkey,
    program::{invoke, invoke_signed},
    msg,
    sysvar::rent::Rent,
};

/// 这是我们程序调用Raydium的Swap方法
pub fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    instruction_data: &[u8], // 用于传递 swap 相关的数据
) -> ProgramResult {
    // 1. 定义 Raydium 的程序ID 和池地址
    let raydium_program_id = Pubkey::new_from_array([/* Raydium 程序公钥 */]);

    // Raydium池地址,假设这里是一个示例池地址
    let raydium_pool_address = Pubkey::new_from_array([/* Raydium 池地址公钥 */]);

    // 2. 准备传递给 Raydium 的账户信息
    let source_token_account = &accounts[0]; // 输入代币账户
    let destination_token_account = &accounts[1]; // 输出代币账户
    let pool_token_account = &accounts[2]; // 池中的代币账户
    let authority_account = &accounts[3]; // 授权账户

    // 3. 构造调用 Raydium Swap 的数据
    // 这里需要根据 Raydium 的 Swap 合约的具体数据结构来构造,假设我们已经知道如何构造数据
    let swap_data = instruction_data.to_vec(); // 在真实实现中,应该根据Raydium的Swap接口构造正确的instruction_data

    msg!("Calling Raydium swap...");

    // 4. 调用 Raydium 程序的 swap 方法
    let instruction = solana_program::instruction::Instruction {
        program_id: raydium_program_id,
        accounts: vec![
            // 这里指定需要传递给 Raydium 的账户
            AccountMeta::new(*source_token_account.key, false),    // 输入代币账户
            AccountMeta::new(*destination_token_account.key, false), // 输出代币账户
            AccountMeta::new(*pool_token_account.key, false), // 池代币账户
            AccountMeta::new(*authority_account.key, true),   // 授权账户,通常需要签名
        ],
        data: swap_data, // 传递 Swap 数据
    };

    // 5. 执行 invoke 调用 Raydium 的 Swap 合约
    invoke(
        &instruction,
        accounts, // 必须提供参与交易的账户信息
    )?;

    msg!("Raydium swap executed successfully!");

    Ok(())
}

关键点说明

  1. Raydium 程序 IDraydium_program_id 是 Raydium 合约的程序公钥。你需要从 Raydium 获取到这个程序公钥。

  2. 账户传递:在这个示例中,accounts 数组中包含了多个账户,分别代表源代币账户、目标代币账户、池代币账户和授权账户。实际情况中,根据 Raydium 的要求,你可能需要传递更多或不同的账户。

  3. Swap 数据构造instruction_data 是你调用 Raydium 的 swap 方法时需要传递的数据。在这里,我们假设你已经通过某种方式(例如 Raydium SDK 或 API)构造好了正确的交换数据。

  4. 调用 invoke 方法:我们使用 invoke 方法来调用 Raydium 程序。你需要确保传递的账户是正确的,并且每个账户都有必要的权限。

  5. 返回结果:调用成功后,你可以根据实际情况处理返回的结果。

实际部署与运行

在实际使用中,你需要确保以下几点:

  1. Raydium 池地址:确保你使用的是正确的池地址。Raydium 上有多个不同的池,你需要使用你想要交换的特定池的地址。

  2. 代币账户:确保你有源代币账户和目标代币账户,并且它们已经正确设置并且具备足够的余额。

  3. 授权账户:如果操作需要签名,你需要使用正确的授权账户。

  4. 调试与测试:在开发过程中,可以使用 Solana Devnet 或 Testnet 进行调试和测试,确保程序逻辑正确。

结语

这个示例展示了如何在 Solana 程序中调用 Raydium 的 Swap 方法。在实际开发中,你可能还需要参考 Raydium 官方文档和 API,确保调用数据结构和合约逻辑的准确性。





以上就是本篇文章的全部内容了,希望对你有帮助。

>> 本站不提供评论服务,技术交流请在 Twitter 上找我