From e6c2420f4efaa7e6a3f531397b10590633bf42df Mon Sep 17 00:00:00 2001 From: alenmestrov Date: Fri, 22 Nov 2024 15:24:40 +0100 Subject: [PATCH] updated types and finalized waiting for execution of transaction --- .../src/client/env/proxy/types/starknet.rs | 20 +++++- .../config/src/client/protocol/starknet.rs | 65 ++++++++++++++----- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/crates/context/config/src/client/env/proxy/types/starknet.rs b/crates/context/config/src/client/env/proxy/types/starknet.rs index c49ce7185..10e5d9835 100644 --- a/crates/context/config/src/client/env/proxy/types/starknet.rs +++ b/crates/context/config/src/client/env/proxy/types/starknet.rs @@ -164,10 +164,28 @@ impl From> for StarknetProposalActionWithArgs { deposit, gas, } => { + // Parse the args string (which is a JSON array of strings) into Felts + let args_vec: Vec = serde_json::from_str(&args) + .unwrap_or_else(|_| Vec::new()); + + let felt_args: Vec = args_vec + .iter() + .map(|arg| { + // If the arg starts with "0x", parse as hex + if arg.starts_with("0x") { + // Use from_hex_unchecked for hex strings + Felt::from_hex_unchecked(arg) + } else { + // Otherwise parse as bytes + Felt::from_bytes_be_slice(arg.as_bytes()) + } + }) + .collect(); + StarknetProposalActionWithArgs::ExternalFunctionCall( Felt::from_bytes_be_slice(receiver_id.as_bytes()), Felt::from_bytes_be_slice(method_name.as_bytes()), - vec![], // TODO: parse args string into Felts + felt_args, ) } ProposalAction::Transfer { diff --git a/crates/context/config/src/client/protocol/starknet.rs b/crates/context/config/src/client/protocol/starknet.rs index bb49582c7..2ac96733e 100644 --- a/crates/context/config/src/client/protocol/starknet.rs +++ b/crates/context/config/src/client/protocol/starknet.rs @@ -6,12 +6,13 @@ use std::sync::Arc; use serde::{Deserialize, Serialize}; use starknet::accounts::{Account, ConnectedAccount, ExecutionEncoding, SingleOwnerAccount}; use starknet::core::codec::Decode; -use starknet::core::types::{BlockId, BlockTag, Call, Felt, FunctionCall}; +use starknet::core::types::{BlockId, BlockTag, Call, ExecutionResult, Felt, FunctionCall, TransactionFinalityStatus}; use starknet::core::utils::get_selector_from_name; use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::{JsonRpcClient, Provider, Url}; use starknet::signers::{LocalWallet, SigningKey}; use thiserror::Error; +use std::time::{Instant, Duration}; use super::Protocol; use crate::client::env::proxy::starknet::StarknetProposalWithApprovals; @@ -310,18 +311,50 @@ impl Network { }]) .send() .await - .unwrap(); - - let receipt = account - .provider() - .get_transaction_receipt(response.transaction_hash) - .await - .unwrap(); + .map_err(|e| StarknetError::Custom { + operation: ErrorOperation::Mutate, + reason: format!("Failed to send transaction: {}", e), + })?; + + let sent_at = Instant::now(); + let timeout = Duration::from_secs(60); // Same 60-second timeout as NEAR + + let receipt = loop { + match account + .provider() + .get_transaction_receipt(response.transaction_hash) + .await + { + Ok(receipt) => { + if let starknet::core::types::TransactionReceipt::Invoke(invoke_receipt) = &receipt.receipt { + if matches!(invoke_receipt.finality_status, + TransactionFinalityStatus::AcceptedOnL2 | + TransactionFinalityStatus::AcceptedOnL1) { + break receipt; + } + + if sent_at.elapsed() > timeout { + return Err(StarknetError::TransactionTimeout); + } + continue; + } + }, + Err(err) => { + return Err(StarknetError::Custom { + operation: ErrorOperation::Mutate, + reason: err.to_string(), + }); + } + } + }; + + // Process the receipt match receipt.receipt { starknet::core::types::TransactionReceipt::Invoke(invoke_receipt) => { match invoke_receipt.execution_result { - starknet::core::types::ExecutionResult::Succeeded => { + ExecutionResult::Succeeded => { + // Process events and return result for event in invoke_receipt.events.iter() { if event.from_address == contract_id { let result = StarknetProposalWithApprovals::decode(&event.data) @@ -329,23 +362,23 @@ impl Network { operation: ErrorOperation::Query, reason: format!("Failed to decode event: {:?}", e), })?; - // Add length prefix (32 bytes) let mut encoded = vec![0u8; 32]; - // Add proposal_id high part (32 bytes) encoded.extend_from_slice(&result.proposal_id.high.to_bytes_be()); - // Add proposal_id low part (32 bytes) encoded.extend_from_slice(&result.proposal_id.low.to_bytes_be()); - // Add num_approvals (32 bytes) encoded.extend_from_slice(&result.num_approvals.to_bytes_be()); - return Ok(encoded); } } Ok(vec![]) + }, + ExecutionResult::Reverted { reason } => { + Err(StarknetError::Custom { + operation: ErrorOperation::Mutate, + reason: format!("Transaction reverted: {}", reason), + }) } - _ => Ok(vec![0]), } - } + }, _ => Ok(vec![0]), } }