-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
eip6963 proxying connect flow (#2090)
Co-authored-by: Jhonatan Gonzalez <[email protected]>
- Loading branch information
1 parent
5fe632a
commit 5c06f0e
Showing
6 changed files
with
202 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
packages/checkout/widgets-lib/src/widgets/checkout/hooks/useEip6963Relayer.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { useCallback, useEffect } from 'react'; | ||
import { EIP6963ProviderDetail, PostMessageHandlerEventType } from '@imtbl/checkout-sdk'; | ||
import { useCheckoutContext } from '../context/CheckoutContextProvider'; | ||
|
||
export function useEip6963Relayer() { | ||
const [checkoutState] = useCheckoutContext(); | ||
const { postMessageHandler } = checkoutState; | ||
|
||
const onAnnounce = useCallback((event: CustomEvent<EIP6963ProviderDetail>) => { | ||
postMessageHandler?.send(PostMessageHandlerEventType.EIP_6963_EVENT, { | ||
message: 'eip6963:announceProvider', | ||
info: event.detail.info, | ||
}); | ||
}, [postMessageHandler]); | ||
|
||
useEffect( | ||
() => { | ||
if (!postMessageHandler) return () => { }; | ||
|
||
window.addEventListener('eip6963:announceProvider', onAnnounce as any); | ||
|
||
return () => window.removeEventListener('eip6963:announceProvider', onAnnounce as any); | ||
}, | ||
[postMessageHandler, onAnnounce], | ||
); | ||
|
||
const onRequest = useCallback((payload: any) => { | ||
if (payload.message !== 'eip6963:requestProvider') return; | ||
|
||
window.dispatchEvent(new CustomEvent('eip6963:requestProvider')); | ||
}, [postMessageHandler]); | ||
|
||
useEffect(() => { | ||
if (!postMessageHandler) return; | ||
|
||
postMessageHandler.subscribe((message) => { | ||
if (message.type === PostMessageHandlerEventType.EIP_6963_EVENT) { | ||
onRequest(message.payload); | ||
} | ||
}); | ||
}, [postMessageHandler, onRequest]); | ||
} |
121 changes: 121 additions & 0 deletions
121
packages/checkout/widgets-lib/src/widgets/checkout/hooks/useProviderRelay.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import { useCallback, useEffect } from 'react'; | ||
import { | ||
EIP6963ProviderInfo, | ||
PostMessageData, | ||
PostMessageHandlerEventType, | ||
} from '@imtbl/checkout-sdk'; | ||
import { Web3Provider } from '@ethersproject/providers'; | ||
import { useCheckoutContext } from '../context/CheckoutContextProvider'; | ||
import { CheckoutActions } from '../context/CheckoutContext'; | ||
|
||
// TODO these types should be in sync with Checkout App | ||
type MessageId = number | string | null; | ||
|
||
interface JsonRpcRequestMessage<TParams = any> { | ||
type: 'dapp'; | ||
jsonrpc: '2.0'; | ||
// Optional in the request. | ||
id?: MessageId; | ||
method: string; | ||
params?: TParams; | ||
} | ||
|
||
type ProviderRelayPayload = { | ||
jsonRpcRequestMessage: JsonRpcRequestMessage; | ||
eip6963Info: EIP6963ProviderInfo; | ||
}; | ||
|
||
export function useProviderRelay() { | ||
const [{ checkout, postMessageHandler, provider }, checkoutDispatch] = useCheckoutContext(); | ||
|
||
/** | ||
* Execute a request using the provider | ||
* and relay the response back using the postMessageHandler | ||
*/ | ||
const execute = useCallback( | ||
async (payload: ProviderRelayPayload, executeProvider: Web3Provider) => { | ||
if (!executeProvider?.provider.request) { | ||
throw new Error("Provider only supports 'request' method"); | ||
} | ||
|
||
if (!postMessageHandler) { | ||
throw new Error( | ||
'Provider can execute request because PostMessageHandler is not initialized', | ||
); | ||
} | ||
|
||
const { id, params, method } = payload.jsonRpcRequestMessage; | ||
|
||
// Execute the request | ||
const result = await executeProvider.provider.request({ method, params }); | ||
const formattedResponse = { id, result, jsonrpc: '2.0' }; | ||
|
||
// Send the response using the postMessageHandler | ||
postMessageHandler.send(PostMessageHandlerEventType.PROVIDER_RELAY, { | ||
response: formattedResponse, | ||
eip6963Info: payload.eip6963Info, | ||
}); | ||
}, | ||
[postMessageHandler], | ||
); | ||
|
||
/** | ||
* Handle incoming provider relay messages | ||
*/ | ||
const onJsonRpcRequestMessage = useCallback( | ||
async ({ type, payload }: PostMessageData) => { | ||
if (!postMessageHandler || !checkout) return; | ||
if (type !== PostMessageHandlerEventType.PROVIDER_RELAY) return; | ||
|
||
const providerRelayPayload = payload as ProviderRelayPayload; | ||
|
||
const injectedProviders = checkout.getInjectedProviders(); | ||
const targetProvider = injectedProviders.find( | ||
(p) => p.info.uuid === providerRelayPayload.eip6963Info.uuid, | ||
); | ||
|
||
if (!targetProvider) { | ||
// eslint-disable-next-line no-console | ||
console.error( | ||
'PARENT - requested provider not found', | ||
providerRelayPayload.eip6963Info, | ||
injectedProviders, | ||
); | ||
return; | ||
} | ||
|
||
// If provider is not defined, connect the target provider | ||
let currentProvider = provider; | ||
if (!currentProvider) { | ||
const connectResponse = await checkout.connect({ | ||
provider: new Web3Provider(targetProvider.provider), | ||
}); | ||
currentProvider = connectResponse.provider; | ||
} | ||
|
||
// Set provider and execute the request | ||
checkoutDispatch({ | ||
payload: { | ||
type: CheckoutActions.SET_PROVIDER, | ||
provider: currentProvider, | ||
}, | ||
}); | ||
|
||
postMessageHandler.send(PostMessageHandlerEventType.PROVIDER_UPDATED, { | ||
eip6963Info: payload.eip6963Info, | ||
}); | ||
|
||
await execute(providerRelayPayload, currentProvider); | ||
}, | ||
|
||
[provider, postMessageHandler, checkout, execute], | ||
); | ||
|
||
/** | ||
* Subscribe to provider relay messages | ||
*/ | ||
useEffect(() => { | ||
if (!postMessageHandler) return; | ||
postMessageHandler.subscribe(onJsonRpcRequestMessage); | ||
}, [provider, postMessageHandler, execute, onJsonRpcRequestMessage]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters