zera-sdk 0.1.0

Rust SDK for ZERA transactions, validator APIs, and bridge workflows
Documentation
use solana_sdk::instruction::{AccountMeta, Instruction};
use solana_sdk::pubkey::Pubkey;

use crate::error::Result;

use super::super::constants::{
    ATA_PROGRAM_ID, CORE_PROGRAM_ID, SYSTEM_PROGRAM_ID, TOKEN_BRIDGE_PROGRAM_ID, TOKEN_PROGRAM_ID,
    WSOL_MINT,
};
use super::super::rpc::SolanaRpc;
use super::super::types::{
    LockSolAccounts, LockSolOptions, LockSolResult, LockSplAccounts, LockSplOptions, LockSplResult,
};
use super::super::utils::{
    concat_bytes, derive_rate_limit_state_pda, derive_router_config_pda, derive_router_signer_pda,
    derive_token_price_registry_pda, derive_token_registration_pda, encode_borsh_string,
    encode_u64_le, generate_discriminator, get_ata,
};
use super::helpers::{build_transaction, parse_pubkey, resolve_recent_blockhash};

pub async fn build_lock_spl_transaction(
    options: LockSplOptions,
    payer: &Pubkey,
    rpc: Option<&dyn SolanaRpc>,
) -> Result<LockSplResult> {
    let mint = parse_pubkey(&options.mint, "mint")?;
    let (router_signer, _) = derive_router_signer_pda();
    let (router_config, _) = derive_router_config_pda();
    let (rate_limit_state, _) = derive_rate_limit_state_pda();
    let (token_registration, _) = derive_token_registration_pda(&mint);

    let user_ata = get_ata(payer, &mint);
    let vault_ata = get_ata(&router_signer, &mint);

    let discriminator = generate_discriminator("global:lock_spl");
    let amount = encode_u64_le(options.amount);
    let zera_address = encode_borsh_string(&options.zera_address);
    let data = concat_bytes(&[
        discriminator.as_ref(),
        amount.as_ref(),
        zera_address.as_slice(),
    ]);

    let instruction = Instruction {
        program_id: *TOKEN_BRIDGE_PROGRAM_ID,
        accounts: vec![
            AccountMeta::new_readonly(*CORE_PROGRAM_ID, false),
            AccountMeta::new_readonly(router_config, false),
            AccountMeta::new(*payer, true),
            AccountMeta::new(user_ata, false),
            AccountMeta::new_readonly(mint, false),
            AccountMeta::new_readonly(router_signer, false),
            AccountMeta::new(vault_ata, false),
            AccountMeta::new(rate_limit_state, false),
            AccountMeta::new(token_registration, false),
            AccountMeta::new_readonly(*TOKEN_PROGRAM_ID, false),
            AccountMeta::new_readonly(*ATA_PROGRAM_ID, false),
            AccountMeta::new_readonly(*SYSTEM_PROGRAM_ID, false),
        ],
        data,
    };

    let recent_blockhash = resolve_recent_blockhash(rpc).await?;
    let transaction = build_transaction(payer, vec![instruction.clone()], recent_blockhash);

    Ok(LockSplResult {
        instruction,
        transaction,
        accounts: LockSplAccounts {
            user_ata,
            vault_ata,
            router_signer,
            router_config,
            rate_limit_state,
            token_registration,
        },
    })
}

pub async fn build_lock_sol_transaction(
    options: LockSolOptions,
    payer: &Pubkey,
    rpc: Option<&dyn SolanaRpc>,
) -> Result<LockSolResult> {
    let (router_signer, _) = derive_router_signer_pda();
    let (router_config, _) = derive_router_config_pda();
    let (rate_limit_state, _) = derive_rate_limit_state_pda();
    let (token_price_registry, _) = derive_token_price_registry_pda();

    let payer_wsol_ata = get_ata(payer, &WSOL_MINT);
    let vault_ata = get_ata(&router_signer, &WSOL_MINT);

    let discriminator = generate_discriminator("global:lock_sol");
    let amount = encode_u64_le(options.amount);
    let zera_address = encode_borsh_string(&options.zera_address);
    let data = concat_bytes(&[
        discriminator.as_ref(),
        amount.as_ref(),
        zera_address.as_slice(),
    ]);

    let instruction = Instruction {
        program_id: *TOKEN_BRIDGE_PROGRAM_ID,
        accounts: vec![
            AccountMeta::new_readonly(*CORE_PROGRAM_ID, false),
            AccountMeta::new_readonly(router_config, false),
            AccountMeta::new(*payer, true),
            AccountMeta::new(payer_wsol_ata, false),
            AccountMeta::new(vault_ata, false),
            AccountMeta::new_readonly(router_signer, false),
            AccountMeta::new_readonly(*WSOL_MINT, false),
            AccountMeta::new(rate_limit_state, false),
            AccountMeta::new_readonly(token_price_registry, false),
            AccountMeta::new_readonly(*TOKEN_PROGRAM_ID, false),
            AccountMeta::new_readonly(*ATA_PROGRAM_ID, false),
            AccountMeta::new_readonly(*SYSTEM_PROGRAM_ID, false),
        ],
        data,
    };

    let recent_blockhash = resolve_recent_blockhash(rpc).await?;
    let transaction = build_transaction(payer, vec![instruction.clone()], recent_blockhash);

    Ok(LockSolResult {
        instruction,
        transaction,
        accounts: LockSolAccounts {
            payer_wsol_ata,
            vault_ata,
            router_signer,
            router_config,
            rate_limit_state,
            token_price_registry,
        },
    })
}