use anyhow::{anyhow, Result};
use equanetwork::{get_network_address, get_vault_address};
use solana_address::Address;
use solana_client::rpc_client::RpcClient;
use solana_instruction::Instruction;
use solana_pubkey::Pubkey;
use solana_signer::Signer;
use spl_associated_token_account_interface::{
address::get_associated_token_address, instruction::create_associated_token_account_idempotent,
};
pub fn pk(address: Address) -> Pubkey {
Pubkey::new_from_array(address.to_bytes())
}
pub fn addr(pubkey: Pubkey) -> Address {
Address::new_from_array(pubkey.to_bytes())
}
pub fn account_exists(rpc: &RpcClient, account: &Pubkey) -> bool {
rpc.get_account(account).is_ok()
}
pub fn ensure_ata(
rpc: &RpcClient,
ixs: &mut Vec<Instruction>,
payer: &impl Signer,
owner: &Pubkey,
mint: &Pubkey,
) -> Pubkey {
let ata = get_associated_token_address(owner, mint);
if !account_exists(rpc, &ata) {
ixs.push(create_associated_token_account_idempotent(
&payer.pubkey(),
owner,
mint,
&spl_token_interface::ID,
));
}
ata
}
pub fn require_signer(config: &crate::config::Config) -> Result<solana_keypair::Keypair> {
config
.keypair()
.ok_or_else(|| anyhow!("signer required (set --signer or Solana CLI config keypair)"))
}
pub fn parse_network_id(raw: &str) -> Result<u32> {
let trimmed = raw.trim();
if let Some(hex) = trimmed
.strip_prefix("0x")
.or_else(|| trimmed.strip_prefix("0X"))
{
return u32::from_str_radix(hex, 16).map_err(|e| anyhow!("invalid network-id hex: {e}"));
}
if trimmed.chars().all(|c| c.is_ascii_hexdigit())
&& trimmed.chars().any(|c| matches!(c, 'a'..='f' | 'A'..='F'))
&& !trimmed.chars().all(|c| c.is_ascii_digit())
{
return u32::from_str_radix(trimmed, 16)
.map_err(|e| anyhow!("invalid network-id hex: {e}"));
}
trimmed
.parse::<u32>()
.map_err(|e| anyhow!("network-id must be a u32 decimal or hex: {e}"))
}
pub fn network_pda(network_id: u32) -> Address {
get_network_address(network_id).0
}
pub fn vault_pda(network: &Pubkey, mint: &Pubkey) -> Address {
get_vault_address(&addr(*network), &addr(*mint)).0
}