From e4cc7ce6b0757edb8516a679ab18d7dc220af3d5 Mon Sep 17 00:00:00 2001 From: IvanMahda Date: Wed, 19 Jun 2024 22:44:26 +0300 Subject: [PATCH] [BRO-39] Migrate away from injecting API (Draft example of chrome API) Example of forwarding requests to walletApi with proxy --- examples/voting/src/Wallet.jsx | 4 +-- .../src/detector.ts | 23 ++++++++++++++++ .../browser-wallet-api-helpers/src/index.ts | 2 +- .../browser-wallet/src/background/index.ts | 27 +++++++++++++++++++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/examples/voting/src/Wallet.jsx b/examples/voting/src/Wallet.jsx index 7016b3dc5..6483220a0 100644 --- a/examples/voting/src/Wallet.jsx +++ b/examples/voting/src/Wallet.jsx @@ -6,7 +6,7 @@ /* eslint-disable import/no-unresolved */ /* eslint-disable no-plusplus */ import React from 'react'; -import { detectConcordiumProvider } from '@concordium/browser-wallet-api-helpers'; +import { concordiumWalletApiProxy } from '@concordium/browser-wallet-api-helpers'; import { Alert, Button } from 'react-bootstrap'; import { AccountTransactionType, @@ -19,7 +19,7 @@ import moment from 'moment'; import { RAW_SCHEMA_BASE64, TESTNET_GENESIS_BLOCK_HASH } from './config'; export async function init(setConnectedAccount) { - const client = await detectConcordiumProvider(); + const client = concordiumWalletApiProxy; // Listen for relevant events from the wallet. client.on('accountChanged', (account) => { console.debug('browserwallet event: accountChange', { account }); diff --git a/packages/browser-wallet-api-helpers/src/detector.ts b/packages/browser-wallet-api-helpers/src/detector.ts index a2baf674e..b390869de 100644 --- a/packages/browser-wallet-api-helpers/src/detector.ts +++ b/packages/browser-wallet-api-helpers/src/detector.ts @@ -31,3 +31,26 @@ export async function detectConcordiumProvider(timeout = 5000): Promise { + chrome.runtime.sendMessage(editorExtensionId, { target, payload }, (response) => { + resolve(response); + }); + }); +} + +// intercept all interactions with object +// in this way we can remotely interact with class instance inside BrowserWallet +// by forwarding 'property' name and payload +const proxyHandler = { + get(target, prop) { + return function (...args) { + return sendMsgToExtension(prop, args); + }; + }, +}; + +// {} as WalletApi - also enables TS annotations +export const concordiumWalletApiProxy = new Proxy({} as WalletApi, proxyHandler); diff --git a/packages/browser-wallet-api-helpers/src/index.ts b/packages/browser-wallet-api-helpers/src/index.ts index 134fd68ae..da7106d9f 100644 --- a/packages/browser-wallet-api-helpers/src/index.ts +++ b/packages/browser-wallet-api-helpers/src/index.ts @@ -1,3 +1,3 @@ export * from './wallet-api-types'; export * from './util'; -export { detectConcordiumProvider } from './detector'; +export { detectConcordiumProvider, concordiumWalletApiProxy } from './detector'; diff --git a/packages/browser-wallet/src/background/index.ts b/packages/browser-wallet/src/background/index.ts index a967c0fe1..90efbdf85 100644 --- a/packages/browser-wallet/src/background/index.ts +++ b/packages/browser-wallet/src/background/index.ts @@ -638,3 +638,30 @@ forwardToPopup( withPromptEnd, (msg) => createMessageTypeFilter(MessageType.Web3IdProof)(msg) && isAgeProof(msg.payload) ); + +// import { walletApi } from '@concordium/browser-wallet-api'; +// We cannot do a simple import in this case +// It creates circular dependencies that cause errors during build +// walletApi is build to work in page context, not inside BW + +// Alternatively we can create new implementation of class WalletApi +// For example implementation of connect() +// Inside can be used bgMessageHandler.sendInternalMessage +// But BW page with connect prompt, will try to receive 'window.location' of the page from which request was made +// So now value 'location' should be provided in payload, and corresponding changes made in React component +// All this leads to more changes across BW, not just only of creation of new WalletApi class +class WalletApi { + public async connect(): Promise { + return Promise.resolve(bgMessageHandler.sendInternalMessage(InternalMessageType.Connect)); + } +} + +const walletApi = new WalletApi(); + +chrome.runtime.onMessageExternal.addListener(function (request, sender, sendResponse) { + const { payload, target } = request; + walletApi[target](...payload).then((response) => { + sendResponse(response); + }); + return true; +});