penumbra-zone / web

Apache License 2.0
14 stars 16 forks source link

Create Interface for extension-specific methods #825

Closed grod220 closed 1 month ago

grod220 commented 7 months ago

We have an objective that eventually other wallets (leap, keplr, etc) will be able to serve as a Penumbra wallet. We already have a few issues with this in mind (https://github.com/penumbra-zone/web/issues/340, https://github.com/penumbra-zone/web/issues/341).

At the moment, web apps have a pretty simple set of things to utilize a penumbra wallet:

// rpc methods
import { createPraxClient } from '@penumbra-zone/client';
export const viewClient = createPraxClient(ViewService);

// extension-specific methods
import { requestPraxConnection, throwIfPraxNotAvailable, throwIfPraxNotInstalled } from '@penumbra-zone/client';
throwIfPraxNotAvailable();
await throwIfPraxNotInstalled();
await requestPraxConnection();

These rely upon the extension (ours or others) to implement a few things available globally:

All of this we handle for ourselves in extension/src/content-scripts. Side note: I'm not quite sure what would happen if two Penumbra-compatible wallets were installed.

Proposal

Create an interface to define the expectations for the extension serving as a Penumbra wallet. Here's an example interface:

interface PenumbraWallet {
  requestPraxConnection(): Promise<void>;
  isPraxConnected(): boolean;
  isPraxInstalled(): boolean;
  throwIfPraxNotInstalled(): void;
  throwIfPraxNotConnected(): void;
  createPraxClient<T extends ServiceType>(serviceType: T): PromiseClient<T>;
}

And then perhaps the web app is required to pass it in themselves

import { LeapPenumbraWallet } from 'leap';
import { Prax } from 'prax';

import { createClient } from '@penumbra-zone/client';

const leap = createClient(LeapPenumbraWallet)
export const leapViewClient = leap(ViewService);

const prax = createClient(Prax)
export const praxViewClient = prax(ViewService);

Another benefit of the interface, is that each method's doc string could inform the extension developer where it needs to go (content scripts, service worker, etc).

turbocrime commented 7 months ago

the PenumbraProvider interface is already designed so that all interactions with it can be the same, regradless of the software behind it. all that the prax-specific methods actually do is, they grab the penumbraprovider object identified by the prax id in the global.

at some point, generic equivalent methods existed, but must have been deleted from a PR before merge

currently, our client package ignores non-prax providers, if they are present.