From 3c55c332ab0433666ccf8a742ecf097a1e8d3b8c Mon Sep 17 00:00:00 2001 From: Emmanouela Date: Fri, 30 Aug 2024 13:37:41 +0300 Subject: [PATCH 1/7] bug(clerk-js): Use EIP6963 standard to get web3 provider --- .../src/utils/injectedWeb3Providers.ts | 54 +++++++++++++++++++ packages/clerk-js/src/utils/web3.ts | 36 +++++++------ 2 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 packages/clerk-js/src/utils/injectedWeb3Providers.ts diff --git a/packages/clerk-js/src/utils/injectedWeb3Providers.ts b/packages/clerk-js/src/utils/injectedWeb3Providers.ts new file mode 100644 index 00000000000..444b413bd8b --- /dev/null +++ b/packages/clerk-js/src/utils/injectedWeb3Providers.ts @@ -0,0 +1,54 @@ +import type { Web3Provider } from '@clerk/types'; + +interface EIP6963ProviderInfo { + walletId: string; + uuid: string; + name: string; + icon: string; +} + +interface EIP1193Provider { + isStatus?: boolean; + host?: string; + path?: string; + sendAsync?: ( + request: { method: string; params?: [] }, + callback: (error: Error | null, response: unknown) => void, + ) => void; // For sending asynchronous requests + send?: (request: { method: string; params?: [] }, callback: (error: Error | null, response: unknown) => void) => void; // For sending synchronous requests + request: (request: { method: string; params?: string[] }) => Promise; // Standard method for sending requests per EIP-1193 +} + +interface EIP6963ProviderDetail { + info: EIP6963ProviderInfo; + provider: EIP1193Provider; +} + +type EIP6963AnnounceProviderEvent = CustomEvent; + +class InjectedWeb3Providers { + #providers: EIP6963ProviderDetail[] = []; + #providerIdMap: Record = { + coinbase: 'Coinbase Wallet', + metamask: 'MetaMask', + } as const; + + constructor() { + window.addEventListener('eip6963:announceProvider', this.#onAnnouncement as EventListener); + window.dispatchEvent(new Event('eip6963:requestProvider')); + } + + get = (provider: Web3Provider) => { + return this.#providers.find(p => p.info.name === this.#providerIdMap[provider])?.provider; + }; + + #onAnnouncement = (event: EIP6963AnnounceProviderEvent) => { + if (this.#providers.some(p => p.info.uuid === event.detail.info.uuid)) { + return; + } + this.#providers.push(event.detail); + console.log(this.#providers); + }; +} + +export const injectedWeb3Providers = new InjectedWeb3Providers(); diff --git a/packages/clerk-js/src/utils/web3.ts b/packages/clerk-js/src/utils/web3.ts index 3dd3f6ade26..7bda320db04 100644 --- a/packages/clerk-js/src/utils/web3.ts +++ b/packages/clerk-js/src/utils/web3.ts @@ -1,23 +1,26 @@ import type { Web3Provider } from '@clerk/types'; import { toHex } from './hex'; - +import { injectedWeb3Providers } from './injectedWeb3Providers'; type GetWeb3IdentifierParams = { provider: Web3Provider; }; -export async function getWeb3Identifier(_: GetWeb3IdentifierParams): Promise { - // @ts-ignore - if (!global.ethereum) { - // Do nothing when ethereum doesn't exist. +// injection order: metamask, coinbase +// global.etherem -> coinbase +// injectedProvider(metamask), will use metamask wallet +// generateWeb3Signature(), will use coinbase wallet +// neds to be generateWeb3Signature({provider: metamask}) instead + +export async function getWeb3Identifier(params: GetWeb3IdentifierParams) { + const injectedProvider = injectedWeb3Providers.get(params.provider); + if (!injectedProvider) { + // TODO: discuss what happens if a plugin for the requested provider is not found in the system + //do we simply return '' or fall back to another plugin? return ''; } - // @ts-ignore - const identifiers = await global.ethereum.request({ - method: 'eth_requestAccounts', - }); - + const identifiers = await injectedProvider.request({ method: 'eth_requestAccounts' }); return (identifiers && identifiers[0]) || ''; } @@ -27,15 +30,16 @@ type GenerateWeb3SignatureParams = { provider: Web3Provider; }; -export async function generateWeb3Signature({ identifier, nonce }: GenerateWeb3SignatureParams): Promise { - // @ts-ignore - if (!global.ethereum) { - // Do nothing when ethereum doesn't exist. +export async function generateWeb3Signature(params: GenerateWeb3SignatureParams): Promise { + const { identifier, nonce, provider } = params; + const injectedProvider = injectedWeb3Providers.get(provider); + if (!injectedProvider) { + // TODO: discuss what happens if a plugin for the requested provider is not found in the system + //do we simply return '' or fall back to another plugin? return ''; } - // @ts-ignore - return await global.ethereum.request({ + return await injectedProvider.request({ method: 'personal_sign', params: [`0x${toHex(nonce)}`, identifier], }); From 55175bbe00e0f2f365d6c516646a6b984975fb13 Mon Sep 17 00:00:00 2001 From: Emmanouela Pothitou <68468183+EmmanouelaPothitou@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:41:40 +0300 Subject: [PATCH 2/7] Create four-tips-push.md --- .changeset/four-tips-push.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/four-tips-push.md diff --git a/.changeset/four-tips-push.md b/.changeset/four-tips-push.md new file mode 100644 index 00000000000..b255bd027a4 --- /dev/null +++ b/.changeset/four-tips-push.md @@ -0,0 +1,5 @@ +--- +"@clerk/clerk-js": patch +--- + +Use the EIP-6963 standard to get a Web3 provider when more than one provider is injected. From f1f46205274e47bfe08977d458f56379ed880096 Mon Sep 17 00:00:00 2001 From: Nikos Douvlis Date: Fri, 30 Aug 2024 13:55:40 +0300 Subject: [PATCH 3/7] chore(clerk-js): Bump bundlewatch --- packages/clerk-js/bundlewatch.config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/clerk-js/bundlewatch.config.json b/packages/clerk-js/bundlewatch.config.json index 9e711db89c8..9701311a5ef 100644 --- a/packages/clerk-js/bundlewatch.config.json +++ b/packages/clerk-js/bundlewatch.config.json @@ -1,6 +1,6 @@ { "files": [ - { "path": "./dist/clerk.browser.js", "maxSize": "63kB" }, + { "path": "./dist/clerk.browser.js", "maxSize": "64kB" }, { "path": "./dist/clerk.headless.js", "maxSize": "43kB" }, { "path": "./dist/ui-common*.js", "maxSize": "85KB" }, { "path": "./dist/vendors*.js", "maxSize": "70KB" }, From 2e69a13eb35eb3a86bd78e2908acc1de549fe2e9 Mon Sep 17 00:00:00 2001 From: Emmanouela Date: Fri, 30 Aug 2024 14:45:02 +0300 Subject: [PATCH 4/7] bug(clerk-js): Add comments --- packages/clerk-js/src/utils/injectedWeb3Providers.ts | 2 +- packages/clerk-js/src/utils/web3.ts | 10 ---------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/clerk-js/src/utils/injectedWeb3Providers.ts b/packages/clerk-js/src/utils/injectedWeb3Providers.ts index 444b413bd8b..51ae188f8d3 100644 --- a/packages/clerk-js/src/utils/injectedWeb3Providers.ts +++ b/packages/clerk-js/src/utils/injectedWeb3Providers.ts @@ -1,4 +1,5 @@ import type { Web3Provider } from '@clerk/types'; +//https://eips.ethereum.org/EIPS/eip-6963 interface EIP6963ProviderInfo { walletId: string; @@ -47,7 +48,6 @@ class InjectedWeb3Providers { return; } this.#providers.push(event.detail); - console.log(this.#providers); }; } diff --git a/packages/clerk-js/src/utils/web3.ts b/packages/clerk-js/src/utils/web3.ts index 7bda320db04..fc6f343be29 100644 --- a/packages/clerk-js/src/utils/web3.ts +++ b/packages/clerk-js/src/utils/web3.ts @@ -6,17 +6,9 @@ type GetWeb3IdentifierParams = { provider: Web3Provider; }; -// injection order: metamask, coinbase -// global.etherem -> coinbase -// injectedProvider(metamask), will use metamask wallet -// generateWeb3Signature(), will use coinbase wallet -// neds to be generateWeb3Signature({provider: metamask}) instead - export async function getWeb3Identifier(params: GetWeb3IdentifierParams) { const injectedProvider = injectedWeb3Providers.get(params.provider); if (!injectedProvider) { - // TODO: discuss what happens if a plugin for the requested provider is not found in the system - //do we simply return '' or fall back to another plugin? return ''; } @@ -34,8 +26,6 @@ export async function generateWeb3Signature(params: GenerateWeb3SignatureParams) const { identifier, nonce, provider } = params; const injectedProvider = injectedWeb3Providers.get(provider); if (!injectedProvider) { - // TODO: discuss what happens if a plugin for the requested provider is not found in the system - //do we simply return '' or fall back to another plugin? return ''; } From 0cdc944efd9df62b4735c7170ee63123d0f12cfd Mon Sep 17 00:00:00 2001 From: Emmanouela Pothitou <68468183+EmmanouelaPothitou@users.noreply.github.com> Date: Mon, 2 Sep 2024 09:44:03 +0300 Subject: [PATCH 5/7] Update .changeset/four-tips-push.md Co-authored-by: panteliselef --- .changeset/four-tips-push.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/four-tips-push.md b/.changeset/four-tips-push.md index b255bd027a4..425cf20db76 100644 --- a/.changeset/four-tips-push.md +++ b/.changeset/four-tips-push.md @@ -2,4 +2,4 @@ "@clerk/clerk-js": patch --- -Use the EIP-6963 standard to get a Web3 provider when more than one provider is injected. +Bug fix: Use the EIP-6963 standard to get a Web3 provider when more than one provider is injected. From 2ade8e0ce8bf74b1bb37ba3f900520ba13637205 Mon Sep 17 00:00:00 2001 From: Emmanouela Date: Fri, 30 Aug 2024 14:45:02 +0300 Subject: [PATCH 6/7] bug(clerk-js): Add comments --- packages/clerk-js/src/utils/injectedWeb3Providers.ts | 2 +- packages/clerk-js/src/utils/web3.ts | 12 ++---------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/clerk-js/src/utils/injectedWeb3Providers.ts b/packages/clerk-js/src/utils/injectedWeb3Providers.ts index 444b413bd8b..51ae188f8d3 100644 --- a/packages/clerk-js/src/utils/injectedWeb3Providers.ts +++ b/packages/clerk-js/src/utils/injectedWeb3Providers.ts @@ -1,4 +1,5 @@ import type { Web3Provider } from '@clerk/types'; +//https://eips.ethereum.org/EIPS/eip-6963 interface EIP6963ProviderInfo { walletId: string; @@ -47,7 +48,6 @@ class InjectedWeb3Providers { return; } this.#providers.push(event.detail); - console.log(this.#providers); }; } diff --git a/packages/clerk-js/src/utils/web3.ts b/packages/clerk-js/src/utils/web3.ts index 7bda320db04..e7b3fca2fbb 100644 --- a/packages/clerk-js/src/utils/web3.ts +++ b/packages/clerk-js/src/utils/web3.ts @@ -6,17 +6,11 @@ type GetWeb3IdentifierParams = { provider: Web3Provider; }; -// injection order: metamask, coinbase -// global.etherem -> coinbase -// injectedProvider(metamask), will use metamask wallet -// generateWeb3Signature(), will use coinbase wallet -// neds to be generateWeb3Signature({provider: metamask}) instead - export async function getWeb3Identifier(params: GetWeb3IdentifierParams) { const injectedProvider = injectedWeb3Providers.get(params.provider); if (!injectedProvider) { - // TODO: discuss what happens if a plugin for the requested provider is not found in the system - //do we simply return '' or fall back to another plugin? + // If a plugin for the requested provider is not found, + // the flow will fail as it has been the expected behavior so far. return ''; } @@ -34,8 +28,6 @@ export async function generateWeb3Signature(params: GenerateWeb3SignatureParams) const { identifier, nonce, provider } = params; const injectedProvider = injectedWeb3Providers.get(provider); if (!injectedProvider) { - // TODO: discuss what happens if a plugin for the requested provider is not found in the system - //do we simply return '' or fall back to another plugin? return ''; } From f4ba8b0162894d232a3ce82f03e6d00420495e63 Mon Sep 17 00:00:00 2001 From: Emmanouela Date: Mon, 2 Sep 2024 11:23:04 +0300 Subject: [PATCH 7/7] fix(clerk-js): Check before using window identifier --- packages/clerk-js/src/utils/injectedWeb3Providers.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/clerk-js/src/utils/injectedWeb3Providers.ts b/packages/clerk-js/src/utils/injectedWeb3Providers.ts index 51ae188f8d3..7ce4591af6c 100644 --- a/packages/clerk-js/src/utils/injectedWeb3Providers.ts +++ b/packages/clerk-js/src/utils/injectedWeb3Providers.ts @@ -35,6 +35,9 @@ class InjectedWeb3Providers { } as const; constructor() { + if (typeof window === 'undefined') { + return; + } window.addEventListener('eip6963:announceProvider', this.#onAnnouncement as EventListener); window.dispatchEvent(new Event('eip6963:requestProvider')); }