Skip to content

Commit

Permalink
feat: add custom events (#278)
Browse files Browse the repository at this point in the history
* feat(server): Add sendMessage method to RPC Node

* chore(changeset): Add changeset

* feat(core): Add type support for events

* chore(core): Adding changeset

* feat(server): Adding support for event handlers

* Update event handler usage

* chore: format files

* Apply suggestions from code review

* chore: changesets

---------

Co-authored-by: Kant <[email protected]>
  • Loading branch information
ComradeAERGO and Justkant authored Dec 12, 2023
1 parent 51b9152 commit e7e609e
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/long-onions-drum.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/wallet-api-core": minor
---

Adding type support for custom events
6 changes: 6 additions & 0 deletions .changeset/spotty-otters-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@ledgerhq/wallet-api-client-react": minor
"@ledgerhq/wallet-api-client": minor
---

Support custom events in the wallet-api client and client-react
5 changes: 5 additions & 0 deletions .changeset/warm-mails-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ledgerhq/wallet-api-server": minor
---

Adding sendMessage to the server to push messages to live apps with permissions check
21 changes: 14 additions & 7 deletions packages/client-react/src/components/WalletAPIProvider/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { WalletAPIClient } from "@ledgerhq/wallet-api-client";
import { useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";
import { WalletAPIProviderContext, initialContextValue } from "./context";
import type {
WalletAPIProviderContextState,
Expand All @@ -14,25 +14,32 @@ export function WalletAPIProvider({
transport,
logger,
getCustomModule,
eventHandlers,
}: WalletAPIProviderProps) {
const [client, setClient] = useState<WalletAPIClient>();
const [state, setState] = useState<WalletAPIProviderContextState>(
initialContextValue.state,
);

useEffect(() => {
const walletApiClient = new WalletAPIClient(
const client = useRef<WalletAPIClient>();

if (client.current === undefined) {
client.current = new WalletAPIClient(
transport,
logger,
getCustomModule,
eventHandlers,
);
}

setClient(walletApiClient);
}, [getCustomModule, logger, transport]);
useEffect(() => {
if (eventHandlers) {
client.current?.setEventHandlers(eventHandlers);
}
}, [eventHandlers]);

const value = useMemo<WalletAPIProviderContextValue>(
() => ({
client,
client: client.current,
state,
setState,
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {
Account,
AnyCustomGetter,
Currency,
EventHandlers,
Logger,
Transport,
WalletAPIClient,
Expand All @@ -20,6 +21,7 @@ export type WalletAPIProviderProps = PropsWithChildren<{
transport: Transport;
logger?: Logger;
getCustomModule?: AnyCustomGetter;
eventHandlers?: EventHandlers;
}>;

export type WalletAPIProviderContextState = {
Expand Down
12 changes: 10 additions & 2 deletions packages/client/src/WalletAPIClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
Logger,
Promisable,
RpcError,
RpcErrorCode,
RpcNode,
Expand All @@ -20,7 +21,9 @@ import { WalletModule } from "./modules/Wallet";

export const defaultLogger = new Logger("Wallet-API-Client");

export type RPCHandler<Result> = (request: RpcRequest) => Promise<Result>;
export type RPCHandler<Result> = (request: RpcRequest) => Promisable<Result>;

export type EventHandlers = Record<`event.${string}`, RPCHandler<unknown>>;

// temporary
const requestHandlers = {
Expand Down Expand Up @@ -101,8 +104,9 @@ export class WalletAPIClient<
transport: Transport,
logger = defaultLogger,
getCustomModule?: CustomGetter,
eventHandlers: EventHandlers = {},
) {
super(transport, requestHandlers);
super(transport, { ...requestHandlers, ...eventHandlers });
this.logger = logger;
this.account = new AccountModule(this);
this.bitcoin = new BitcoinModule(this);
Expand All @@ -118,6 +122,10 @@ export class WalletAPIClient<
) as typeof this.custom;
}

public setEventHandlers(eventHandlers: EventHandlers) {
this.requestHandlers = { ...requestHandlers, ...eventHandlers };
}

protected onRequest(request: RpcRequest) {
this.logger.log(request.method);
const handler =
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/spec/rpcHandlers/AppHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export type AppHandlers = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type UnknownCustomEvent = Record<`event.${string}`, any>;

export type AppHandlers<GenericCustomEvent = UnknownCustomEvent> = {
"event.account.updated": undefined;
};
} & GenericCustomEvent;
16 changes: 16 additions & 0 deletions packages/server/src/WalletAPIServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export { customWrapper } from "./internalHandlers";

export const defaultLogger = new Logger("Wallet-API-Server");

type MethodParams<T> = T extends (...args: infer P) => unknown ? P[0] : T;
type MethodParamsIfExists<T, S> = S extends keyof T ? MethodParams<T[S]> : S;

export class WalletAPIServer extends RpcNode<
typeof internalHandlers,
AppHandlers
Expand Down Expand Up @@ -90,6 +93,19 @@ export class WalletAPIServer extends RpcNode<
this.requestHandlers = { ...internalHandlers, ...customHandlers };
}

public sendMessage(
method: keyof AppHandlers,
params: MethodParamsIfExists<AppHandlers, keyof AppHandlers>,
) {
const allowedMethodIds = new Set(this.permissions.methodIds$.getValue());

if (!allowedMethodIds.has(method)) {
throw new ServerError(createPermissionDenied(method));
}

return this.notify(method, params);
}

protected async onRequest(
request: RpcRequest<string, unknown>,
): Promise<unknown> {
Expand Down

2 comments on commit e7e609e

@vercel
Copy link

@vercel vercel bot commented on e7e609e Dec 12, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

wallet-api – ./apps/docs

wallet-api-ledgerhq.vercel.app
wallet.api.live.ledger.com
wallet-api-git-main-ledgerhq.vercel.app

@vercel
Copy link

@vercel vercel bot commented on e7e609e Dec 12, 2023

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

wallet-api-wallet-api-tools – ./apps/wallet-api-tools

wallet-api-wallet-api-tools.vercel.app
wallet-api-wallet-api-tools-git-main-ledgerhq.vercel.app
wallet-api-wallet-api-tools-ledgerhq.vercel.app

Please sign in to comment.