anza-xyz / wallet-standard

Solana extensions to the Wallet Standard.
Apache License 2.0
79 stars 42 forks source link

Are there any docs on writing a wallet with a Wallet Standard compatible API? #17

Closed mikemaccana closed 1 year ago

mikemaccana commented 1 year ago

Hi @jordansexton , the docs mention:

This guide is for wallets that want to implement the Wallet Standard. This can be done in essentially two ways.

A. Write a wallet with a Wallet Standard compatible API. B. Wrap your existing API with a Wallet Standard compatible API.

These methods are similar, but since wallets that exist today already have their own APIs, we'll focus on the latter.

Are there any docs on A? I have an existing wallet (connecting to Solana, handling token transfers, transaction history, getting NFT metadata, etc) and simply want to:

mikemaccana commented 1 year ago

I guess something like:

Your content script should add an object with the following methods:

export interface SomeWalletEvent {
  connect(...args: unknown[]): unknown;
  disconnect(...args: unknown[]): unknown;
  accountChanged(...args: unknown[]): unknown;
}

export interface SomeWalletEventEmitter {
  on<E extends keyof SomeWalletEvent >(event: E, listener: SomeWalletEvent [E], context?: any): void;
  off<E extends keyof SomeWalletEvent >(event: E, listener: SomeWalletEvent [E], context?: any): void;
}

export interface SomeWallet extends SomeWalletEventEmitter {
  publicKey: PublicKey | null;
  connect(options?: { onlyIfTrusted?: boolean }): Promise<{ publicKey: PublicKey }>;
  disconnect(): Promise<void>;
  signAndSendTransaction<T extends Transaction | VersionedTransaction>(
    transaction: T,
    options?: SendOptions
  ): Promise<{ signature: TransactionSignature }>;
  signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T>;
  signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]>;
  signMessage(message: Uint8Array): Promise<{ signature: Uint8Array }>;
}

Then some docs about the intended use for each of these. Right now I can stumble though the TS files - so let me know if that's what I should be doing - but if there's some docs I'm missing I'd love to read them - thanks! ❤️

mikemaccana commented 1 year ago

I think I've managed to work it out - the thing called GhostWallet is what I need to create, the thing called ghost (that is consumed by the GhostWallet constructor) is the actual implementation of wallet functions, which I can substitute for my own. The code is a little odd and the term 'wallet' is very much overloaded, but I can figure it out. If there are docs here please do let me know though!

jordaaash commented 1 year ago

Yes, that's right. ghost is the equivalent of window.solana. "Wallet" (definitely overloaded) here is a Standard Wallet as defined by https://wallet-standard.github.io/wallet-standard/modules/_wallet_standard_base.html

Most wallets already have some preexisting (usually Phantom-like) API, so wrapping this API makes sense for them to get Wallet Standard support quickly. However, you can take advantage of the full range of features in the Standard, especially multiple account/network handling, if you use it directly.

Here's an incomplete example of a headless (no extension) Wallet that implements it directly: https://github.com/wallet-standard/wallet-standard/blob/master/packages/example/wallets/src/solanaWallet.ts

There isn't a working example of a browser extension that does this, but here's a non-working one: https://github.com/wallet-standard/wallet-standard/blob/master/packages/example/extension/src/content/multiChainWallet.ts

mikemaccana commented 1 year ago

Awesome, the first link in particular helps a lot!