diff --git a/Cargo.lock b/Cargo.lock index 68f04bb3..282676f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3865,7 +3865,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 2.0.46", diff --git a/bridge-escrow-test.sh b/bridge-escrow-test.sh new file mode 100755 index 00000000..010a8621 --- /dev/null +++ b/bridge-escrow-test.sh @@ -0,0 +1,40 @@ +rm -fr ./test-ledger + +solana-test-validator > /dev/null 2>&1 & +VALIDATOR_PID=$! + +echo "Solana test validator started in the background with PID $VALIDATOR_PID." + +sleep 5 + +echo "Running Debug and Deployment" + +# Default behavior +SKIP_DEPLOY=false + +# Parse command-line arguments +while [[ "$#" -gt 0 ]]; do + case $1 in + --skip-deploy) SKIP_DEPLOY=true ;; + *) echo "Unknown parameter passed: $1"; exit 1 ;; + esac + shift +done + + +solana config set --url http://127.0.0.1:8899 + +if [ "$SKIP_DEPLOY" = false ]; then + anchor build -p bridge_escrow + solana program deploy target/deploy/bridge_escrow.so --program-id target/deploy/bridge_escrow-keypair.json +else + echo "Skipping Deployment" +fi + +cargo test -p bridge-escrow -- --nocapture + +echo "Stopping solana-test-validator..." +kill $VALIDATOR_PID + +wait $VALIDATOR_PID +echo "Solana test validator has been stopped." \ No newline at end of file diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs index 934311d3..25126141 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/lib.rs @@ -23,7 +23,7 @@ pub mod events; #[cfg(test)] mod tests; -declare_id!("AhfoGVmS19tvkEG2hBuZJ1D6qYEjyFmXZ1qPoFD6H4Mj"); +declare_id!("H3jfQXtiC3DW4bwMafKiiW2xhYjwZDkV21SMaYqEtMM8"); #[program] pub mod bridge_escrow { @@ -63,32 +63,57 @@ pub mod bridge_escrow { ); require!( - new_intent.token_in == ctx.accounts.user_token_account.mint, + new_intent.token_in == System::id() || new_intent.token_in == ctx.accounts.user_token_account.clone().unwrap().mint, ErrorCode::TokenInNotMint ); require!( - new_intent.user_in == ctx.accounts.user_token_account.owner, + new_intent.user_in == ctx.accounts.user_token_account.clone().unwrap().owner, ErrorCode::SrcUserNotUserIn ); // Step 2: Escrow the funds (same as before) + // Handle Native SOL Transfer + if new_intent.token_in == System::id() { + // Perform SOL transfer from Solver to User + let src_user = ctx.accounts.user.clone(); + + let ix = solana_program::system_instruction::transfer( + src_user.key, + &ctx.accounts.auctioneer_state.key(), + new_intent.amount_in, + ); - let cpi_accounts = SplTransfer { - from: ctx.accounts.user_token_account.to_account_info(), - to: ctx.accounts.escrow_token_account.to_account_info(), - authority: ctx.accounts.user.to_account_info(), - }; - - let cpi_program = ctx.accounts.token_program.to_account_info(); - let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); - - token::transfer(cpi_ctx, new_intent.amount_in)?; + invoke( + &ix, + &[ + src_user.to_account_info(), + ctx.accounts.auctioneer_state.to_account_info(), + ctx.accounts.system_program.to_account_info(), + ], + )?; + + // **src_user.lamports.borrow_mut() -= new_intent.amount_in; + // **ctx.accounts.auctioneer_state.to_account_info().lamports.borrow_mut() += new_intent.amount_in; + + } else { + + let cpi_accounts = SplTransfer { + from: ctx.accounts.user_token_account.clone().unwrap().to_account_info(), + to: ctx.accounts.escrow_token_account.clone().unwrap().to_account_info(), + authority: ctx.accounts.user.to_account_info(), + }; + + let cpi_program = ctx.accounts.token_program.to_account_info(); + let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); + + token::transfer(cpi_ctx, new_intent.amount_in)?; + } events::emit(events::Event::EscrowFunds(events::EscrowFunds { amount: new_intent.amount_in, sender: ctx.accounts.user.key(), - token_mint: ctx.accounts.token_mint.key(), + token_mint: ctx.accounts.token_mint.clone().unwrap().key(), })).map_err(|err| { msg!("{}", err); ErrorCode::InvalidEventFormat @@ -318,20 +343,11 @@ pub mod bridge_escrow { // Handle Native SOL Transfer if intent.token_out == System::id().to_string() { // Perform SOL transfer from Solver to User - let ix = solana_program::system_instruction::transfer( - solver.key, - &intent.user_in, - amount_out, - ); - - invoke( - &ix, - &[ - solver.to_account_info(), - accounts.user_token_out_account.to_account_info(), - accounts.system_program.to_account_info(), - ], - )?; + let out_user_account = accounts.user_account.clone().unwrap(); + + **solver.lamports.borrow_mut() -= amount_out; + **out_user_account.lamports.borrow_mut() += amount_out; + } else { // Perform SPL transfer from Solver to User let cpi_accounts = SplTransfer { @@ -368,26 +384,31 @@ pub mod bridge_escrow { .as_ref() .ok_or(ErrorCode::AccountsNotPresent)?; - require!( - intent.token_in == auctioneer_token_in_account.mint, - ErrorCode::MismatchTokenIn - ); - - let cpi_accounts = SplTransfer { - from: auctioneer_token_in_account.to_account_info(), - to: solver_token_in_account.to_account_info(), - authority: accounts.auctioneer_state.to_account_info(), - }; - let cpi_program = token_program.to_account_info(); - - token::transfer( - CpiContext::new_with_signer( - cpi_program, - cpi_accounts, - signer_seeds, - ), - intent.amount_in, - )?; + if intent.token_in == System::id() { + **accounts.auctioneer_state.to_account_info().lamports.borrow_mut() -= intent.amount_in; + **solver.lamports.borrow_mut() += intent.amount_in; + } else { + require!( + intent.token_in == auctioneer_token_in_account.mint, + ErrorCode::MismatchTokenIn + ); + + let cpi_accounts = SplTransfer { + from: auctioneer_token_in_account.to_account_info(), + to: solver_token_in_account.to_account_info(), + authority: accounts.auctioneer_state.to_account_info(), + }; + let cpi_program = token_program.to_account_info(); + + token::transfer( + CpiContext::new_with_signer( + cpi_program, + cpi_accounts, + signer_seeds, + ), + intent.amount_in, + )?; + } events::emit(events::Event::SendFundsToUser( events::SendFundsToUser { @@ -430,20 +451,11 @@ pub mod bridge_escrow { // Check if token_out is native SOL or SPL token if accounts.token_out.key() == System::id() { // Handle Native SOL Transfer - let ix = solana_program::system_instruction::transfer( - solver.key, - &accounts.user_token_out_account.key(), - amount_out, - ); - - invoke( - &ix, - &[ - solver.to_account_info(), - accounts.user_token_out_account.to_account_info(), - accounts.system_program.to_account_info(), - ], - )?; + let out_user_account = accounts.user_account.clone().unwrap(); + + **solver.lamports.borrow_mut() -= amount_out; + **out_user_account.lamports.borrow_mut() += amount_out; + } else { // Perform SPL token transfer from Solver to User let cpi_accounts = SplTransfer { @@ -713,6 +725,10 @@ pub struct SplTokenTransferCrossChain<'info> { #[account(mut, token::mint = token_out)] pub user_token_out_account: Box>, + // Solver -> User Account in case of SOL transfer + #[account(mut, address = user_token_out_account.owner)] + pub user_account: Option>, + pub token_program: Program<'info, Token>, pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, @@ -767,7 +783,7 @@ pub struct SplTokenTransfer<'info> { #[account(mut, address = intent.clone().unwrap().user_in)] /// CHECK: pub intent_owner: UncheckedAccount<'info>, - #[account(seeds = [AUCTIONEER_SEED], bump)] + #[account(mut, seeds = [AUCTIONEER_SEED], bump)] pub auctioneer_state: Box>, #[account(mut)] pub solver: Signer<'info>, @@ -791,6 +807,10 @@ pub struct SplTokenTransfer<'info> { #[account(mut, token::mint = token_out)] pub user_token_out_account: Box>, + // Solver -> User Account in case of SOL transfer + #[account(mut, address = user_token_out_account.owner)] + pub user_account: Option>, + pub token_program: Program<'info, Token>, pub associated_token_program: Program<'info, AssociatedToken>, pub system_program: Program<'info, System>, @@ -844,18 +864,18 @@ pub struct EscrowAndStoreIntent<'info> { // Box this account to avoid copying large account data #[account(mut, token::authority = user, token::mint = token_mint)] - pub user_token_account: Box>, + pub user_token_account: Option>>, // Box this account as it holds state that might be large - #[account(seeds = [AUCTIONEER_SEED], bump)] + #[account(mut, seeds = [AUCTIONEER_SEED], bump)] pub auctioneer_state: Box>, // Box the token mint account if it's large or for performance reasons - pub token_mint: Box>, + pub token_mint: Option>>, // Box the escrow token account as it's mutable and holds token data #[account(init_if_needed, payer = user, associated_token::mint = token_mint, associated_token::authority = auctioneer_state)] - pub escrow_token_account: Box>, + pub escrow_token_account: Option>>, // From StoreIntent // Box the intent account, as it's a new account with considerable space allocated diff --git a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs index a5f76002..8ec37bc9 100644 --- a/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs +++ b/solana/bridge-escrow/programs/bridge-escrow/src/tests.rs @@ -1,4 +1,5 @@ use std::rc::Rc; +use std::str::FromStr; use std::thread::sleep; use std::time::{Duration, SystemTime, UNIX_EPOCH}; @@ -10,6 +11,7 @@ use anchor_client::solana_sdk::pubkey::Pubkey; use anchor_client::solana_sdk::signature::{ read_keypair_file, Keypair, Signature, Signer as SolanaSigner, }; +use anchor_client::solana_sdk::transaction::Transaction; use anchor_client::{Client, Cluster}; use anchor_lang::system_program; use anchor_spl::associated_token::{self, get_associated_token_address}; @@ -35,15 +37,359 @@ fn airdrop(client: &RpcClient, account: Pubkey, lamports: u64) -> Signature { airdrop_signature } +fn simulate_tx(client: RpcClient, transaction: Transaction) { + // Simulate the transaction + let simulation_result = client + .simulate_transaction( + &transaction, + ) + .expect("Failed to simulate transaction"); + println!("Simulation logs: {:?}", simulation_result); + + // Print the result + if let Some(logs) = simulation_result.value.logs { + println!("Simulation logs:"); + for log in logs { + println!("{}", log); + } + } else { + println!("No logs returned from simulation."); + } +} + +#[test] +//#[ignore = "Requires local validator to run"] +fn test_native_mint_transfer() -> Result<()> { + // Setup the client and wallet + let auctioneer = + Rc::new(read_keypair_file("../../../solana-ibc/keypair.json").unwrap()); + + let client = Client::new_with_options( + Cluster::from_str("http://127.0.0.1:8899").unwrap(),//Cluster::Localnet, + auctioneer.clone(), + CommitmentConfig::processed(), + ); + + let program = client.program(crate::ID)?; + let sol_rpc_client = program.rpc(); + + let lamports = 20_000_000_000; + + let solver = Rc::new(Keypair::new()); + let user = Rc::new(Keypair::new()); + let token_in_keypair = Keypair::new(); + let token_in = token_in_keypair.pubkey(); + let token_out_keypair = Keypair::new(); + let token_out = token_out_keypair.pubkey(); + + let program_rpc = program.rpc(); + + // Below is for Devnet/Mainnet + + println!("User {:?}", user.to_bytes()); + println!("Solver {:?}", solver.to_bytes()); + + airdrop(&program_rpc, auctioneer.pubkey(), lamports); + airdrop(&program_rpc, user.pubkey(), lamports); + airdrop(&program_rpc, solver.pubkey(), lamports); + + let auctioneer_state = + Pubkey::find_program_address(&[crate::AUCTIONEER_SEED], &crate::ID).0; + + /* + * Creating Token In Mint + */ + println!("\nCreating a token in mint"); + + let create_token_in_account_ix = create_account( + &auctioneer.pubkey(), + &token_in, + sol_rpc_client.get_minimum_balance_for_rent_exemption(82).unwrap(), + 82, + &anchor_spl::token::ID, + ); + + let create_token_in_mint_ix = initialize_mint2( + &anchor_spl::token::ID, + &token_in, + &auctioneer.pubkey(), + Some(&auctioneer.pubkey()), + 6, + ) + .expect("invalid mint instruction"); + + let create_token_acc_ix = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &solver.pubkey(), &token_in, &anchor_spl::token::ID); + let create_token_acc_ix_2 = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &user.pubkey(), &token_in, &anchor_spl::token::ID); + let user_token_in_addr = + get_associated_token_address(&user.pubkey(), &token_in); + let mint_ix = spl_token::instruction::mint_to( + &anchor_spl::token::ID, + &token_in, + &user_token_in_addr, + &auctioneer.pubkey(), + &[&auctioneer.pubkey()], + MINT_AMOUNT, + ) + .unwrap(); + + let tx = program + .request() + .instruction(create_token_in_account_ix) + .instruction(create_token_in_mint_ix) + .instruction(create_token_acc_ix) + .instruction(create_token_acc_ix_2) + .instruction(mint_ix) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .signer(&token_in_keypair) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + })?; + + println!(" Signature: {}", tx); + + /* + * Creating Token Out Mint + */ + println!("\nCreating a token out mint"); + + let create_token_out_account_ix = create_account( + &auctioneer.pubkey(), + &token_out, + sol_rpc_client.get_minimum_balance_for_rent_exemption(82).unwrap(), + 82, + &anchor_spl::token::ID, + ); + + let create_token_out_mint_ix = initialize_mint2( + &anchor_spl::token::ID, + &token_out, + &auctioneer.pubkey(), + Some(&auctioneer.pubkey()), + 6, + ) + .expect("invalid mint instruction"); + + let create_token_acc_ix = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &solver.pubkey(), &token_out, &anchor_spl::token::ID); + let create_token_acc_ix_2 = spl_associated_token_account::instruction::create_associated_token_account(&auctioneer.pubkey(), &user.pubkey(), &token_out, &anchor_spl::token::ID); + let solver_token_out_addr = + get_associated_token_address(&solver.pubkey(), &token_out); + let mint_ix = spl_token::instruction::mint_to( + &anchor_spl::token::ID, + &token_out, + &solver_token_out_addr, + &auctioneer.pubkey(), + &[&auctioneer.pubkey()], + MINT_AMOUNT, + ) + .unwrap(); + + let tx = program + .request() + .instruction(create_token_out_account_ix) + .instruction(create_token_out_mint_ix) + .instruction(create_token_acc_ix) + .instruction(create_token_acc_ix_2) + .instruction(mint_ix) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .signer(&token_out_keypair) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + })?; + + println!(" Signature: {}", tx); + + let dummy_token_mint = + Pubkey::find_program_address(&[crate::DUMMY_SEED], &crate::ID).0; + + // Initialize the program to define the auctioneer + println!("\nInitializing the program"); + + if !program_rpc.get_account(&auctioneer_state).is_ok() { + let sig = program + .request() + .accounts(crate::accounts::Initialize { + authority: auctioneer.pubkey(), + auctioneer: auctioneer_state, + token_mint: dummy_token_mint, + system_program: anchor_lang::solana_program::system_program::ID, + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, + }) + .args(crate::instruction::Initialize {}) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + + println!("Signature: {}", sig); + } else { + println!("Program already initialized. Skipping Initialization ..."); + } + + + let token_in_escrow_addr = + get_associated_token_address(&auctioneer_state, &token_in); + + // Escrow user funds and store intent (combined) + println!("\nEscrow user funds and store intent for single domain"); + + let intent_id = "123456789".to_string(); + // Define amount_out (this would typically come from the intent) + let amount_out = 10000; // This should match what’s expected in the intent + + // Find the Program Derived Address (PDA) for the intent account + let intent_state = Pubkey::find_program_address( + &[crate::INTENT_SEED, intent_id.as_bytes()], + &crate::ID, + ) + .0; + + // Get the current timestamp + let current_timestamp = + SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + + // Define the new intent payload + let new_intent = IntentPayload { + intent_id: intent_id.clone(), + user_in: user.pubkey(), // Must match the ctx.accounts.user key in the contract + user_out: user.pubkey().to_string(), + token_in: Pubkey::default(), // token_in, + amount_in: TRANSFER_AMOUNT, + token_out: Pubkey::default().to_string(),// token_out.to_string(), + amount_out: amount_out.to_string(), // Amount out as a string + timeout_timestamp_in_sec: current_timestamp + 10000, // Arbitrary timeout + single_domain: true, + }; + + // Call the escrow_and_store_intent() function + let sig = program + .request() + .accounts(crate::accounts::EscrowAndStoreIntent { + user: user.pubkey(), + user_token_account: Some(user_token_in_addr), + auctioneer_state, + token_mint: Some(token_in), + escrow_token_account: Some(token_in_escrow_addr), + intent: intent_state, + token_program: anchor_spl::token::ID, + associated_token_program: associated_token::ID, + system_program: system_program::ID, + }) + .args(crate::instruction::EscrowAndStoreIntent { + new_intent, + }) + .payer(user.clone()) + .signer(&*user) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + + println!(" Signature: {}", sig); + + // Test for the update_auction_data function (only auctioneer can call this) + println!("\nTesting update_auction_data function"); + + // New auction data + let amount_out = 10_000; // This should match what’s expected in the intent + let winner_solver = solver.pubkey(); // A new winner solver public key + + // Only auctioneer should be able to call this function + let sig = program + .request() + .accounts(crate::accounts::UpdateAuctionData { + authority: auctioneer.pubkey(), // Must be auctioneer + auctioneer: auctioneer_state, + intent: intent_state, + }) + .args(crate::instruction::UpdateAuctionData { + intent_id: intent_id.clone(), + amount_out: amount_out.clone().to_string(), + winner_solver: winner_solver.to_string(), + }) + .payer(auctioneer.clone()) + .signer(&*auctioneer) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..RpcSendTransactionConfig::default() + }) + .unwrap(); + + // println!(" Signature: {}", sig); + + // Send funds to user (single domain) + println!("\nSend funds to user single domain"); + + // Get the associated token addresses for the solver and the user + let solver_token_in_addr = get_associated_token_address(&solver.pubkey(), &token_in); + let user_token_out_addr = get_associated_token_address(&user.pubkey(), &token_out); + + // Call the `send_funds_to_user` function + let sig = program + .request() + .accounts(crate::accounts::SplTokenTransfer { + solver: solver.pubkey(), + intent: Some(intent_state), + intent_owner: user.pubkey(), + auctioneer_state, + auctioneer: auctioneer.pubkey(), + token_in: Some(token_in), + token_out, + auctioneer_token_in_account: Some(token_in_escrow_addr), + solver_token_in_account: Some(solver_token_in_addr), + solver_token_out_account: solver_token_out_addr, + user_token_out_account: user_token_out_addr, + user_account: Some(user.pubkey()), + token_program: anchor_spl::token::ID, + associated_token_program: anchor_spl::associated_token::ID, + system_program: anchor_lang::solana_program::system_program::ID, + // Cross-chain related fields, set to None since it's single domain + ibc_program: None, + receiver: None, + storage: None, + trie: None, + chain: None, + mint_authority: None, + token_mint: None, + escrow_account: None, + receiver_token_account: None, + fee_collector: None, + }) + .args(crate::instruction::SendFundsToUser { + intent_id: intent_id.clone() + }) + .payer(solver.clone()) + .signer(&*solver) + .send_with_spinner_and_config(RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }) + .unwrap(); + + println!(" Signature: {}", sig); + + Ok(()) +} + + #[test] -#[ignore = "Requires local validator to run"] +#[ignore] +//#[ignore = "Requires local validator to run"] fn escrow_bridge_program() -> Result<()> { // Setup the client and wallet let auctioneer = Rc::new(read_keypair_file("../../../solana-ibc/keypair.json").unwrap()); let client = Client::new_with_options( - Cluster::Localnet, + Cluster::from_str("http://127.0.0.1:8899").unwrap(),//Cluster::Localnet, auctioneer.clone(), CommitmentConfig::processed(), ); @@ -51,7 +397,7 @@ fn escrow_bridge_program() -> Result<()> { let program = client.program(crate::ID)?; let sol_rpc_client = program.rpc(); - let lamports = 2_000_000_000; + let lamports = 20_000_000_000; let solver = Rc::new(Keypair::new()); let user = Rc::new(Keypair::new()); @@ -64,8 +410,8 @@ fn escrow_bridge_program() -> Result<()> { // Below is for Devnet/Mainnet - // println!("User {:?}", user.to_bytes()); - // println!("Solver {:?}", solver.to_bytes()); + println!("User {:?}", user.to_bytes()); + println!("Solver {:?}", solver.to_bytes()); // let blockhash = program_rpc.get_latest_blockhash()?; // let user_transfer_ix = @@ -203,7 +549,9 @@ fn escrow_bridge_program() -> Result<()> { // Initialize the program to define the auctioneer println!("\nInitializing the program"); - let sig = program + + if !program_rpc.get_account(&auctioneer_state).is_ok() { + let sig = program .request() .accounts(crate::accounts::Initialize { authority: auctioneer.pubkey(), @@ -221,7 +569,12 @@ fn escrow_bridge_program() -> Result<()> { ..Default::default() }) .unwrap(); - println!(" Signature: {}", sig); + + println!("Signature: {}", sig); + } else { + println!("Program already initialized. Skipping Initialization ..."); + } + let token_in_escrow_addr = get_associated_token_address(&auctioneer_state, &token_in); @@ -256,23 +609,22 @@ fn escrow_bridge_program() -> Result<()> { timeout_timestamp_in_sec: current_timestamp + 10000, // Arbitrary timeout single_domain: true, }; - + // Call the escrow_and_store_intent() function let sig = program .request() .accounts(crate::accounts::EscrowAndStoreIntent { user: user.pubkey(), - user_token_account: user_token_in_addr, + user_token_account: Some(user_token_in_addr), auctioneer_state, - token_mint: token_in, - escrow_token_account: token_in_escrow_addr, + token_mint: Some(token_in), + escrow_token_account: Some(token_in_escrow_addr), intent: intent_state, token_program: anchor_spl::token::ID, associated_token_program: associated_token::ID, system_program: system_program::ID, }) .args(crate::instruction::EscrowAndStoreIntent { - amount: TRANSFER_AMOUNT, new_intent, }) .payer(user.clone()) @@ -327,7 +679,8 @@ fn escrow_bridge_program() -> Result<()> { .request() .accounts(crate::accounts::SplTokenTransfer { solver: solver.pubkey(), - intent: intent_state, + intent: Some(intent_state), + intent_owner: user.pubkey(), auctioneer_state, auctioneer: auctioneer.pubkey(), token_in: Some(token_in), @@ -336,6 +689,7 @@ fn escrow_bridge_program() -> Result<()> { solver_token_in_account: Some(solver_token_in_addr), solver_token_out_account: solver_token_out_addr, user_token_out_account: user_token_out_addr, + user_account: Some(user.pubkey()), token_program: anchor_spl::token::ID, associated_token_program: anchor_spl::associated_token::ID, system_program: anchor_lang::solana_program::system_program::ID, @@ -352,18 +706,18 @@ fn escrow_bridge_program() -> Result<()> { fee_collector: None, }) .args(crate::instruction::SendFundsToUser { - intent_id: intent_id.clone(), - amount_out, // Pass the amount to transfer to the user - solver_out: None, // Set to None since this is a single domain transaction - single_domain: true, // Indicating that this is a single domain transaction + intent_id: intent_id.clone() }) .payer(solver.clone()) .signer(&*solver) + // .signed_transaction(); .send_with_spinner_and_config(RpcSendTransactionConfig { skip_preflight: true, ..Default::default() }) .unwrap(); + + // simulate_tx(program_rpc, sig.unwrap()); println!(" Signature: {}", sig);