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

react provider 3 #1450

Merged
merged 5 commits into from
Jul 15, 2024
Merged

react provider 3 #1450

merged 5 commits into from
Jul 15, 2024

Conversation

turbocrime
Copy link
Contributor

@turbocrime turbocrime commented Jul 8, 2024

implements

  • <PenumbraContextProvider> wrapper component
  • sync hook usePenumbra which acquires context from component
  • hooks usePenumbraTransport and usePenumbraService

PenumbraContextProvider verifies presence of an extension before forwarding context, and provides manifest data synchronously.

uses listener interface, so requires prax-wallet/prax#92

check out the readme https://github.com/penumbra-zone/web/blob/09d052686de21d1301c8eca3b712aa2517a0be14/packages/react/README.md

@turbocrime turbocrime requested review from VanishMax and a team July 8, 2024 21:58
Copy link

changeset-bot bot commented Jul 8, 2024

🦋 Changeset detected

Latest commit: 87d69ef

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@penumbra-zone/react Major
@penumbra-zone/client Minor
minifront Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@turbocrime turbocrime changed the title Turbocrime/react wallet 3 react wallet 3 Jul 8, 2024
@turbocrime turbocrime force-pushed the turbocrime/react-wallet-3 branch 3 times, most recently from d04ddce to d46337b Compare July 8, 2024 23:16
@turbocrime turbocrime requested a review from TalDerei July 9, 2024 16:16
@turbocrime
Copy link
Contributor Author

cc @grod220

@turbocrime turbocrime changed the title react wallet 3 react provider 3 Jul 11, 2024
@turbocrime turbocrime force-pushed the turbocrime/react-wallet-3 branch 4 times, most recently from 0670bce to fb9404f Compare July 12, 2024 05:56
Copy link
Contributor

@jessepinho jessepinho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic work! This is really great. I'm excited to see it in use.

I left a lot of comments, but they're almost all very minor things. Feel free to self-merge after addressing.

packages/react/README.md Show resolved Hide resolved
packages/react/README.md Outdated Show resolved Hide resolved

## Possible provider states

On the bare Penumbra injection, there is only a boolean/undefined
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if we should explain what the "Penumbra injection" is? i.e., that it's an object injected by the extension (and perhaps link to the TypeScript interface — I forget where it is)?

Again, feel free to ignore if this is already obvious to web3/dapp devs

packages/react/README.md Outdated Show resolved Hide resolved
packages/react/README.md Outdated Show resolved Hide resolved
packages/react/src/manifest.ts Outdated Show resolved Hide resolved
packages/react/src/manifest.ts Outdated Show resolved Hide resolved
packages/react/src/hooks/use-penumbra-transport.ts Outdated Show resolved Hide resolved
packages/react/src/hooks/use-penumbra-transport.ts Outdated Show resolved Hide resolved
}
}, [failure, penumbra, port, resolvePort, rejectPort, state]);

return transport;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the transport automatically queue up requests until the connection is ready? Or how is the queueing handled?

Copy link
Contributor Author

@turbocrime turbocrime Jul 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

behavior is in https://github.com/penumbra-zone/web/blob/main/packages/transport-dom/src/create.ts

each request awaits a shared connection attempt as part of its lifecycle, involving the getPort option. the connection respects the timeout configuration passed into the transport.

the difference between the two methods is that

  • usePenumbraTransportSync will create a transport, and the transport will await a port with its timeout clock beginning at the first request.
  • usePenumbraTransport will promise a transport, but won't init the transport until a port appears in context. the transport will spend no timeout clock, but if the port never appears the wait may be indefinite.

packages/react/src/util.ts Outdated Show resolved Hide resolved
packages/react/src/manifest.ts Outdated Show resolved Hide resolved
}
}, [makeApprovalRequest, providerState, providerInjection?.connect, manifest, failure]);

const createdContext: PenumbraContext = useMemo(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to have context? It would be nice if the consumer wouldn't need to wrap their app with a provider. Especially since it appears that this initiates actions automatically. Doesn't all state live within the injection now? Aka, can't we just rely upon a usePenumbra() hook without a provider?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the developer just wants to grab a client wherever they are, @penumbra-zone/client already provides methods for that.

import { createPenumbraClient } from '@penumbra-zone/client/create';
import { ViewService } from '@penumbra-zone/protobuf';

// this goes through the same connection process
const viewClient = createPenumbraClient(ViewService, someOptionalOrigin);

export const ChainIdComponent = () => {
    const [chainId, setChainId] = useState<string>();
    useEffect(() => { // or useQuery or whatever
        const { parameters } = await viewClient.appParameters({});
        return setChainId(parameters?.chainId);
    });
    return <div>{chainId}</div>
};

i agree that a dedicated react package isn't much of a value-add. at best this may help prevent a naive developer from constructing/deconstructing a transport and client for every component on every rerender.

yes the injection tracks its own detailed connection state including called methods, so now the caller doesn't have to remember what they've done. but all that it delivers is a MessagePort. the page still needs to construct its own transport etc.

and if the goal is to share state among components, context providers are the way to achieve shared state in react, unless we expect users to prop-drill the clients everywhere. and it's convenient to throw in things like prefetched manifest data at this level.

@turbocrime turbocrime merged commit 72d83ea into main Jul 15, 2024
6 checks passed
@turbocrime turbocrime deleted the turbocrime/react-wallet-3 branch July 15, 2024 08:55
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

Successfully merging this pull request may close these issues.

4 participants