Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AccountInterface methods should be async #11078

Open
twt-- opened this issue Jan 6, 2025 · 10 comments
Open

AccountInterface methods should be async #11078

twt-- opened this issue Jan 6, 2025 · 10 comments

Comments

@twt--
Copy link
Contributor

twt-- commented Jan 6, 2025

I am attempting to build a @aztec/aztec.js Wallet that uses a remote implementation on a separate web site for all of its functionality.
The AccountInterface method definitions are all synchronous, unlike everything else in the wallet/account interfaces which are async. Can you switch AccountInterface methods to be async?

@olehmisar
Copy link
Contributor

getChainId and getVersion should be turned async but not getAddress and getCompleteAddress. The address should be fixed per account (even if it's an RPC account). Look at ethers for example:

const provider = new ethers.JsonRpcProvider(...);
const signer = await provider.getSigner();
signer.address // type: string

The reason is that the address of the account should be fixed to avoid problems with user switching accounts. I.e., it should NOT be possible to have this code fail:

const signer = await provider.getSigner();
const currentAddress = signer.address;
// user switches accounts in wallet UI
await sleep(10_000);
assert(signer.address === currentAddress); // should never fail

@Maddiaa0
Copy link
Member

Maddiaa0 commented Jan 7, 2025

@twt-- do you need all methods or are getChainId and getVersion enough to cover your use cases?

@twt--
Copy link
Contributor Author

twt-- commented Jan 7, 2025

I would prefer everything be async - having it consistent for everything in that interface would be nice, and that would also mean i don't have to throw an error if i haven't managed to cache the value yet!

to @olehmisar's point, my use case is a bit different, but i don't necessarily disagree... I want to prompt the user to ask if they are willing to share the address, and if not, throw an error (or send a fake address), and after that it will always resolve to the same value. Having everything async would make it a lot easier to handle.

thanks!

@olehmisar
Copy link
Contributor

olehmisar commented Jan 7, 2025

I want to prompt the user to ask if they are willing to share the address, and if not, throw an error (or send a fake address)

@twt-- it should happen when you request the account (await provider.getSigner()). Once you get the account, the address should be known already.

@twt--
Copy link
Contributor Author

twt-- commented Jan 7, 2025

@olehmisar I get what you're saying, but it also sounds like you're making different assumptions about the intent of the interfaces/types than I am. AccountInterface doesn't define getAddress() as a readonly, which I'm interpreting to mean that I can have a bit more freedom with it (maybe return a different value based on context, user choice, etc). My version 1 is going to have to always resolve to the same value, but I don't intend for that to be the final state

@olehmisar
Copy link
Contributor

olehmisar commented Jan 7, 2025

@twt-- I am making a point that getAddress() must always return the same value. For different accounts, you should have different AccountInterface instances

@twt--
Copy link
Contributor Author

twt-- commented Jan 7, 2025

@twt-- I am making a point that getAddress() must always return the same value. For different accounts, you should have different AccountInterface instances

Why? I was planning on having a Wallet type that could service >1 address. Contrast that with the AccountWallet that is bound to a single account, and the SignerlessWallet that doesn't have an account associated with it.

Perhaps this speaks to a larger issue: maybe the Wallet type is too strict in its definition? Or maybe it needs to be more strict to make it clear what its intended usage is? I was thinking of it more like ethereum web3js/ethers conventions where an account/signer is a single address, but a wallet can represent a collection of them.

@olehmisar
Copy link
Contributor

@twt-- it's to make code less error-prone. One instance of AccountWallet - one address. Developers will not get unexpected changes to the address if user switches/disconnects accounts in wallet UI. I am generally against dynamic addresses unless you provide a use case where it would be beneficial to have an instance where .getAddress() returns different addresses at different times.

Also, looks like the ecosystem as a whole is aligned with my vision (ethers, viem). So, unless there is a reason to move away from the standard, I wouldn't do it

@twt--
Copy link
Contributor Author

twt-- commented Jan 7, 2025

One instance of AccountWallet - one address.

Right, one instance of AccountWallet, one address. But I am trying to make a Wallet, not an AccountWallet. The Wallet should be usable (per aztec examples) even when getAddress() throws.

Also, looks like the ecosystem as a whole is aligned with my vision (ethers, viem). So, unless there is a reason to move away from the standard, I wouldn't do it

I disagree, but I think this is a jargon/naming problem, not an actual disagreement. Viem supports the concept of a Wallet without an account, and also has async getAddress() https://github.com/wevm/viem/blob/53552a3fd8f8996d2cc357b7b0be9bcb04ae741a/src/account-abstraction/accounts/types.ts#L49 and ethersjs uses async getAddress() for Signers https://github.com/ethers-io/ethers.js/blob/22c081e1cd617b43d267fd4b29cd92ada5fc7e43/src.ts/providers/signer.ts#L37

The single, static address is an add-on, not a defining characteristic, of a more generic "wallet". In Viem the static address add-on is called an Account and in ethersjs it's a Wallet.
The Aztec libraries don't really separate out these separate concepts well, so it can lead to confusion, so perhaps a more "correct" solution would be to refactor the Aztec "Account" and "Wallet" types to have a more clear separation and purpose. But until then, please give me async methods for everything :)

@olehmisar
Copy link
Contributor

Let's get terminology defined:

  • account - an instance that has a single address
  • wallet or wallet client - a collection of accounts

it's fine for wallets to have multiple addresses but not for accounts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants