Skip to content

Commit

Permalink
readme
Browse files Browse the repository at this point in the history
  • Loading branch information
turbocrime committed Jun 25, 2024
1 parent 4fd8a1f commit cc0465a
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 18 deletions.
112 changes: 112 additions & 0 deletions packages/client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# `@penumbra-zone/client`

This package contains interfaces, types, and some helpers for using the page API to Penumbra providers.

**To use this package, you need to [enable the Buf Schema Registry](https://buf.build/docs/bsr/generated-sdks/npm):**

```sh
echo "@buf:registry=https://buf.build/gen/npm/v1/" >> .npmrc
```

## A simple example

```ts
import { bech32mAddress } from '@penumbra-zone/bech32m';
import { createPenumbraClient } from '@penumbra-zone/client/create';
import { ViewService, SctService } from '@penumbra-zone/protobuf';

// This may connect to any available injected provider.
const viewClient = createPenumbraClient(ViewService);

// Or, you might prefer a specific provider.
const praxViewClient = createPenumbraClient(
ViewService,
'chrome-extension://lkpmkhpnhknhmibgnmmhdhgdilepfghe',
);

const { address } = await praxViewClient.addressByIndex({});
console.log(bech32mAddress(address));
```

## React use

It's likely you want to use this client in your webapp, and there's a good
chance you're using React or another tanstacklike. Penumbra providers use
`@connectrpc` tooling, so these clients are supported by `@connectrpc/query` and
`@tanstack/react-query`.

After using `createPenumbraChannelTransport` from `@penumbra-zone/client/create`
and `TransportProvider` from `@connectrpc/query` in a parent component, you can
use convenient React idioms.

You can see a full example of this at https://github.com/penumbra-zone/nextjs-penumbra-client-example

### A parent component

```ts
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { syncCreatePenumbraChannelTransport } from "@penumbra-zone/client/create";
import { TransportProvider } from "@connectrpc/connect-query";
import { useMemo } from "react";

const queryClient = new QueryClient();

export const PenumbraQueryProvider = ({
providerOrigin,
children,
}: {
providerOrigin: string;
children: React.ReactNode;
}) => {
const penumbraTransport = useMemo(
() => syncCreatePenumbraChannelTransport(providerOrigin),
[providerOrigin],
);
return (
<TransportProvider transport={penumbraTransport}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</TransportProvider>
);
};
```

### A querying component

```ts
"use client";
import { addressByIndex } from "@buf/penumbra-zone_penumbra.connectrpc_query-es/penumbra/view/v1/view-ViewService_connectquery";
import { bech32mAddress } from "@penumbra-zone/bech32m/penumbra";
import { useQuery } from "@connectrpc/connect-query";

export const PenumbraAddress = ({ account }: { account?: number }) => {
const { data } = useQuery(addressByIndex, { addressIndex: { account } });
return (
data?.address && (
<span className="address">{bech32mAddress(data.address)}</span>
)
);
};
```

## You could access the providers directly, without importing this package.

This example is javascript.

```js
import { createChannelTransport } from '@penumbra-zone/transport-dom';
import { createPromiseClient } from '@connectrpc/connect';
import { jsonOptions, ViewService } from '@penumbra-zone/protobuf';

// naively get first available provider
const provider = Object.values(window[Symbol.for('penumbra')])[0];
void provider.request();

// create a client
const viewClient = createPromiseClient(
ViewService,
createChannelTransport({ jsonOptions, getPort: provider.connect }),
);

const { catchingUp, fullSyncHeight } = viewClient.status({});
```
21 changes: 3 additions & 18 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const PenumbraSymbol = Symbol.for('penumbra');
* fetching the provider manifest. Provider details such as name, version,
* website, brief descriptive text, and icons should be available in the
* manifest.
*
*
* Presently clients may expect the manifest is a chrome extension manifest v3.
* @see https://developer.chrome.com/docs/extensions/reference/manifest
*
Expand All @@ -28,23 +28,8 @@ export const PenumbraSymbol = Symbol.for('penumbra');
* provider. It is convenient to provide the `connect` method as the `getPort`
* option for `createChannelTransport` from `@penumbra-zone/transport-dom`, or
* use the helpers available in `@penumbra-zone/client/create`.
*
```js
import { jsonOptions } from '@penumbra-zone/protobuf';
import { createChannelTransport } from '@penumbra-zone/transport-dom';
// naively get first available provider
const provider = Object.values(window[Symbol.for('penumbra')])[0];
void provider.request();
// establish a transport
const transport = createChannelTransport({ jsonOptions, getPort: provider.connect });
// export function to create client
export const createPenumbraClient = serviceType => createPromiseClient(serviceType, transport);
```
*
*/
*
*/
export interface PenumbraInjection {
/** Call when creating a channel transport to this provider. Returns a promise
* that may resolve with an active `MessagePort`. */
Expand Down

0 comments on commit cc0465a

Please sign in to comment.