Thanks @kristofer we were able to solve that but now within the function itself we make two ETH contract interactions, one being a call and the other being a send that requires a signer:
#[update(name = "Poolwithdraw")]
async fn pool_withdraw(
pool_id: u64,
user: String,
pool_deposit_type: u8,
chain_id: u64,
) -> Result<String, String> {
let nat_chain_id = Nat::from(chain_id);
let network = STATE.with(|state| {
let state = state.borrow();
let network = match state.supported_networks.get(&nat_chain_id) {
Some(network) => network,
None => panic!("Network with chain_id {} not found", chain_id),
};
network.clone()
});
let pool_contract_address = match Address::from_str(&network.evm_pool_contract_address) {
Ok(address) => address,
Err(_) => panic!("Error parsing pool contract address"),
};
let user_address = match Address::from_str(&user) {
Ok(address) => address,
Err(e) => panic!("Error parsing user address {}", e),
};
let pdt = match pool_deposit_type {
0 => DepositType::Normal,
1 => DepositType::Vault,
_ => return Err("Invalid deposit type".to_string()),
};
let signer = create_icp_signer().await;
let address = signer.address();
let wallet = EthereumWallet::from(signer);
let rpc_service = generate_rpc_service(network.rpc_url.clone());
let config = IcpConfig::new(rpc_service);
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(wallet)
.on_icp(config);
let nonce = provider.get_transaction_count(address).await.unwrap_or(0);
// let provider_chain_id = provider.get_chain_id().await.unwrap_or(chain_id);
let pool_contract = InsurancePool::new(pool_contract_address, provider.clone());
let result = pool_contract
.getUserGenericDeposit(U256::from(pool_id), user_address, pdt.into())
.call()
.await;
let (
user,
amount,
pool_id,
daily_payout,
status,
days_left,
start_date,
exp_date,
accrued_payout,
dt,
adt,
asset,
) = match result {
Ok(value) => value._0,
Err(e) => return Err(format!("Error fetching user deposit detials: {}", e)),
};
let deposit_detail = GenericDepositDetail {
lp: user,
amount,
pool_id,
daily_payout,
status,
days_left,
start_date,
expiry_date: exp_date,
accrued_payout,
pdt: dt,
adt,
asset,
};
if pdt != DepositType::Normal {
return Err("Must be pool withdrawal".to_string());
}
let gas_price = match provider.get_gas_price().await {
Ok(price) => price,
Err(_) => 10000000000,
};
match pool_contract
.setUserDepositToZero(U256::from(pool_id), user_address, pdt.into())
.nonce(nonce)
.gas(200000)
.gas_price(gas_price)
.send()
.await
{
Ok(_) => (),
Err(e) => return Err(format!("Error setting user deposit to zero: {}", e)),
}
let signer = create_icp_signer().await;
match deposit_detail.adt {
0 => {
let hash = match send_eth(
signer,
deposit_detail.amount,
user_address,
network.rpc_url,
chain_id,
)
.await
{
Ok(hash) => hash,
Err(e) => {
return Err(format!("Could not get transaction: {}", e));
}
};
Ok(hash)
}
1 => {
let hash = match send_erc20_token(
signer,
deposit_detail.amount,
user_address,
network.rpc_url,
chain_id,
deposit_detail.asset,
)
.await
{
Ok(hash) => hash,
Err(e) => {
return Err(format!("Could not get transaction: {}", e));
}
};
Ok(hash)
}
_ => {
return Err(format!("Wrong Asset Deposit Type: {}", deposit_detail.adt));
}
}
}
I get no issue when I make the call but when I try to make the send I get this error even when I don’t use the chainId for building the provider or transaction:
dfx canister call icp_backend Poolwithdraw '(3,"0xd9d0Ab6D58Cc17402A47A62fc5D285d620af46D5",0,686868)'
(
variant {
Err = "Error setting user deposit to zero: server returned an error response: error code -32000: invalid chain id"
},
)
I created a simple function just to check if the issue was from my provider or the chainId gotten:
#[update(name = "getNetworkDetails")]
async fn get_network_details(chain_id: u64) -> Result<NetworkDetails, String> {
let nat_chain_id = Nat::from(chain_id);
let network = STATE.with(|state| {
let state = state.borrow();
let network = match state.supported_networks.get(&nat_chain_id) {
Some(network) => network,
None => panic!("Network with chain_id {} not found", chain_id),
};
network.clone()
});
let signer = create_icp_signer().await;
let address = signer.address();
let wallet = EthereumWallet::from(signer);
let rpc_service = generate_rpc_service(network.rpc_url.clone());
let config = IcpConfig::new(rpc_service);
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(wallet)
.on_icp(config);
let nonce = provider.get_transaction_count(address).await.unwrap_or(0);
let gas_price = provider.get_gas_price().await.unwrap_or(0);
let gas = 1000;
let provider_chain_id = provider.get_chain_id().await.unwrap_or(0);
let netdet = NetworkDetails {
chain_id: provider_chain_id,
nonce,
gas,
gas_price,
};
Ok(netdet)
}
but I was successfully retrieve the details:
dfx canister call icp_backend getNetworkDetails '(686868)'
(
variant {
Ok = record {
gas = 1_000 : nat;
chain_id = 686_868 : nat64;
nonce = 0 : nat64;
gas_price = 6_250_000 : nat;
}
},
)
I would appreciate any feedback on this, I am bit confused why this error persists.
Thanks