ethers-rs
ethers-rs copied to clipboard
Difficulty sharing a signer
In the code snipper below, I need to use a signer for two purposes: either to sign an off-chain payload, or to sign an on-chain transaction.
The current API makes that difficult (impossible?) as far as I know, without creating two Contract instances. The things I tried are:
- Cloning the signer (Ledger is not clonable)
- Calling
contract.signer()ormiddleware.signer()etc. (no such method) - Keeping a single
Contract, and then using something likecontract.connect(signer)when the signer needs to be used with the contract. (doesn't work)
I think either of the above could be a solution, otherwise being able to use a signer by reference would be another possibility. What I really expected to work which didn't was (3).
async fn anchor<P: 'static + JsonRpcClient + Clone, S: 'static + Signer>(
opts: Options,
provider: Provider<P>,
signer: S,
) -> anyhow::Result<()> {
let abi: Abi = serde_json::from_str(ORG_ABI)?;
// Read-only contract
let contract = Contract::new(opts.org, abi.clone(), provider.clone());
let org_owner: Address = contract.method("owner", ())?.call().await?;
let safe = ...;
let id = ...;
let tag = ...;
let hash = ...;
if let Some(safe) = safe {
let call = contract.method::<_, ()>("anchor", (id, tag, hash))?;
let data = call.calldata().unwrap();
// Signer is required here to produce a signature payload.
anchor_safe(opts.org, data, &safe, &signer).await
} else {
// We have to re-create the contract here with a signer instead of
// provider, to submit a transaction :(
let signer = SignerMiddleware::new(provider, signer);
let contract = Contract::new(opts.org, abi, signer);
let call = contract.method::<_, ()>("anchor", (id, tag, hash))?;
anchor_eoa(call).await
}
}