alloy is used to send evm transactions. In the local environment, the transaction can be successfully sent, but on the main ICP network, a message is displayed indicating a TransportError(ErrorResp(ErrorPayload {code: -32000, message: "already known", data: None})), it seems to be because of the error caused by ICP consensus, please help me
se crate::types::{CHAIN_INFO, CONFIG_INFO};
use alloy::primitives::PrimitiveSignature;
use alloy::{
network::EthereumWallet,
primitives::{Address, Bytes, U256},
providers::{Provider, ProviderBuilder},
signers::local::PrivateKeySigner,
sol,
transports::icp::{IcpConfig, RpcApi, RpcService},
};
use common_utils::decrypt_keystore::{decrypt_keystore, get_private_key};
use common_utils::get_time;
use common_utils::types::PRIVATE_KEY_STORAGE;
use hex::FromHex;
sol!(
#[allow(missing_docs, clippy::too_many_arguments)]
#[sol(rpc)]
MarketCapManager,
"abi/abi.json"
);
pub async fn send_withdraw(
cycle: u64,
amount: u128,
inter_nonce: u64,
sign_time: u64,
signature: String,
swap_amount: u128,
) -> Result<String, String> {
let private_key = get_private_key();
let signer = private_key
.parse::<PrivateKeySigner>()
.map_err(|e| format!("Private key conversion error, {}", e))?;
let address = signer.address();
let wallet = EthereumWallet::from(signer);
let chain_info = CHAIN_INFO.with(|chain| chain.borrow().get().clone());
let rpc_service = RpcService::Custom(RpcApi {
url: chain_info.chain_url.clone(),
headers: None,
});
let config = IcpConfig::new(rpc_service);
let provider = ProviderBuilder::new()
.with_gas_estimation()
.wallet(wallet)
.on_icp(config);
let contract_address: Address = chain_info
.contract_address
.parse()
.map_err(|e| format!("Invalid contract address: {}", e))?;
let contract = MarketCapManager::new(contract_address, provider.clone());
let signature_bytes = match Vec::from_hex(&signature) {
Ok(bytes) => bytes,
Err(e) => return Err(format!("Invalid signature hex: {}", e)),
};
let result = provider.get_transaction_count(address).await;
let nonce = match result {
Ok(n) => n,
Err(e) => {
return Err(format!("Description Failed to obtain the nonce, {}", e));
}
};
//first withdraw -> swap
match contract
.withdrawFromMiningPool(
U256::from(cycle),
U256::from(amount),
U256::from(inter_nonce),
U256::from(sign_time),
Bytes::from(signature_bytes.clone()),
U256::from(swap_amount),
)
.nonce(nonce)
.chain_id(chain_info.chain_id)
.from(address)
.gas_price(3000000000)
.send()
.await
{
Ok(builder) => {
let node_hash = *builder.tx_hash();
let tx_response = provider.get_transaction_by_hash(node_hash).await.unwrap();
match tx_response {
Some(tx) => return Ok(format!("The 1 task is successfully, {}", tx.hash)),
None => return Err(format!(
"The 1 task failed, could not get transaction, {}",
node_hash
)),
}
},
Err(e) => {
return Err(format!(
"The 1 task failed, could not send transaction, {:?}",
e
));
}
};
Err("The 1 task exception error".to_string())
}