Add a standard wallet interface #1467
Replies: 19 comments 16 replies
-
It seems like the Discord discussion is pretty dated, so I'll offer some thoughts on this here, also to get this discussion going again. I like the proposed interface, but I'd like to suggest an additional generic signing method that could actually encapsulate the other two and also be used for arbitrary signing purposes: interface Wallet {
sign: (arbitraryB64: string) => Promise<string>;
} (Internally, an implementation could have something like Also, should we discuss the trade-off between allowing encoded XDR passed in vs. the actual XDR object? I think encoded is fine, but we need to be sure to communicate to the implementers that they should NOT trust the input string to be well-formed or even necessarily represent an |
Beta Was this translation helpful? Give feedback.
-
If we are adding extra methods, I would like to include an extra one:
I also prefer separated functions instead of a single generic function because it's easier for a wallet implementing something unique that they only have (like albedo with its messages signing features) and dapp developers can easily decide if they want to support that or not by just adding that extra function. But that being said the more "features" we add (sighAuthEntry included) the more we will reduce the support for non stellar native wallets like those using wallet connect (Lobstr), hardware wallets, airgapped wallets, etc so at the end of the day devs will still need to handle different interfaces no matter what |
Beta Was this translation helpful? Give feedback.
-
I have mixed feelings about such an interface. It's simple and unified, and that's great. On the other hand, I really don't like the idea of returning plain strings from the method calls. Can we change the interface to return objects (with the predefined set of fields) instead of strings? For example, {
getPublicKey: () => Promise<{publicKey: string}>,
signTransaction: (xdr: string) => Promise<{signedXdr: string}>,
signAuthEntry: (authEntryXdr: string) => Promise<{signedAuthEntry: string}>,
signMessage: (message: string) => Promise<{signedMessage: string}>
} Motivation:
|
Beta Was this translation helpful? Give feedback.
-
Aside from the successful result standardization, we also have to define the standardized error output format. Albedo client lib defines several standard errors for different scenarios. I'm not advocating for sticking with our vendor format, but it would be nice to have a few basic standard errors defined in a minimalistic format, e.g. {
message: string, // general description message returned to the client app
code: number, // unique error code
ext: Array<string> // optional extended details
} Proposed standard errors: {
unhandled: { // internal wallet error, likely caused by the wallet logic itself
message: 'Unhandled error occurred.',
code: -1
},
external: { // external service (Horizon, RPC, etc.) returned an error
message: 'External error occurred.',
code: -2,
ext: ['Operation 2: Invalid "amount" value.', "Operation 5: Asset issuer is required."] // malformed tx error example
},
invalid: { // client app request is invalid (wrong parameters, invalid transaction XDR, etc.)
message: 'Request is invalid.',
code: -3,
ext: ['Invalid transaction XDR'] // example error
},
rejected: { // user rejected the request, client app should not try to retry the request
message: 'Rejected by the user.',
code: -4
}
} |
Beta Was this translation helpful? Give feedback.
-
One more thing to consider. Multi-account wallets in some cases need an option to identify the specific account to utilize for the request. However, if the user interacted with the app from two different accounts (for example, traded with DEX from two different accounts), I have a problem. The obvious solution is to show the list (or dropdown) of all wallet accounts with pre-selected the most recent account. Yet allowing an app to request signature for a specific account makes the UX much more streamlined on the wallet side, decreasing the possibility of a human error and saving a few clicks. How about adding a second optional parameter |
Beta Was this translation helpful? Give feedback.
-
Lastly, kudos to @earrietadev for maintaining the StellarWalletsKit lib that allows client apps to avoid complexity of dealing with different wallets by abstracting the interface. |
Beta Was this translation helpful? Give feedback.
-
One thing I notice about the proposed API is that it doesn't expose any concept of a network, or a network passphrase. If a web app knew that it was only deployed to testnet or pubnet, how would it communicate the supported network, or see what network the wallet supported? |
Beta Was this translation helpful? Give feedback.
-
We could draw some inspiration from Ethereum as well. EIP-1193 was introduced to standardize a dapp connecting with different wallets from different providers - which is something I believe this proposal is trying to achieve as well EIP-6963 was introduced to let a dapp discover when a browser wallet was installed, which becomes important when a user has multiple wallets installed |
Beta Was this translation helpful? Give feedback.
-
@piyalbasu I'd like to suggest some interface additions. It could be for next iteration of this SEP.
|
Beta Was this translation helpful? Give feedback.
-
I've incorporated changes we've agreed to here as well as those I've collected on Discord on this PR: #1478 |
Beta Was this translation helpful? Give feedback.
-
Just wanted bring something else to the table that it might be good to include: a way to import an asset. Since we are promoting the usage of assets list, something I have used a lot when using EVM wallets is clicking on a protocol's site and add the asset to my wallet (basically it adds the asset contract ID). This is good for users that might be using a protocol that is not that popular yet or for custom assets that will probably be outside of the lists (like pool shares) |
Beta Was this translation helpful? Give feedback.
-
I'd like to suggest an Occasionally wallets shutdown for various reasons (no more run way, key member departure, so on and so forth). Users could migrate off the wallet by using seedphrase, but in all instances, this is too challenging for all the users. If wallets consistently have the ability to import account by private key, the wallet about to shutdown can push a feature to export keys and import to other wallets. It makes migration off a wallet less choatic. In general be able to import by key is useful from dev perspective too. |
Beta Was this translation helpful? Give feedback.
-
@earrietadev and @orbitlens we're planning to finalize this proposed standard during the Stellar Protocol Meeting next week on Thursday, June 6th at 1:00 PM PDT. We'd love your support and participation in the meeting. |
Beta Was this translation helpful? Give feedback.
-
The corresponding proposal was put to vote on 6/6/24. The votes represent ecosystem sentiment and can be used by the author to determine next steps The voting card is on testnet deployment of Soroban Governor (link) Here is the snapshot of the final count: |
Beta Was this translation helpful? Give feedback.
-
I'm curious which wallets are planning to implement or have already implemented this standard? @piyalbasu @earrietadev @orbitlens |
Beta Was this translation helpful? Give feedback.
-
Do we really need Someone mentioned earlier that it can be useful for multisig. However, to my mind, |
Beta Was this translation helpful? Give feedback.
-
How Do we want to make sure that a user really owns the account he authenticating with? I mean, someone can easily clone the open-source wallet repo, and slightly change the code to impersonate some other account owner, returning a public key from the account they doesn't own (e.g., one of SDF's accounts). We have two options: either sign and return some challenge in this method, similar to the |
Beta Was this translation helpful? Give feedback.
-
We probably need to standardize the implementation of the Our algorithm: function signMessage(message, keypair) {
const publicKey = keypair.publicKey()
const signedMessage = keypair.publicKey()+':'+message //protection from spoofing
const messageHash = sha256(signedMessage)
const signature = keypair.sign(messageHash).toString('hex')
return {publicKey, signature, signedMessage}
} From my point of view, the |
Beta Was this translation helpful? Give feedback.
-
Regarding the As I see it, the network selection during the transaction signing should be controlled by the dapp UI. A user should see the requested network in the wallet interface during the request authorization, but shouldn't be able to change it (again, to avoid weird glitches). The network, selected by the user in the wallet interface prior to the transaction signing request must not affect the request received from the dapp. If the network was not specified in the request, the wallet should assume that the dapp uses Stellar Pubnet by default. |
Beta Was this translation helpful? Give feedback.
-
Background
Many browser wallets expose an API so dapps can interact with a user's wallet. This allows a dapp to ask a wallet to do things like transmit a public key or sign an XDR.
Problem
Right now wallets all implement this API differently, which can make building a dapp or an SDK difficult; a dev must account for all these differences and manually integrate different wallet API's in order to support as many wallets as possible. This will conceivably become more complex as more wallets enter the ecosystem.
Proposal
The ecosystem agrees to a standard wallet API interface to make wallet integration easier. If all wallets agree to a minimum standard interface, a dapp or SDK developer could reliably infer what methods will be supported and what the function signature will be.
Example API interface:
Relevant discord conversation: https://discord.com/channels/897514728459468821/1019346446014759013/1206810627377467413
Beta Was this translation helpful? Give feedback.
All reactions