From 55ada0c60b7fb62aabdec2b6f0ba231c77d7ee7b Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 13 Dec 2023 16:16:28 +0200 Subject: [PATCH 01/20] - Add metamask-snap support --- packages/core/package.json | 3 ++ packages/core/src/discovery.ts | 11 ++++++++ packages/core/src/main.ts | 3 ++ packages/core/src/wallet/metamaskBridge.ts | 33 ++++++++++++++++++++++ pnpm-lock.yaml | 9 ++++++ 5 files changed, 59 insertions(+) create mode 100644 packages/core/src/wallet/metamaskBridge.ts diff --git a/packages/core/package.json b/packages/core/package.json index 0cec766..ba7f7f5 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,5 +46,8 @@ "starknet": { "optional": false } + }, + "dependencies": { + "@metamask/detect-provider": "^2.0.0" } } diff --git a/packages/core/src/discovery.ts b/packages/core/src/discovery.ts index c7a25d8..dfb1d30 100644 --- a/packages/core/src/discovery.ts +++ b/packages/core/src/discovery.ts @@ -30,6 +30,17 @@ const wallets: WalletProvider[] = [ edge: "https://microsoftedge.microsoft.com/addons/detail/braavos-wallet/hkkpjehhcnhgefhbdcgfkeegglpjchdc", }, }, + { + id: "metamask", + name: "MetaMask", + icon: `data:image/svg+xml;utf8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMTIiIGhlaWdodD0iMTg5IiB2aWV3Qm94PSIwIDAgMjEyIDE4OSI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cG9seWdvbiBmaWxsPSIjQ0RCREIyIiBwb2ludHM9IjYwLjc1IDE3My4yNSA4OC4zMTMgMTgwLjU2MyA4OC4zMTMgMTcxIDkwLjU2MyAxNjguNzUgMTA2LjMxMyAxNjguNzUgMTA2LjMxMyAxODAgMTA2LjMxMyAxODcuODc1IDg5LjQzOCAxODcuODc1IDY4LjYyNSAxNzguODc1Ii8+PHBvbHlnb24gZmlsbD0iI0NEQkRCMiIgcG9pbnRzPSIxMDUuNzUgMTczLjI1IDEzMi43NSAxODAuNTYzIDEzMi43NSAxNzEgMTM1IDE2OC43NSAxNTAuNzUgMTY4Ljc1IDE1MC43NSAxODAgMTUwLjc1IDE4Ny44NzUgMTMzLjg3NSAxODcuODc1IDExMy4wNjMgMTc4Ljg3NSIgdHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMjU2LjUgMCkiLz48cG9seWdvbiBmaWxsPSIjMzkzOTM5IiBwb2ludHM9IjkwLjU2MyAxNTIuNDM4IDg4LjMxMyAxNzEgOTEuMTI1IDE2OC43NSAxMjAuMzc1IDE2OC43NSAxMjMuNzUgMTcxIDEyMS41IDE1Mi40MzggMTE3IDE0OS42MjUgOTQuNSAxNTAuMTg4Ii8+PHBvbHlnb24gZmlsbD0iI0Y4OUMzNSIgcG9pbnRzPSI3NS4zNzUgMjcgODguODc1IDU4LjUgOTUuMDYzIDE1MC4xODggMTE3IDE1MC4xODggMTIzLjc1IDU4LjUgMTM2LjEyNSAyNyIvPjxwb2x5Z29uIGZpbGw9IiNGODlEMzUiIHBvaW50cz0iMTYuMzEzIDk2LjE4OCAuNTYzIDE0MS43NSAzOS45MzggMTM5LjUgNjUuMjUgMTM5LjUgNjUuMjUgMTE5LjgxMyA2NC4xMjUgNzkuMzEzIDU4LjUgODMuODEzIi8+PHBvbHlnb24gZmlsbD0iI0Q4N0MzMCIgcG9pbnRzPSI0Ni4xMjUgMTAxLjI1IDkyLjI1IDEwMi4zNzUgODcuMTg4IDEyNiA2NS4yNSAxMjAuMzc1Ii8+PHBvbHlnb24gZmlsbD0iI0VBOEQzQSIgcG9pbnRzPSI0Ni4xMjUgMTAxLjgxMyA2NS4yNSAxMTkuODEzIDY1LjI1IDEzNy44MTMiLz48cG9seWdvbiBmaWxsPSIjRjg5RDM1IiBwb2ludHM9IjY1LjI1IDEyMC4zNzUgODcuNzUgMTI2IDk1LjA2MyAxNTAuMTg4IDkwIDE1MyA2NS4yNSAxMzguMzc1Ii8+PHBvbHlnb24gZmlsbD0iI0VCOEYzNSIgcG9pbnRzPSI2NS4yNSAxMzguMzc1IDYwLjc1IDE3My4yNSA5MC41NjMgMTUyLjQzOCIvPjxwb2x5Z29uIGZpbGw9IiNFQThFM0EiIHBvaW50cz0iOTIuMjUgMTAyLjM3NSA5NS4wNjMgMTUwLjE4OCA4Ni42MjUgMTI1LjcxOSIvPjxwb2x5Z29uIGZpbGw9IiNEODdDMzAiIHBvaW50cz0iMzkuMzc1IDEzOC45MzggNjUuMjUgMTM4LjM3NSA2MC43NSAxNzMuMjUiLz48cG9seWdvbiBmaWxsPSIjRUI4RjM1IiBwb2ludHM9IjEyLjkzOCAxODguNDM4IDYwLjc1IDE3My4yNSAzOS4zNzUgMTM4LjkzOCAuNTYzIDE0MS43NSIvPjxwb2x5Z29uIGZpbGw9IiNFODgyMUUiIHBvaW50cz0iODguODc1IDU4LjUgNjQuNjg4IDc4Ljc1IDQ2LjEyNSAxMDEuMjUgOTIuMjUgMTAyLjkzOCIvPjxwb2x5Z29uIGZpbGw9IiNERkNFQzMiIHBvaW50cz0iNjAuNzUgMTczLjI1IDkwLjU2MyAxNTIuNDM4IDg4LjMxMyAxNzAuNDM4IDg4LjMxMyAxODAuNTYzIDY4LjA2MyAxNzYuNjI1Ii8+PHBvbHlnb24gZmlsbD0iI0RGQ0VDMyIgcG9pbnRzPSIxMjEuNSAxNzMuMjUgMTUwLjc1IDE1Mi40MzggMTQ4LjUgMTcwLjQzOCAxNDguNSAxODAuNTYzIDEyOC4yNSAxNzYuNjI1IiB0cmFuc2Zvcm09Im1hdHJpeCgtMSAwIDAgMSAyNzIuMjUgMCkiLz48cG9seWdvbiBmaWxsPSIjMzkzOTM5IiBwb2ludHM9IjcwLjMxMyAxMTIuNSA2NC4xMjUgMTI1LjQzOCA4Ni4wNjMgMTE5LjgxMyIgdHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMTUwLjE4OCAwKSIvPjxwb2x5Z29uIGZpbGw9IiNFODhGMzUiIHBvaW50cz0iMTIuMzc1IC41NjMgODguODc1IDU4LjUgNzUuOTM4IDI3Ii8+PHBhdGggZmlsbD0iIzhFNUEzMCIgZD0iTTEyLjM3NTAwMDIsMC41NjI1MDAwMDggTDIuMjUwMDAwMDMsMzEuNTAwMDAwNSBMNy44NzUwMDAxMiw2NS4yNTAwMDEgTDMuOTM3NTAwMDYsNjcuNTAwMDAxIEw5LjU2MjUwMDE0LDcyLjU2MjUgTDUuMDYyNTAwMDgsNzYuNTAwMDAxMSBMMTEuMjUsODIuMTI1MDAxMiBMNy4zMTI1MDAxMSw4NS41MDAwMDEzIEwxNi4zMTI1MDAyLDk2Ljc1MDAwMTQgTDU4LjUwMDAwMDksODMuODEyNTAxMiBDNzkuMTI1MDAxMiw2Ny4zMTI1MDA0IDg5LjI1MDAwMTMsNTguODc1MDAwMyA4OC44NzUwMDEzLDU4LjUwMDAwMDkgQzg4LjUwMDAwMTMsNTguMTI1MDAwOSA2My4wMDAwMDA5LDM4LjgxMjUwMDYgMTIuMzc1MDAwMiwwLjU2MjUwMDAwOCBaIi8+PGcgdHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMjExLjUgMCkiPjxwb2x5Z29uIGZpbGw9IiNGODlEMzUiIHBvaW50cz0iMTYuMzEzIDk2LjE4OCAuNTYzIDE0MS43NSAzOS45MzggMTM5LjUgNjUuMjUgMTM5LjUgNjUuMjUgMTE5LjgxMyA2NC4xMjUgNzkuMzEzIDU4LjUgODMuODEzIi8+PHBvbHlnb24gZmlsbD0iI0Q4N0MzMCIgcG9pbnRzPSI0Ni4xMjUgMTAxLjI1IDkyLjI1IDEwMi4zNzUgODcuMTg4IDEyNiA2NS4yNSAxMjAuMzc1Ii8+PHBvbHlnb24gZmlsbD0iI0VBOEQzQSIgcG9pbnRzPSI0Ni4xMjUgMTAxLjgxMyA2NS4yNSAxMTkuODEzIDY1LjI1IDEzNy44MTMiLz48cG9seWdvbiBmaWxsPSIjRjg5RDM1IiBwb2ludHM9IjY1LjI1IDEyMC4zNzUgODcuNzUgMTI2IDk1LjA2MyAxNTAuMTg4IDkwIDE1MyA2NS4yNSAxMzguMzc1Ii8+PHBvbHlnb24gZmlsbD0iI0VCOEYzNSIgcG9pbnRzPSI2NS4yNSAxMzguMzc1IDYwLjc1IDE3My4yNSA5MCAxNTMiLz48cG9seWdvbiBmaWxsPSIjRUE4RTNBIiBwb2ludHM9IjkyLjI1IDEwMi4zNzUgOTUuMDYzIDE1MC4xODggODYuNjI1IDEyNS43MTkiLz48cG9seWdvbiBmaWxsPSIjRDg3QzMwIiBwb2ludHM9IjM5LjM3NSAxMzguOTM4IDY1LjI1IDEzOC4zNzUgNjAuNzUgMTczLjI1Ii8+PHBvbHlnb24gZmlsbD0iI0VCOEYzNSIgcG9pbnRzPSIxMi45MzggMTg4LjQzOCA2MC43NSAxNzMuMjUgMzkuMzc1IDEzOC45MzggLjU2MyAxNDEuNzUiLz48cG9seWdvbiBmaWxsPSIjRTg4MjFFIiBwb2ludHM9Ijg4Ljg3NSA1OC41IDY0LjY4OCA3OC43NSA0Ni4xMjUgMTAxLjI1IDkyLjI1IDEwMi45MzgiLz48cG9seWdvbiBmaWxsPSIjMzkzOTM5IiBwb2ludHM9IjcwLjMxMyAxMTIuNSA2NC4xMjUgMTI1LjQzOCA4Ni4wNjMgMTE5LjgxMyIgdHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMTUwLjE4OCAwKSIvPjxwb2x5Z29uIGZpbGw9IiNFODhGMzUiIHBvaW50cz0iMTIuMzc1IC41NjMgODguODc1IDU4LjUgNzUuOTM4IDI3Ii8+PHBhdGggZmlsbD0iIzhFNUEzMCIgZD0iTTEyLjM3NTAwMDIsMC41NjI1MDAwMDggTDIuMjUwMDAwMDMsMzEuNTAwMDAwNSBMNy44NzUwMDAxMiw2NS4yNTAwMDEgTDMuOTM3NTAwMDYsNjcuNTAwMDAxIEw5LjU2MjUwMDE0LDcyLjU2MjUgTDUuMDYyNTAwMDgsNzYuNTAwMDAxMSBMMTEuMjUsODIuMTI1MDAxMiBMNy4zMTI1MDAxMSw4NS41MDAwMDEzIEwxNi4zMTI1MDAyLDk2Ljc1MDAwMTQgTDU4LjUwMDAwMDksODMuODEyNTAxMiBDNzkuMTI1MDAxMiw2Ny4zMTI1MDA0IDg5LjI1MDAwMTMsNTguODc1MDAwMyA4OC44NzUwMDEzLDU4LjUwMDAwMDkgQzg4LjUwMDAwMTMsNTguMTI1MDAwOSA2My4wMDAwMDA5LDM4LjgxMjUwMDYgMTIuMzc1MDAwMiwwLjU2MjUwMDAwOCBaIi8+PC9nPjwvZz48L3N2Zz4=`, + downloads: { + chrome: + "https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn", + firefox: "https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/", + edge: "https://microsoftedge.microsoft.com/addons/detail/metamask/ejbalbakoplchlghecdalmeeeajnimhm?hl=en-US", + } + } ] export default wallets diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 16241b9..892378f 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -7,6 +7,7 @@ import { IStorageWrapper, LocalStorageWrapper } from "./localStorageStore" import { pipe } from "./utils" import { FilterList, filterBy, filterByPreAuthorized } from "./wallet/filter" import { isWalletObj } from "./wallet/isWalletObject" +import { bootstrapMetamaskBridge } from "./wallet/metamaskBridge" import { scanObjectForWallets } from "./wallet/scan" import { Sort, sortBy } from "./wallet/sort" @@ -75,6 +76,8 @@ export function getStarknet( } const lastConnectedStore = storageFactoryImplementation("gsw-last") + bootstrapMetamaskBridge(); + return { getAvailableWallets: async (options = {}) => { const availableWallets = scanObjectForWallets( diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts new file mode 100644 index 0000000..7f59ad4 --- /dev/null +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -0,0 +1,33 @@ +import detectEthereumProvider from '@metamask/detect-provider'; + +async function hasSnapSupport(provider: any) { + try { + await provider.request({ + method: "wallet_getSnaps", + }) + return true + } catch { + return false + } +} + +async function bootstrapMetamaskBridge() { + if (window.hasOwnProperty("starknet_metamask")) { + return; + } + + const provider = await detectEthereumProvider() + if (!provider) { + return; + } + + const snapSupport = await hasSnapSupport(provider) + if (!snapSupport) { + return; + } + + const MetaMaskSnapWallet = await import('starknet-metamask') + window["starknet_metamask"] = new MetaMaskSnapWallet(provider) +} + +export {bootstrapMetamaskBridge} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f79396e..8cf59ea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,10 @@ importers: version: 3.0.0 packages/core: + dependencies: + '@metamask/detect-provider': + specifier: ^2.0.0 + version: 2.0.0 devDependencies: c8: specifier: ^7.12.0 @@ -959,6 +963,11 @@ packages: read-yaml-file: 1.1.0 dev: true + /@metamask/detect-provider@2.0.0: + resolution: {integrity: sha512-sFpN+TX13E9fdBDh9lvQeZdJn4qYoRb/6QF2oZZK/Pn559IhCFacPMU1rMuqyXoFQF3JSJfii2l98B87QDPeCQ==} + engines: {node: '>=14.0.0'} + dev: false + /@microsoft/api-extractor-model@7.27.3(@types/node@20.3.1): resolution: {integrity: sha512-fSFvw7otYHduOkyshjTbapKKgwF8bgquVHvgF8VgeKtMYvqXkoaj7W6VcM7PNY7E2bbblhUgC4XNdqZLD4SJGw==} dependencies: From aa4422ca0104e6a37112b12b50df2b53a7028dc0 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Tue, 19 Dec 2023 13:41:10 +0200 Subject: [PATCH 02/20] - Integrate @consensys/get-starknet --- packages/core/package.json | 1 + packages/core/src/StarknetWindowObject.ts | 38 ++++----- packages/core/src/wallet/metamaskBridge.ts | 5 +- packages/ui/package.json | 2 +- pnpm-lock.yaml | 92 ++++++++++++---------- 5 files changed, 77 insertions(+), 61 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index ba7f7f5..29fa54d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -48,6 +48,7 @@ } }, "dependencies": { + "@consensys/get-starknet": "1.0.0-dev-998a4b7-202312151810", "@metamask/detect-provider": "^2.0.0" } } diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index ca6b002..96c98b9 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -3,6 +3,7 @@ import type { AccountInterface as AccountInterfaceV4, ProviderInterface as ProviderInterfaceV4, } from "starknet4" +import type { MetaMaskSnapWallet } from '@consensys/get-starknet'; export type AccountChangeEventHandler = (accounts: string[]) => void @@ -10,13 +11,13 @@ export type NetworkChangeEventHandler = (network?: string) => void export type WalletEvents = | { - type: "accountsChanged" - handler: AccountChangeEventHandler - } + type: "accountsChanged" + handler: AccountChangeEventHandler + } | { - type: "networkChanged" - handler: NetworkChangeEventHandler - } + type: "networkChanged" + handler: NetworkChangeEventHandler + } // EIP-747: // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-747.md @@ -57,20 +58,20 @@ export interface SwitchStarknetChainParameter { export type RpcMessage = | { - type: "wallet_watchAsset" - params: WatchAssetParameters - result: boolean - } + type: "wallet_watchAsset" + params: WatchAssetParameters + result: boolean + } | { - type: "wallet_addStarknetChain" - params: AddStarknetChainParameters - result: boolean - } + type: "wallet_addStarknetChain" + params: AddStarknetChainParameters + result: boolean + } | { - type: "wallet_switchStarknetChain" - params: SwitchStarknetChainParameter - result: boolean - } + type: "wallet_switchStarknetChain" + params: SwitchStarknetChainParameter + result: boolean + } export interface IStarknetWindowObject { id: string @@ -118,6 +119,7 @@ declare global { starknet?: StarknetWindowObject starknet_braavos?: StarknetWindowObject starknet_argentX?: StarknetWindowObject + starknet_metamask?: MetaMaskSnapWallet [key: `starknet_${string}`]: StarknetWindowObject | undefined } } diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index 7f59ad4..320b34e 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -1,3 +1,4 @@ +import type { MetaMaskProvider } from '@consensys/get-starknet/dist/type'; import detectEthereumProvider from '@metamask/detect-provider'; async function hasSnapSupport(provider: any) { @@ -16,7 +17,7 @@ async function bootstrapMetamaskBridge() { return; } - const provider = await detectEthereumProvider() + const provider = await detectEthereumProvider() if (!provider) { return; } @@ -26,7 +27,7 @@ async function bootstrapMetamaskBridge() { return; } - const MetaMaskSnapWallet = await import('starknet-metamask') + const {MetaMaskSnapWallet} = await import('@consensys/get-starknet') window["starknet_metamask"] = new MetaMaskSnapWallet(provider) } diff --git a/packages/ui/package.json b/packages/ui/package.json index 4f33159..9263666 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -37,7 +37,7 @@ "@sveltejs/vite-plugin-svelte": "^1.0.1", "@tsconfig/svelte": "^3.0.0", "autoprefixer": "^10.4.7", - "postcss": "^8.4.14", + "postcss": "^8.4.21", "svelte": "^3.49.0", "svelte-check": "^2.8.0", "svelte-preprocess": "^4.10.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8cf59ea..9f21e56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -66,6 +66,9 @@ importers: packages/core: dependencies: + '@consensys/get-starknet': + specifier: 1.0.0-dev-998a4b7-202312151810 + version: 1.0.0-dev-998a4b7-202312151810 '@metamask/detect-provider': specifier: ^2.0.0 version: 2.0.0 @@ -112,22 +115,22 @@ importers: version: 3.0.0 autoprefixer: specifier: ^10.4.7 - version: 10.4.7(postcss@8.4.14) + version: 10.4.7(postcss@8.4.32) postcss: - specifier: ^8.4.14 - version: 8.4.14 + specifier: ^8.4.21 + version: 8.4.32 svelte: specifier: ^3.49.0 version: 3.49.0 svelte-check: specifier: ^2.8.0 - version: 2.8.0(@babel/core@7.17.8)(postcss@8.4.14)(svelte@3.49.0) + version: 2.8.0(@babel/core@7.17.8)(postcss@8.4.32)(svelte@3.49.0) svelte-preprocess: specifier: ^4.10.7 - version: 4.10.7(@babel/core@7.17.8)(postcss@8.4.14)(svelte@3.49.0)(typescript@4.6.4) + version: 4.10.7(@babel/core@7.17.8)(postcss@8.4.32)(svelte@3.49.0)(typescript@4.6.4) tailwindcss: specifier: ^3.1.6 - version: 3.1.6(postcss@8.4.14)(ts-node@10.9.1) + version: 3.1.6(postcss@8.4.32)(ts-node@10.9.1) tslib: specifier: ^2.4.0 version: 2.4.0 @@ -866,6 +869,14 @@ packages: chalk: 4.1.2 dev: true + /@consensys/get-starknet@1.0.0-dev-998a4b7-202312151810: + resolution: {integrity: sha512-CzywgXiQTkhgrcYs2uMtMGU8IebbP1x8Z1z6mvd9MQYEFG/6UTQ/u6u86RcopXYt41MJOry5kYtjZMcYLSRAhA==} + dependencies: + starknet: 5.18.0 + transitivePeerDependencies: + - encoding + dev: false + /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -1015,7 +1026,6 @@ packages: resolution: {integrity: sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==} dependencies: '@noble/hashes': 1.3.0 - dev: true /@noble/hashes@1.2.0: resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} @@ -1023,12 +1033,10 @@ packages: /@noble/hashes@1.3.0: resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} - dev: true /@noble/hashes@1.3.1: resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} engines: {node: '>= 16'} - dev: true /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} @@ -1494,7 +1502,7 @@ packages: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: true - /autoprefixer@10.4.7(postcss@8.4.14): + /autoprefixer@10.4.7(postcss@8.4.32): resolution: {integrity: sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==} engines: {node: ^10 || ^12 || >=14} hasBin: true @@ -1506,7 +1514,7 @@ packages: fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 - postcss: 8.4.14 + postcss: 8.4.32 postcss-value-parser: 4.2.0 dev: true @@ -3148,7 +3156,6 @@ packages: whatwg-fetch: 3.6.2 transitivePeerDependencies: - encoding - dev: true /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} @@ -3409,7 +3416,6 @@ packages: /lossless-json@2.0.9: resolution: {integrity: sha512-PUfJ5foxULG1x/dXpSckmt0woBDqyq/WFoI885vEqjGwuP41K2EBYh2IT3zYx9dWqcTLIfXiCE5AjhF1jk9Sbg==} - dev: true /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} @@ -3519,7 +3525,6 @@ packages: dependencies: '@noble/curves': 1.0.0 '@noble/hashes': 1.3.1 - dev: true /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} @@ -3623,6 +3628,12 @@ packages: hasBin: true dev: true + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + /node-fetch@2.6.11: resolution: {integrity: sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==} engines: {node: 4.x || >=6.0.0} @@ -3633,7 +3644,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: true /node-releases@2.0.12: resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} @@ -3789,7 +3799,6 @@ packages: /pako@2.1.0: resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} - dev: true /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} @@ -3881,29 +3890,29 @@ packages: find-up: 4.1.0 dev: true - /postcss-import@14.1.0(postcss@8.4.14): + /postcss-import@14.1.0(postcss@8.4.32): resolution: {integrity: sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==} engines: {node: '>=10.0.0'} peerDependencies: postcss: ^8.0.0 dependencies: - postcss: 8.4.14 + postcss: 8.4.32 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.2 dev: true - /postcss-js@4.0.1(postcss@8.4.14): + /postcss-js@4.0.1(postcss@8.4.32): resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} engines: {node: ^12 || ^14 || >= 16} peerDependencies: postcss: ^8.4.21 dependencies: camelcase-css: 2.0.1 - postcss: 8.4.14 + postcss: 8.4.32 dev: true - /postcss-load-config@3.1.4(postcss@8.4.14)(ts-node@10.9.1): + /postcss-load-config@3.1.4(postcss@8.4.32)(ts-node@10.9.1): resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} engines: {node: '>= 10'} peerDependencies: @@ -3916,18 +3925,18 @@ packages: optional: true dependencies: lilconfig: 2.1.0 - postcss: 8.4.14 + postcss: 8.4.32 ts-node: 10.9.1(@types/node@20.3.1)(typescript@4.6.4) yaml: 1.10.2 dev: true - /postcss-nested@5.0.6(postcss@8.4.14): + /postcss-nested@5.0.6(postcss@8.4.32): resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==} engines: {node: '>=12.0'} peerDependencies: postcss: ^8.2.14 dependencies: - postcss: 8.4.14 + postcss: 8.4.32 postcss-selector-parser: 6.0.13 dev: true @@ -3952,6 +3961,15 @@ packages: source-map-js: 1.0.2 dev: true + /postcss@8.4.32: + resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /preferred-pm@3.0.3: resolution: {integrity: sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==} engines: {node: '>=10'} @@ -4526,7 +4544,6 @@ packages: url-join: 4.0.1 transitivePeerDependencies: - encoding - dev: true /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} @@ -4654,7 +4671,7 @@ packages: engines: {node: '>= 0.4'} dev: true - /svelte-check@2.8.0(@babel/core@7.17.8)(postcss@8.4.14)(svelte@3.49.0): + /svelte-check@2.8.0(@babel/core@7.17.8)(postcss@8.4.32)(svelte@3.49.0): resolution: {integrity: sha512-HRL66BxffMAZusqe5I5k26mRWQ+BobGd9Rxm3onh7ZVu0nTk8YTKJ9vu3LVPjUGLU9IX7zS+jmwPVhJYdXJ8vg==} hasBin: true peerDependencies: @@ -4667,7 +4684,7 @@ packages: picocolors: 1.0.0 sade: 1.8.1 svelte: 3.49.0 - svelte-preprocess: 4.10.7(@babel/core@7.17.8)(postcss@8.4.14)(svelte@3.49.0)(typescript@4.6.4) + svelte-preprocess: 4.10.7(@babel/core@7.17.8)(postcss@8.4.32)(svelte@3.49.0)(typescript@4.6.4) typescript: 4.6.4 transitivePeerDependencies: - '@babel/core' @@ -4691,7 +4708,7 @@ packages: svelte: 3.49.0 dev: true - /svelte-preprocess@4.10.7(@babel/core@7.17.8)(postcss@8.4.14)(svelte@3.49.0)(typescript@4.6.4): + /svelte-preprocess@4.10.7(@babel/core@7.17.8)(postcss@8.4.32)(svelte@3.49.0)(typescript@4.6.4): resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==} engines: {node: '>= 9.11.2'} requiresBuild: true @@ -4737,7 +4754,7 @@ packages: '@types/sass': 1.45.0 detect-indent: 6.1.0 magic-string: 0.25.9 - postcss: 8.4.14 + postcss: 8.4.32 sorcery: 0.10.0 strip-indent: 3.0.0 svelte: 3.49.0 @@ -4764,7 +4781,7 @@ packages: get-port: 3.2.0 dev: true - /tailwindcss@3.1.6(postcss@8.4.14)(ts-node@10.9.1): + /tailwindcss@3.1.6(postcss@8.4.32)(ts-node@10.9.1): resolution: {integrity: sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==} engines: {node: '>=12.13.0'} hasBin: true @@ -4784,11 +4801,11 @@ packages: normalize-path: 3.0.0 object-hash: 3.0.0 picocolors: 1.0.0 - postcss: 8.4.14 - postcss-import: 14.1.0(postcss@8.4.14) - postcss-js: 4.0.1(postcss@8.4.14) - postcss-load-config: 3.1.4(postcss@8.4.14)(ts-node@10.9.1) - postcss-nested: 5.0.6(postcss@8.4.14) + postcss: 8.4.32 + postcss-import: 14.1.0(postcss@8.4.32) + postcss-js: 4.0.1(postcss@8.4.32) + postcss-load-config: 3.1.4(postcss@8.4.32)(ts-node@10.9.1) + postcss-nested: 5.0.6(postcss@8.4.32) postcss-selector-parser: 6.0.13 postcss-value-parser: 4.2.0 quick-lru: 5.1.1 @@ -4874,7 +4891,6 @@ packages: /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} @@ -5034,7 +5050,6 @@ packages: /url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} - dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -5163,7 +5178,6 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} @@ -5179,7 +5193,6 @@ packages: /whatwg-fetch@3.6.2: resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} - dev: true /whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} @@ -5191,7 +5204,6 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} From aba9d5dbb6d948d3d8ef0bc30c3fd771fa772e2b Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 20 Dec 2023 16:19:10 +0200 Subject: [PATCH 03/20] - Wait for metamask (3 retries) --- packages/core/src/wallet/metamaskBridge.ts | 32 +++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index 320b34e..a024d4e 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -1,7 +1,29 @@ import type { MetaMaskProvider } from '@consensys/get-starknet/dist/type'; import detectEthereumProvider from '@metamask/detect-provider'; -async function hasSnapSupport(provider: any) { +async function waitForEthereumProvider(options: { timeout?: number, retries?: number } = {}): Promise { + const { timeout = 3000, retries = 0 } = options; + + let provider: MetaMaskProvider | null = null; + try { + provider = await detectEthereumProvider({ timeout }); + } catch { + // Silent error - do nothing + } + + if (provider) { + return provider; + } + + if (retries === 0) { + return null; + } + + provider = await waitForEthereumProvider({ timeout, retries: retries - 1 }) + return provider; +} + +async function hasSnapSupport(provider: MetaMaskProvider) { try { await provider.request({ method: "wallet_getSnaps", @@ -17,7 +39,9 @@ async function bootstrapMetamaskBridge() { return; } - const provider = await detectEthereumProvider() + let provider: MetaMaskProvider | null = null; + + provider = await waitForEthereumProvider({ retries: 3 }) if (!provider) { return; } @@ -27,8 +51,8 @@ async function bootstrapMetamaskBridge() { return; } - const {MetaMaskSnapWallet} = await import('@consensys/get-starknet') + const { MetaMaskSnapWallet } = await import('@consensys/get-starknet') window["starknet_metamask"] = new MetaMaskSnapWallet(provider) } -export {bootstrapMetamaskBridge} \ No newline at end of file +export { bootstrapMetamaskBridge } \ No newline at end of file From 0706e1145ada647e02dc9f41b1e8d4ecb7411029 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Mon, 15 Jan 2024 17:35:41 +0200 Subject: [PATCH 04/20] - Set build target to es2020 (the same as snjs) --- example/vite.config.ts | 4 ++++ packages/core/vite.config.ts | 2 ++ packages/ui/vite.config.ts | 2 ++ 3 files changed, 8 insertions(+) diff --git a/example/vite.config.ts b/example/vite.config.ts index dc52590..1daa1dd 100644 --- a/example/vite.config.ts +++ b/example/vite.config.ts @@ -3,5 +3,9 @@ import { defineConfig } from "vite" // https://vitejs.dev/config/ export default defineConfig({ + build: { + target: 'es2020' + }, plugins: [react()], + optimizeDeps: { esbuildOptions: { target: 'es2020' } } }) diff --git a/packages/core/vite.config.ts b/packages/core/vite.config.ts index dd2321f..57fbc58 100644 --- a/packages/core/vite.config.ts +++ b/packages/core/vite.config.ts @@ -17,6 +17,7 @@ export default defineConfig({ // the proper extensions will be added fileName: "core", }, + target: 'es2020' }, plugins: [ dts({ @@ -31,4 +32,5 @@ export default defineConfig({ exclude: ["**/node_modules/**", "**/*.mock.ts"], }, }, + optimizeDeps: { esbuildOptions: { target: 'es2020' } } }) diff --git a/packages/ui/vite.config.ts b/packages/ui/vite.config.ts index 36a0ff0..97e8231 100644 --- a/packages/ui/vite.config.ts +++ b/packages/ui/vite.config.ts @@ -13,6 +13,7 @@ export default defineConfig({ // the proper extensions will be added fileName: "ui", }, + target: 'es2020' }, plugins: [ svelte({ emitCss: false }), @@ -21,4 +22,5 @@ export default defineConfig({ insertTypesEntry: true, }), ], + optimizeDeps: { esbuildOptions: { target: 'es2020' } } }) From 2db83dfc5506918aed561091f09f105c5bbf31f2 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Mon, 15 Jan 2024 17:36:13 +0200 Subject: [PATCH 05/20] - Fix starknet_metamask definition --- packages/core/src/StarknetWindowObject.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 96c98b9..3192900 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -3,7 +3,6 @@ import type { AccountInterface as AccountInterfaceV4, ProviderInterface as ProviderInterfaceV4, } from "starknet4" -import type { MetaMaskSnapWallet } from '@consensys/get-starknet'; export type AccountChangeEventHandler = (accounts: string[]) => void @@ -119,7 +118,7 @@ declare global { starknet?: StarknetWindowObject starknet_braavos?: StarknetWindowObject starknet_argentX?: StarknetWindowObject - starknet_metamask?: MetaMaskSnapWallet + starknet_metamask?: StarknetWindowObject [key: `starknet_${string}`]: StarknetWindowObject | undefined } } From d7308abbe5591f63748f8620c29ead11e87acdf9 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Mon, 15 Jan 2024 17:38:37 +0200 Subject: [PATCH 06/20] - Change metamask bridge strategy - Show metamask if there is metamask extension with snap support - Load consensys metamask package if the user selects metamask from the list --- packages/core/src/main.ts | 4 +- packages/core/src/wallet/metamaskBridge.ts | 75 ++++++++++++++++++---- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 892378f..51e84a7 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -7,7 +7,7 @@ import { IStorageWrapper, LocalStorageWrapper } from "./localStorageStore" import { pipe } from "./utils" import { FilterList, filterBy, filterByPreAuthorized } from "./wallet/filter" import { isWalletObj } from "./wallet/isWalletObject" -import { bootstrapMetamaskBridge } from "./wallet/metamaskBridge" +import { injectMetamaskBridge } from "./wallet/metamaskBridge" import { scanObjectForWallets } from "./wallet/scan" import { Sort, sortBy } from "./wallet/sort" @@ -76,7 +76,7 @@ export function getStarknet( } const lastConnectedStore = storageFactoryImplementation("gsw-last") - bootstrapMetamaskBridge(); + injectMetamaskBridge(); return { getAvailableWallets: async (options = {}) => { diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index a024d4e..d4088cd 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -1,12 +1,50 @@ -import type { MetaMaskProvider } from '@consensys/get-starknet/dist/type'; import detectEthereumProvider from '@metamask/detect-provider'; +import wallets, { WalletProvider } from '../discovery'; +import type { MetaMaskProvider } from '@consensys/get-starknet/dist/type'; +import { DisconnectedStarknetWindowObject, RpcMessage } from '../StarknetWindowObject'; +import type { ProviderInterface } from "starknet" + +class EmptyMetaMaskProvider implements DisconnectedStarknetWindowObject { + id: string; + name: string; + icon: string; + version = '0.0.0'; + isConnected = false as const; + provider: undefined | ProviderInterface; + constructor(private metamaskProvider: MetaMaskProvider, walletInfo: WalletProvider) { + this.id = walletInfo.id; + this.name = walletInfo.name; + this.icon = walletInfo.icon; + } + request(): Promise { + throw new Error('Wallet not enabled'); + } + async enable(options?: { starknetVersion?: "v4" | "v5" }): Promise { + const { MetaMaskSnapWallet } = await import('@consensys/get-starknet') + const metaMaskSnapWallet = new MetaMaskSnapWallet(this.metamaskProvider); + + Object.assign(this, metaMaskSnapWallet); + this.constructor.prototype = metaMaskSnapWallet.constructor.prototype; + + return await this.enable(options); + } + isPreauthorized() { + return Promise.resolve(false); + } + on() { + throw new Error('Wallet not enabled'); + } + off() { + throw new Error('Wallet not enabled'); + } +} async function waitForEthereumProvider(options: { timeout?: number, retries?: number } = {}): Promise { const { timeout = 3000, retries = 0 } = options; let provider: MetaMaskProvider | null = null; try { - provider = await detectEthereumProvider({ timeout }); + provider = await detectEthereumProvider({ timeout }); } catch { // Silent error - do nothing } @@ -25,34 +63,43 @@ async function waitForEthereumProvider(options: { timeout?: number, retries?: nu async function hasSnapSupport(provider: MetaMaskProvider) { try { - await provider.request({ - method: "wallet_getSnaps", - }) + await provider.request({ method: "wallet_getSnaps" }); return true } catch { return false } } -async function bootstrapMetamaskBridge() { +async function detectMetamaskSupport() { + const provider = await waitForEthereumProvider({ retries: 3 }) + if (!provider) { + return null; + } + + const snapSupport = await hasSnapSupport(provider) + if (!snapSupport) { + return null; + } + + return provider; +} + +async function injectMetamaskBridge() { if (window.hasOwnProperty("starknet_metamask")) { return; } - let provider: MetaMaskProvider | null = null; - - provider = await waitForEthereumProvider({ retries: 3 }) + const provider = await detectMetamaskSupport(); if (!provider) { return; } - const snapSupport = await hasSnapSupport(provider) - if (!snapSupport) { + const metamaskWalletInfo = wallets.find(wallet => wallet.id === "metamask"); + if (!metamaskWalletInfo) { return; } - const { MetaMaskSnapWallet } = await import('@consensys/get-starknet') - window["starknet_metamask"] = new MetaMaskSnapWallet(provider) + window.starknet_metamask = new EmptyMetaMaskProvider(provider, metamaskWalletInfo); } -export { bootstrapMetamaskBridge } \ No newline at end of file +export { injectMetamaskBridge } \ No newline at end of file From d5c025e5cafbd60f74d30deb79e01a61c1efba2a Mon Sep 17 00:00:00 2001 From: NaorYe Date: Mon, 15 Jan 2024 17:40:33 +0200 Subject: [PATCH 07/20] - Format --- example/vite.config.ts | 4 +- packages/core/package.json | 8 +- packages/core/src/StarknetWindowObject.ts | 36 ++++---- packages/core/src/discovery.ts | 4 +- packages/core/src/main.ts | 2 +- packages/core/src/wallet/metamaskBridge.ts | 95 ++++++++++++---------- packages/core/vite.config.ts | 4 +- packages/ui/vite.config.ts | 4 +- 8 files changed, 84 insertions(+), 73 deletions(-) diff --git a/example/vite.config.ts b/example/vite.config.ts index 1daa1dd..8a495a6 100644 --- a/example/vite.config.ts +++ b/example/vite.config.ts @@ -4,8 +4,8 @@ import { defineConfig } from "vite" // https://vitejs.dev/config/ export default defineConfig({ build: { - target: 'es2020' + target: "es2020", }, plugins: [react()], - optimizeDeps: { esbuildOptions: { target: 'es2020' } } + optimizeDeps: { esbuildOptions: { target: "es2020" } }, }) diff --git a/packages/core/package.json b/packages/core/package.json index 29fa54d..9dd7b59 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -29,6 +29,10 @@ "dev": "vite build --watch", "test": "vitest" }, + "dependencies": { + "@consensys/get-starknet": "1.0.0-dev-998a4b7-202312151810", + "@metamask/detect-provider": "^2.0.0" + }, "devDependencies": { "c8": "^7.12.0", "happy-dom": "^6.0.4", @@ -46,9 +50,5 @@ "starknet": { "optional": false } - }, - "dependencies": { - "@consensys/get-starknet": "1.0.0-dev-998a4b7-202312151810", - "@metamask/detect-provider": "^2.0.0" } } diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 3192900..01e7035 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -10,13 +10,13 @@ export type NetworkChangeEventHandler = (network?: string) => void export type WalletEvents = | { - type: "accountsChanged" - handler: AccountChangeEventHandler - } + type: "accountsChanged" + handler: AccountChangeEventHandler + } | { - type: "networkChanged" - handler: NetworkChangeEventHandler - } + type: "networkChanged" + handler: NetworkChangeEventHandler + } // EIP-747: // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-747.md @@ -57,20 +57,20 @@ export interface SwitchStarknetChainParameter { export type RpcMessage = | { - type: "wallet_watchAsset" - params: WatchAssetParameters - result: boolean - } + type: "wallet_watchAsset" + params: WatchAssetParameters + result: boolean + } | { - type: "wallet_addStarknetChain" - params: AddStarknetChainParameters - result: boolean - } + type: "wallet_addStarknetChain" + params: AddStarknetChainParameters + result: boolean + } | { - type: "wallet_switchStarknetChain" - params: SwitchStarknetChainParameter - result: boolean - } + type: "wallet_switchStarknetChain" + params: SwitchStarknetChainParameter + result: boolean + } export interface IStarknetWindowObject { id: string diff --git a/packages/core/src/discovery.ts b/packages/core/src/discovery.ts index dfb1d30..f445039 100644 --- a/packages/core/src/discovery.ts +++ b/packages/core/src/discovery.ts @@ -39,8 +39,8 @@ const wallets: WalletProvider[] = [ "https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn", firefox: "https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/", edge: "https://microsoftedge.microsoft.com/addons/detail/metamask/ejbalbakoplchlghecdalmeeeajnimhm?hl=en-US", - } - } + }, + }, ] export default wallets diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 51e84a7..429442b 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -76,7 +76,7 @@ export function getStarknet( } const lastConnectedStore = storageFactoryImplementation("gsw-last") - injectMetamaskBridge(); + injectMetamaskBridge() return { getAvailableWallets: async (options = {}) => { diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index d4088cd..3473699 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -1,69 +1,77 @@ -import detectEthereumProvider from '@metamask/detect-provider'; -import wallets, { WalletProvider } from '../discovery'; -import type { MetaMaskProvider } from '@consensys/get-starknet/dist/type'; -import { DisconnectedStarknetWindowObject, RpcMessage } from '../StarknetWindowObject'; +import { + DisconnectedStarknetWindowObject, + RpcMessage, +} from "../StarknetWindowObject" +import wallets, { WalletProvider } from "../discovery" +import type { MetaMaskProvider } from "@consensys/get-starknet/dist/type" +import detectEthereumProvider from "@metamask/detect-provider" import type { ProviderInterface } from "starknet" class EmptyMetaMaskProvider implements DisconnectedStarknetWindowObject { - id: string; - name: string; - icon: string; - version = '0.0.0'; - isConnected = false as const; - provider: undefined | ProviderInterface; - constructor(private metamaskProvider: MetaMaskProvider, walletInfo: WalletProvider) { - this.id = walletInfo.id; - this.name = walletInfo.name; - this.icon = walletInfo.icon; + id: string + name: string + icon: string + version = "0.0.0" + isConnected = false as const + provider: undefined | ProviderInterface + constructor( + private metamaskProvider: MetaMaskProvider, + walletInfo: WalletProvider, + ) { + this.id = walletInfo.id + this.name = walletInfo.name + this.icon = walletInfo.icon } request(): Promise { - throw new Error('Wallet not enabled'); + throw new Error("Wallet not enabled") } async enable(options?: { starknetVersion?: "v4" | "v5" }): Promise { - const { MetaMaskSnapWallet } = await import('@consensys/get-starknet') - const metaMaskSnapWallet = new MetaMaskSnapWallet(this.metamaskProvider); - - Object.assign(this, metaMaskSnapWallet); - this.constructor.prototype = metaMaskSnapWallet.constructor.prototype; + const { MetaMaskSnapWallet } = await import("@consensys/get-starknet") + const metaMaskSnapWallet = new MetaMaskSnapWallet(this.metamaskProvider) - return await this.enable(options); + Object.assign(this, metaMaskSnapWallet) + this.constructor.prototype = metaMaskSnapWallet.constructor.prototype + + return await this.enable(options) } isPreauthorized() { - return Promise.resolve(false); + return Promise.resolve(false) } on() { - throw new Error('Wallet not enabled'); + throw new Error("Wallet not enabled") } off() { - throw new Error('Wallet not enabled'); + throw new Error("Wallet not enabled") } } -async function waitForEthereumProvider(options: { timeout?: number, retries?: number } = {}): Promise { - const { timeout = 3000, retries = 0 } = options; +async function waitForEthereumProvider( + options: { timeout?: number; retries?: number } = {}, +): Promise { + const { timeout = 3000, retries = 0 } = options - let provider: MetaMaskProvider | null = null; + let provider: MetaMaskProvider | null = null try { - provider = await detectEthereumProvider({ timeout }); + provider = await detectEthereumProvider({ timeout }) } catch { // Silent error - do nothing } if (provider) { - return provider; + return provider } if (retries === 0) { - return null; + return null } provider = await waitForEthereumProvider({ timeout, retries: retries - 1 }) - return provider; + return provider } async function hasSnapSupport(provider: MetaMaskProvider) { try { - await provider.request({ method: "wallet_getSnaps" }); + await provider.request({ method: "wallet_getSnaps" }) return true } catch { return false @@ -73,33 +81,36 @@ async function hasSnapSupport(provider: MetaMaskProvider) { async function detectMetamaskSupport() { const provider = await waitForEthereumProvider({ retries: 3 }) if (!provider) { - return null; + return null } const snapSupport = await hasSnapSupport(provider) if (!snapSupport) { - return null; + return null } - return provider; + return provider } async function injectMetamaskBridge() { if (window.hasOwnProperty("starknet_metamask")) { - return; + return } - const provider = await detectMetamaskSupport(); + const provider = await detectMetamaskSupport() if (!provider) { - return; + return } - const metamaskWalletInfo = wallets.find(wallet => wallet.id === "metamask"); + const metamaskWalletInfo = wallets.find((wallet) => wallet.id === "metamask") if (!metamaskWalletInfo) { - return; + return } - window.starknet_metamask = new EmptyMetaMaskProvider(provider, metamaskWalletInfo); + window.starknet_metamask = new EmptyMetaMaskProvider( + provider, + metamaskWalletInfo, + ) } -export { injectMetamaskBridge } \ No newline at end of file +export { injectMetamaskBridge } diff --git a/packages/core/vite.config.ts b/packages/core/vite.config.ts index 57fbc58..9c8528c 100644 --- a/packages/core/vite.config.ts +++ b/packages/core/vite.config.ts @@ -17,7 +17,7 @@ export default defineConfig({ // the proper extensions will be added fileName: "core", }, - target: 'es2020' + target: "es2020", }, plugins: [ dts({ @@ -32,5 +32,5 @@ export default defineConfig({ exclude: ["**/node_modules/**", "**/*.mock.ts"], }, }, - optimizeDeps: { esbuildOptions: { target: 'es2020' } } + optimizeDeps: { esbuildOptions: { target: "es2020" } }, }) diff --git a/packages/ui/vite.config.ts b/packages/ui/vite.config.ts index 97e8231..549883c 100644 --- a/packages/ui/vite.config.ts +++ b/packages/ui/vite.config.ts @@ -13,7 +13,7 @@ export default defineConfig({ // the proper extensions will be added fileName: "ui", }, - target: 'es2020' + target: "es2020", }, plugins: [ svelte({ emitCss: false }), @@ -22,5 +22,5 @@ export default defineConfig({ insertTypesEntry: true, }), ], - optimizeDeps: { esbuildOptions: { target: 'es2020' } } + optimizeDeps: { esbuildOptions: { target: "es2020" } }, }) From f4e01556cca179f29a9dc6125ed868157af8ce6e Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 6 Mar 2024 15:09:08 +0200 Subject: [PATCH 08/20] - Add version --- packages/core/src/wallet/metamaskBridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index 3473699..931fed9 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -27,7 +27,7 @@ class EmptyMetaMaskProvider implements DisconnectedStarknetWindowObject { } async enable(options?: { starknetVersion?: "v4" | "v5" }): Promise { const { MetaMaskSnapWallet } = await import("@consensys/get-starknet") - const metaMaskSnapWallet = new MetaMaskSnapWallet(this.metamaskProvider) + const metaMaskSnapWallet = new MetaMaskSnapWallet(this.metamaskProvider, "*") Object.assign(this, metaMaskSnapWallet) this.constructor.prototype = metaMaskSnapWallet.constructor.prototype From 8fb30cdf76e5a609e470d1dbada6ac5a82b1d76f Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 6 Mar 2024 15:23:56 +0200 Subject: [PATCH 09/20] - Upgrade @consensys/get-starknet and fix type --- packages/core/package.json | 2 +- packages/core/src/wallet/metamaskBridge.ts | 2 +- pnpm-lock.yaml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 9dd7b59..1fea02f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -30,7 +30,7 @@ "test": "vitest" }, "dependencies": { - "@consensys/get-starknet": "1.0.0-dev-998a4b7-202312151810", + "@consensys/get-starknet": "1.0.0-dev-fc04076-202312205118", "@metamask/detect-provider": "^2.0.0" }, "devDependencies": { diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index 931fed9..d2318f3 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -3,7 +3,7 @@ import { RpcMessage, } from "../StarknetWindowObject" import wallets, { WalletProvider } from "../discovery" -import type { MetaMaskProvider } from "@consensys/get-starknet/dist/type" +import type { MetaMaskProvider } from "@consensys/get-starknet" import detectEthereumProvider from "@metamask/detect-provider" import type { ProviderInterface } from "starknet" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9f21e56..e1ecd27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,8 +67,8 @@ importers: packages/core: dependencies: '@consensys/get-starknet': - specifier: 1.0.0-dev-998a4b7-202312151810 - version: 1.0.0-dev-998a4b7-202312151810 + specifier: 1.0.0-dev-fc04076-202312205118 + version: 1.0.0-dev-fc04076-202312205118 '@metamask/detect-provider': specifier: ^2.0.0 version: 2.0.0 @@ -869,8 +869,8 @@ packages: chalk: 4.1.2 dev: true - /@consensys/get-starknet@1.0.0-dev-998a4b7-202312151810: - resolution: {integrity: sha512-CzywgXiQTkhgrcYs2uMtMGU8IebbP1x8Z1z6mvd9MQYEFG/6UTQ/u6u86RcopXYt41MJOry5kYtjZMcYLSRAhA==} + /@consensys/get-starknet@1.0.0-dev-fc04076-202312205118: + resolution: {integrity: sha512-s2GoDFR/sPedfhQsv0F7Y8AwQEWTOVueTlmd4Ks8C5/FwHE9GoY+Vh3lNW49YJYhFVkXvjPzK4bb8270kPv6Uw==} dependencies: starknet: 5.18.0 transitivePeerDependencies: From a299ff57f3f85e451bc7ca032ce0c5bcb402755b Mon Sep 17 00:00:00 2001 From: NaorYe Date: Thu, 7 Mar 2024 12:45:39 +0200 Subject: [PATCH 10/20] - Fix @consensys/get-starknet version to support patch updates --- packages/core/package.json | 2 +- pnpm-lock.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 1fea02f..b66a0d0 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -30,7 +30,7 @@ "test": "vitest" }, "dependencies": { - "@consensys/get-starknet": "1.0.0-dev-fc04076-202312205118", + "@consensys/get-starknet": "^1.0.0-dev-fc04076-202312205118", "@metamask/detect-provider": "^2.0.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1ecd27..82bd150 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,7 +67,7 @@ importers: packages/core: dependencies: '@consensys/get-starknet': - specifier: 1.0.0-dev-fc04076-202312205118 + specifier: ^1.0.0-dev-fc04076-202312205118 version: 1.0.0-dev-fc04076-202312205118 '@metamask/detect-provider': specifier: ^2.0.0 From e5cd51368ce412cb7b41cdf96e9cee14f0f16e3e Mon Sep 17 00:00:00 2001 From: NaorYe Date: Thu, 7 Mar 2024 12:46:05 +0200 Subject: [PATCH 11/20] - Fix implementation to wrapper provider --- packages/core/src/StarknetWindowObject.ts | 1 + packages/core/src/wallet/metamaskBridge.ts | 101 +++++++++++++-------- 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/packages/core/src/StarknetWindowObject.ts b/packages/core/src/StarknetWindowObject.ts index 01e7035..cd97aaa 100644 --- a/packages/core/src/StarknetWindowObject.ts +++ b/packages/core/src/StarknetWindowObject.ts @@ -94,6 +94,7 @@ export interface IStarknetWindowObject { provider?: ProviderInterface | ProviderInterfaceV4 selectedAddress?: string chainId?: string + isConnected: boolean } export interface ConnectedStarknetWindowObject extends IStarknetWindowObject { diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index d2318f3..55c19d2 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -1,50 +1,73 @@ -import { - DisconnectedStarknetWindowObject, +import type { + IStarknetWindowObject, RpcMessage, + StarknetWindowObject, + WalletEvents, } from "../StarknetWindowObject" import wallets, { WalletProvider } from "../discovery" -import type { MetaMaskProvider } from "@consensys/get-starknet" +import type { MetaMaskProvider, MetaMaskSnapWallet } from "@consensys/get-starknet" import detectEthereumProvider from "@metamask/detect-provider" -import type { ProviderInterface } from "starknet" - -class EmptyMetaMaskProvider implements DisconnectedStarknetWindowObject { - id: string - name: string - icon: string - version = "0.0.0" - isConnected = false as const - provider: undefined | ProviderInterface - constructor( - private metamaskProvider: MetaMaskProvider, - walletInfo: WalletProvider, - ) { - this.id = walletInfo.id - this.name = walletInfo.name - this.icon = walletInfo.icon - } - request(): Promise { - throw new Error("Wallet not enabled") - } - async enable(options?: { starknetVersion?: "v4" | "v5" }): Promise { - const { MetaMaskSnapWallet } = await import("@consensys/get-starknet") - const metaMaskSnapWallet = new MetaMaskSnapWallet(this.metamaskProvider, "*") - Object.assign(this, metaMaskSnapWallet) - this.constructor.prototype = metaMaskSnapWallet.constructor.prototype - return await this.enable(options) - } - isPreauthorized() { - return Promise.resolve(false) - } - on() { - throw new Error("Wallet not enabled") - } - off() { - throw new Error("Wallet not enabled") +function createMetaMaskProviderWrapper(metamaskProvider: MetaMaskProvider, walletInfo: WalletProvider): StarknetWindowObject { + let metaMaskSnapWallet: MetaMaskSnapWallet | undefined; + const metaMaskProviderWrapper: IStarknetWindowObject = { + id: walletInfo.id, + name: walletInfo.name, + icon: walletInfo.icon, + get version() { + return metaMaskSnapWallet?.version ?? "0.0.0" + }, + get isConnected() { + return metaMaskSnapWallet?.isConnected ?? false; + }, + get provider() { + return metaMaskSnapWallet?.provider + }, + get account() { + return metaMaskSnapWallet?.account; + }, + get selectedAddress() { + return metaMaskSnapWallet?.selectedAddress; + }, + get chainId() { + return metaMaskSnapWallet?.chainId; + }, + request(call: Omit): Promise { + if (!metaMaskSnapWallet) { + throw new Error("Wallet not enabled") + } + return metaMaskSnapWallet.request(call); + }, + async enable(): Promise { + const { MetaMaskSnapWallet } = await import("@consensys/get-starknet") + metaMaskSnapWallet = new MetaMaskSnapWallet(metamaskProvider, "*") + + return await metaMaskSnapWallet.enable() + }, + isPreauthorized() { + return metaMaskSnapWallet?.isPreauthorized() ?? Promise.resolve(false) + }, + on(event: E["type"], handleEvent: E["handler"],): void { + if (!metaMaskSnapWallet) { + throw new Error("Wallet not enabled"); + } + // @ts-ignore: Metamask currently doesn't support on method + return metaMaskSnapWallet.on(event, handleEvent); + }, + off(event: E["type"], handleEvent: E["handler"],) { + if (!metaMaskSnapWallet) { + throw new Error("Wallet not enabled"); + } + // @ts-ignore: Metamask currently doesn't support off method + return metaMaskSnapWallet.off(event, handleEvent); + } } + + return metaMaskProviderWrapper as StarknetWindowObject; } + async function waitForEthereumProvider( options: { timeout?: number; retries?: number } = {}, ): Promise { @@ -107,7 +130,7 @@ async function injectMetamaskBridge() { return } - window.starknet_metamask = new EmptyMetaMaskProvider( + window.starknet_metamask = createMetaMaskProviderWrapper( provider, metamaskWalletInfo, ) From 537b0b2d6981b806cae9d8b6a4e83afdbf5dd9f1 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Tue, 9 Apr 2024 14:02:46 +0300 Subject: [PATCH 12/20] - Remove metamask related dependencies - Add @module-federation/runtime --- packages/core/package.json | 3 +- pnpm-lock.yaml | 113 ++++++++++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 21 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index b66a0d0..4b85d9a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -30,8 +30,7 @@ "test": "vitest" }, "dependencies": { - "@consensys/get-starknet": "^1.0.0-dev-fc04076-202312205118", - "@metamask/detect-provider": "^2.0.0" + "@module-federation/runtime": "^0.1.2" }, "devDependencies": { "c8": "^7.12.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 82bd150..be4aeea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -66,12 +66,9 @@ importers: packages/core: dependencies: - '@consensys/get-starknet': - specifier: ^1.0.0-dev-fc04076-202312205118 - version: 1.0.0-dev-fc04076-202312205118 - '@metamask/detect-provider': - specifier: ^2.0.0 - version: 2.0.0 + '@module-federation/runtime': + specifier: ^0.1.2 + version: 0.1.2 devDependencies: c8: specifier: ^7.12.0 @@ -93,7 +90,7 @@ importers: version: 3.0.0 vite-plugin-dts: specifier: ^1.4.0 - version: 1.4.0(@types/node@20.3.1)(vite@3.0.0) + version: 1.4.0(vite@3.0.0) vitest: specifier: ^0.19.1 version: 0.19.1(c8@7.12.0)(happy-dom@6.0.4) @@ -869,14 +866,6 @@ packages: chalk: 4.1.2 dev: true - /@consensys/get-starknet@1.0.0-dev-fc04076-202312205118: - resolution: {integrity: sha512-s2GoDFR/sPedfhQsv0F7Y8AwQEWTOVueTlmd4Ks8C5/FwHE9GoY+Vh3lNW49YJYhFVkXvjPzK4bb8270kPv6Uw==} - dependencies: - starknet: 5.18.0 - transitivePeerDependencies: - - encoding - dev: false - /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -974,10 +963,15 @@ packages: read-yaml-file: 1.1.0 dev: true - /@metamask/detect-provider@2.0.0: - resolution: {integrity: sha512-sFpN+TX13E9fdBDh9lvQeZdJn4qYoRb/6QF2oZZK/Pn559IhCFacPMU1rMuqyXoFQF3JSJfii2l98B87QDPeCQ==} - engines: {node: '>=14.0.0'} - dev: false + /@microsoft/api-extractor-model@7.27.3: + resolution: {integrity: sha512-fSFvw7otYHduOkyshjTbapKKgwF8bgquVHvgF8VgeKtMYvqXkoaj7W6VcM7PNY7E2bbblhUgC4XNdqZLD4SJGw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.59.4 + transitivePeerDependencies: + - '@types/node' + dev: true /@microsoft/api-extractor-model@7.27.3(@types/node@20.3.1): resolution: {integrity: sha512-fSFvw7otYHduOkyshjTbapKKgwF8bgquVHvgF8VgeKtMYvqXkoaj7W6VcM7PNY7E2bbblhUgC4XNdqZLD4SJGw==} @@ -989,6 +983,26 @@ packages: - '@types/node' dev: true + /@microsoft/api-extractor@7.36.0: + resolution: {integrity: sha512-P+kYgJFDXIr+UNzhRMhlpM/dderi6ab4lxn35vdhfAIMPtGCSXIJxrrtpTOQmQW8CZtmoZX06LYoUsKCc1zjow==} + hasBin: true + dependencies: + '@microsoft/api-extractor-model': 7.27.3 + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.59.4 + '@rushstack/rig-package': 0.4.0 + '@rushstack/ts-command-line': 4.15.1 + colors: 1.2.5 + lodash: 4.17.21 + resolve: 1.22.2 + semver: 7.3.8 + source-map: 0.6.1 + typescript: 5.0.4 + transitivePeerDependencies: + - '@types/node' + dev: true + /@microsoft/api-extractor@7.36.0(@types/node@20.3.1): resolution: {integrity: sha512-P+kYgJFDXIr+UNzhRMhlpM/dderi6ab4lxn35vdhfAIMPtGCSXIJxrrtpTOQmQW8CZtmoZX06LYoUsKCc1zjow==} hasBin: true @@ -1022,10 +1036,21 @@ packages: resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} dev: true + /@module-federation/runtime@0.1.2: + resolution: {integrity: sha512-KdTL2aR48p+hOdMuim5osN15xkxzm1ccyXnvqR6TSl61r+chq7qFhU124JQYDU/SSkmbRm7Fb53IaaXo/PjKQw==} + dependencies: + '@module-federation/sdk': 0.1.2 + dev: false + + /@module-federation/sdk@0.1.2: + resolution: {integrity: sha512-G9af5sV/yyz5EpHOpg+y5gtDxomT6T1c7KETMs9k76GOcHKGBAoqiC8RJimgncN6O2wPhiBKEvNjf9VxrrX+gw==} + dev: false + /@noble/curves@1.0.0: resolution: {integrity: sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==} dependencies: '@noble/hashes': 1.3.0 + dev: true /@noble/hashes@1.2.0: resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} @@ -1033,10 +1058,12 @@ packages: /@noble/hashes@1.3.0: resolution: {integrity: sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==} + dev: true /@noble/hashes@1.3.1: resolution: {integrity: sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==} engines: {node: '>= 16'} + dev: true /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} @@ -1071,6 +1098,23 @@ packages: picomatch: 2.3.1 dev: true + /@rushstack/node-core-library@3.59.4: + resolution: {integrity: sha512-YAKJDC6Mz/KA1D7bvB88WaRX3knt/ZuLzkRu5G9QADGSjLtvTWzCNCytRF2PCSaaHOZaZsWul4F1KQdgFgUDqA==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.2 + semver: 7.3.8 + z-schema: 5.0.5 + dev: true + /@rushstack/node-core-library@3.59.4(@types/node@20.3.1): resolution: {integrity: sha512-YAKJDC6Mz/KA1D7bvB88WaRX3knt/ZuLzkRu5G9QADGSjLtvTWzCNCytRF2PCSaaHOZaZsWul4F1KQdgFgUDqA==} peerDependencies: @@ -1822,6 +1866,7 @@ packages: /commander@9.5.0: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} + requiresBuild: true dev: true /compare-func@2.0.0: @@ -3156,6 +3201,7 @@ packages: whatwg-fetch: 3.6.2 transitivePeerDependencies: - encoding + dev: true /istanbul-lib-coverage@3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} @@ -3416,6 +3462,7 @@ packages: /lossless-json@2.0.9: resolution: {integrity: sha512-PUfJ5foxULG1x/dXpSckmt0woBDqyq/WFoI885vEqjGwuP41K2EBYh2IT3zYx9dWqcTLIfXiCE5AjhF1jk9Sbg==} + dev: true /loupe@2.3.6: resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} @@ -3525,6 +3572,7 @@ packages: dependencies: '@noble/curves': 1.0.0 '@noble/hashes': 1.3.1 + dev: true /micromatch@4.0.5: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} @@ -3644,6 +3692,7 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 + dev: true /node-releases@2.0.12: resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} @@ -3799,6 +3848,7 @@ packages: /pako@2.1.0: resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} + dev: true /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} @@ -4544,6 +4594,7 @@ packages: url-join: 4.0.1 transitivePeerDependencies: - encoding + dev: true /stream-transform@2.1.3: resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} @@ -4891,6 +4942,7 @@ packages: /tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: true /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} @@ -5050,6 +5102,7 @@ packages: /url-join@4.0.1: resolution: {integrity: sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==} + dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -5099,6 +5152,25 @@ packages: - supports-color dev: true + /vite-plugin-dts@1.4.0(vite@3.0.0): + resolution: {integrity: sha512-RyDCjQzVxUeDqF+Rl1hQT+t/rKmvfvo04gaGV/l3597FpeIWGKtNF1S4x509Kx1AfHOjLa1JdmjVgnSEIv+lpw==} + engines: {node: '>=12.0.0'} + peerDependencies: + vite: '>=2.4.4' + dependencies: + '@microsoft/api-extractor': 7.36.0 + '@rushstack/node-core-library': 3.59.4 + chalk: 4.1.2 + debug: 4.3.4 + fast-glob: 3.2.12 + fs-extra: 10.1.0 + ts-morph: 14.0.0 + vite: 3.0.0 + transitivePeerDependencies: + - '@types/node' + - supports-color + dev: true + /vite@3.0.0: resolution: {integrity: sha512-M7phQhY3+fRZa0H+1WzI6N+/onruwPTBTMvaj7TzgZ0v2TE+N2sdLKxJOfOv9CckDWt5C4HmyQP81xB4dwRKzA==} engines: {node: '>=14.18.0'} @@ -5178,6 +5250,7 @@ packages: /webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: true /webidl-conversions@7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} @@ -5193,6 +5266,7 @@ packages: /whatwg-fetch@3.6.2: resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} + dev: true /whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} @@ -5204,6 +5278,7 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 + dev: true /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} From 71a9d0992d012cefd0bca7b626363f669d1e59e9 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Tue, 9 Apr 2024 14:20:51 +0300 Subject: [PATCH 13/20] - Fix matemaskBridge --- packages/core/src/wallet/metamaskBridge.ts | 186 ++++++++++++++------- 1 file changed, 123 insertions(+), 63 deletions(-) diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index 55c19d2..e08a82f 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -1,3 +1,4 @@ +import { loadRemote, init } from "@module-federation/runtime" import type { IStarknetWindowObject, RpcMessage, @@ -5,77 +6,55 @@ import type { WalletEvents, } from "../StarknetWindowObject" import wallets, { WalletProvider } from "../discovery" -import type { MetaMaskProvider, MetaMaskSnapWallet } from "@consensys/get-starknet" -import detectEthereumProvider from "@metamask/detect-provider" +interface MetaMaskProvider { + isMetaMask: boolean + request(options: { method: string }): Promise +} -function createMetaMaskProviderWrapper(metamaskProvider: MetaMaskProvider, walletInfo: WalletProvider): StarknetWindowObject { - let metaMaskSnapWallet: MetaMaskSnapWallet | undefined; - const metaMaskProviderWrapper: IStarknetWindowObject = { - id: walletInfo.id, - name: walletInfo.name, - icon: walletInfo.icon, - get version() { - return metaMaskSnapWallet?.version ?? "0.0.0" - }, - get isConnected() { - return metaMaskSnapWallet?.isConnected ?? false; - }, - get provider() { - return metaMaskSnapWallet?.provider - }, - get account() { - return metaMaskSnapWallet?.account; - }, - get selectedAddress() { - return metaMaskSnapWallet?.selectedAddress; - }, - get chainId() { - return metaMaskSnapWallet?.chainId; - }, - request(call: Omit): Promise { - if (!metaMaskSnapWallet) { - throw new Error("Wallet not enabled") - } - return metaMaskSnapWallet.request(call); - }, - async enable(): Promise { - const { MetaMaskSnapWallet } = await import("@consensys/get-starknet") - metaMaskSnapWallet = new MetaMaskSnapWallet(metamaskProvider, "*") +declare global { + interface Window { + ethereum?: MetaMaskProvider + } +} - return await metaMaskSnapWallet.enable() - }, - isPreauthorized() { - return metaMaskSnapWallet?.isPreauthorized() ?? Promise.resolve(false) - }, - on(event: E["type"], handleEvent: E["handler"],): void { - if (!metaMaskSnapWallet) { - throw new Error("Wallet not enabled"); +function detectMetaMaskProvider({ timeout = 3000 } = {}) { + let handled = false + return new Promise((resolve) => { + if (window.ethereum) { + handleEthereum() + } else { + window.addEventListener("ethereum#initialized", handleEthereum, { + once: true, + }) + setTimeout(() => { + handleEthereum() + }, timeout) + } + function handleEthereum() { + if (handled) { + return } - // @ts-ignore: Metamask currently doesn't support on method - return metaMaskSnapWallet.on(event, handleEvent); - }, - off(event: E["type"], handleEvent: E["handler"],) { - if (!metaMaskSnapWallet) { - throw new Error("Wallet not enabled"); + handled = true + window.removeEventListener("ethereum#initialized", handleEthereum) + const { ethereum } = window + if (ethereum && ethereum.isMetaMask) { + resolve(ethereum) + } else { + resolve(null) } - // @ts-ignore: Metamask currently doesn't support off method - return metaMaskSnapWallet.off(event, handleEvent); } - } - - return metaMaskProviderWrapper as StarknetWindowObject; + }) } - -async function waitForEthereumProvider( +async function waitForMetaMaskProvider( options: { timeout?: number; retries?: number } = {}, ): Promise { const { timeout = 3000, retries = 0 } = options let provider: MetaMaskProvider | null = null try { - provider = await detectEthereumProvider({ timeout }) + provider = await detectMetaMaskProvider({ timeout }) } catch { // Silent error - do nothing } @@ -88,7 +67,7 @@ async function waitForEthereumProvider( return null } - provider = await waitForEthereumProvider({ timeout, retries: retries - 1 }) + provider = await waitForMetaMaskProvider({ timeout, retries: retries - 1 }) return provider } @@ -102,7 +81,7 @@ async function hasSnapSupport(provider: MetaMaskProvider) { } async function detectMetamaskSupport() { - const provider = await waitForEthereumProvider({ retries: 3 }) + const provider = await waitForMetaMaskProvider({ retries: 3 }) if (!provider) { return null } @@ -115,6 +94,90 @@ async function detectMetamaskSupport() { return provider } +function createMetaMaskProviderWrapper( + walletInfo: WalletProvider, +): StarknetWindowObject { + let metaMaskSnapWallet: IStarknetWindowObject | undefined + const metaMaskProviderWrapper: IStarknetWindowObject = { + id: walletInfo.id, + name: walletInfo.name, + icon: walletInfo.icon, + get version() { + return metaMaskSnapWallet?.version ?? "0.0.0" + }, + get isConnected() { + return metaMaskSnapWallet?.isConnected ?? false + }, + get provider() { + return metaMaskSnapWallet?.provider + }, + get account() { + return metaMaskSnapWallet?.account + }, + get selectedAddress() { + return metaMaskSnapWallet?.selectedAddress + }, + get chainId() { + return metaMaskSnapWallet?.chainId + }, + request( + call: Omit, + ): Promise { + if (!metaMaskSnapWallet) { + throw new Error("Wallet not enabled") + } + return metaMaskSnapWallet.request(call) + }, + async enable(): Promise { + await init({ + name: "MetaMaskStarknetSnapWallet", + remotes: [ + { + name: "MetaMaskStarknetSnapWallet", + alias: "MetaMaskStarknetSnapWallet", + entry: + "https://s3.eu-central-1.amazonaws.com/dev.snaps.consensys.io/get-starknet/remoteEntry.js", + }, + ], + }) + + const result = await loadRemote("MetaMaskStarknetSnapWallet/index") + + const { MetaMaskSnapWallet, MetaMaskSnap } = result as { + MetaMaskSnapWallet: any + MetaMaskSnap: any + } + + const provider = await MetaMaskSnap.GetProvider(window) + const wallet = new MetaMaskSnapWallet(provider, "*") + + return await wallet.enable() + }, + isPreauthorized() { + return metaMaskSnapWallet?.isPreauthorized() ?? Promise.resolve(false) + }, + on( + event: E["type"], + handleEvent: E["handler"], + ): void { + if (!metaMaskSnapWallet) { + throw new Error("Wallet not enabled") + } + // @ts-ignore: Metamask currently doesn't support on method + return metaMaskSnapWallet.on(event, handleEvent) + }, + off(event: E["type"], handleEvent: E["handler"]) { + if (!metaMaskSnapWallet) { + throw new Error("Wallet not enabled") + } + // @ts-ignore: Metamask currently doesn't support off method + return metaMaskSnapWallet.off(event, handleEvent) + }, + } + + return metaMaskProviderWrapper as StarknetWindowObject +} + async function injectMetamaskBridge() { if (window.hasOwnProperty("starknet_metamask")) { return @@ -130,10 +193,7 @@ async function injectMetamaskBridge() { return } - window.starknet_metamask = createMetaMaskProviderWrapper( - provider, - metamaskWalletInfo, - ) + window.starknet_metamask = createMetaMaskProviderWrapper(metamaskWalletInfo) } export { injectMetamaskBridge } From 1b9d7f660c1848d466bf80ce841a063fc064f0eb Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 10 Apr 2024 12:09:05 +0300 Subject: [PATCH 14/20] - Fix implementation: cache wallet and utilize metaMaskSnapWallet --- packages/core/src/wallet/metamaskBridge.ts | 50 ++++++++++++---------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index e08a82f..b73ec4f 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -96,6 +96,7 @@ async function detectMetamaskSupport() { function createMetaMaskProviderWrapper( walletInfo: WalletProvider, + provider: unknown, ): StarknetWindowObject { let metaMaskSnapWallet: IStarknetWindowObject | undefined const metaMaskProviderWrapper: IStarknetWindowObject = { @@ -129,29 +130,30 @@ function createMetaMaskProviderWrapper( return metaMaskSnapWallet.request(call) }, async enable(): Promise { - await init({ - name: "MetaMaskStarknetSnapWallet", - remotes: [ - { - name: "MetaMaskStarknetSnapWallet", - alias: "MetaMaskStarknetSnapWallet", - entry: - "https://s3.eu-central-1.amazonaws.com/dev.snaps.consensys.io/get-starknet/remoteEntry.js", - }, - ], - }) - - const result = await loadRemote("MetaMaskStarknetSnapWallet/index") - - const { MetaMaskSnapWallet, MetaMaskSnap } = result as { - MetaMaskSnapWallet: any - MetaMaskSnap: any + if (!metaMaskSnapWallet) { + await init({ + name: "MetaMaskStarknetSnapWallet", + remotes: [ + { + name: "MetaMaskStarknetSnapWallet", + alias: "MetaMaskStarknetSnapWallet", + entry: + "https://s3.eu-central-1.amazonaws.com/dev.snaps.consensys.io/get-starknet/remoteEntry.js", + }, + ], + }) + + const result = await loadRemote("MetaMaskStarknetSnapWallet/index") + + const { MetaMaskSnapWallet } = result as { + MetaMaskSnapWallet: any + MetaMaskSnap: any + } + + metaMaskSnapWallet = new MetaMaskSnapWallet(provider, "*") } - const provider = await MetaMaskSnap.GetProvider(window) - const wallet = new MetaMaskSnapWallet(provider, "*") - - return await wallet.enable() + return await metaMaskSnapWallet!.enable() }, isPreauthorized() { return metaMaskSnapWallet?.isPreauthorized() ?? Promise.resolve(false) @@ -192,8 +194,10 @@ async function injectMetamaskBridge() { if (!metamaskWalletInfo) { return } - - window.starknet_metamask = createMetaMaskProviderWrapper(metamaskWalletInfo) + window.starknet_metamask = createMetaMaskProviderWrapper( + metamaskWalletInfo, + provider, + ) } export { injectMetamaskBridge } From 8f457adc4e97135dca1c1a91aa4c6a4ccb786c22 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 10 Apr 2024 14:24:39 +0300 Subject: [PATCH 15/20] - Remove unneeded configurations --- example/vite.config.ts | 4 ---- packages/core/vite.config.ts | 2 -- packages/ui/vite.config.ts | 2 -- 3 files changed, 8 deletions(-) diff --git a/example/vite.config.ts b/example/vite.config.ts index 8a495a6..dc52590 100644 --- a/example/vite.config.ts +++ b/example/vite.config.ts @@ -3,9 +3,5 @@ import { defineConfig } from "vite" // https://vitejs.dev/config/ export default defineConfig({ - build: { - target: "es2020", - }, plugins: [react()], - optimizeDeps: { esbuildOptions: { target: "es2020" } }, }) diff --git a/packages/core/vite.config.ts b/packages/core/vite.config.ts index 9c8528c..dd2321f 100644 --- a/packages/core/vite.config.ts +++ b/packages/core/vite.config.ts @@ -17,7 +17,6 @@ export default defineConfig({ // the proper extensions will be added fileName: "core", }, - target: "es2020", }, plugins: [ dts({ @@ -32,5 +31,4 @@ export default defineConfig({ exclude: ["**/node_modules/**", "**/*.mock.ts"], }, }, - optimizeDeps: { esbuildOptions: { target: "es2020" } }, }) diff --git a/packages/ui/vite.config.ts b/packages/ui/vite.config.ts index 549883c..36a0ff0 100644 --- a/packages/ui/vite.config.ts +++ b/packages/ui/vite.config.ts @@ -13,7 +13,6 @@ export default defineConfig({ // the proper extensions will be added fileName: "ui", }, - target: "es2020", }, plugins: [ svelte({ emitCss: false }), @@ -22,5 +21,4 @@ export default defineConfig({ insertTypesEntry: true, }), ], - optimizeDeps: { esbuildOptions: { target: "es2020" } }, }) From e6fb82bb5b961c0c85e8a8b423c5b77a5fbdb178 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Tue, 16 Apr 2024 21:12:24 +0300 Subject: [PATCH 16/20] - Remove snap check and use provided window --- packages/core/src/main.ts | 2 +- packages/core/src/wallet/metamaskBridge.ts | 71 ++++++++++------------ 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 429442b..245a96e 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -76,7 +76,7 @@ export function getStarknet( } const lastConnectedStore = storageFactoryImplementation("gsw-last") - injectMetamaskBridge() + injectMetamaskBridge(windowObject) return { getAvailableWallets: async (options = {}) => { diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index b73ec4f..3db27c5 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -6,27 +6,34 @@ import type { WalletEvents, } from "../StarknetWindowObject" import wallets, { WalletProvider } from "../discovery" - interface MetaMaskProvider { isMetaMask: boolean request(options: { method: string }): Promise } -declare global { - interface Window { - ethereum?: MetaMaskProvider - } +function isMetaMaskProvider(obj: unknown): obj is MetaMaskProvider { + return ( + obj !== null && + typeof obj === "object" && + obj.hasOwnProperty("isMetaMask") && + obj.hasOwnProperty("request") + ) } -function detectMetaMaskProvider({ timeout = 3000 } = {}) { +function detectMetaMaskProvider( + windowObject: Record, + { timeout = 3000 } = {}, +) { let handled = false return new Promise((resolve) => { - if (window.ethereum) { + if (windowObject.ethereum) { handleEthereum() } else { - window.addEventListener("ethereum#initialized", handleEthereum, { - once: true, - }) + if (typeof windowObject.addEventListener === "function") { + windowObject.addEventListener("ethereum#initialized", handleEthereum, { + once: true, + }) + } setTimeout(() => { handleEthereum() }, timeout) @@ -36,9 +43,11 @@ function detectMetaMaskProvider({ timeout = 3000 } = {}) { return } handled = true - window.removeEventListener("ethereum#initialized", handleEthereum) - const { ethereum } = window - if (ethereum && ethereum.isMetaMask) { + if (typeof windowObject.removeEventListener === "function") { + windowObject.removeEventListener("ethereum#initialized", handleEthereum) + } + const { ethereum } = windowObject + if (isMetaMaskProvider(ethereum)) { resolve(ethereum) } else { resolve(null) @@ -48,13 +57,14 @@ function detectMetaMaskProvider({ timeout = 3000 } = {}) { } async function waitForMetaMaskProvider( + windowObject: Record, options: { timeout?: number; retries?: number } = {}, ): Promise { const { timeout = 3000, retries = 0 } = options let provider: MetaMaskProvider | null = null try { - provider = await detectMetaMaskProvider({ timeout }) + provider = await detectMetaMaskProvider(windowObject, { timeout }) } catch { // Silent error - do nothing } @@ -71,26 +81,8 @@ async function waitForMetaMaskProvider( return provider } -async function hasSnapSupport(provider: MetaMaskProvider) { - try { - await provider.request({ method: "wallet_getSnaps" }) - return true - } catch { - return false - } -} - -async function detectMetamaskSupport() { - const provider = await waitForMetaMaskProvider({ retries: 3 }) - if (!provider) { - return null - } - - const snapSupport = await hasSnapSupport(provider) - if (!snapSupport) { - return null - } - +async function detectMetamaskSupport(windowObject: Record) { + const provider = await waitForMetaMaskProvider(windowObject, { retries: 3 }) return provider } @@ -180,20 +172,21 @@ function createMetaMaskProviderWrapper( return metaMaskProviderWrapper as StarknetWindowObject } -async function injectMetamaskBridge() { +async function injectMetamaskBridge(windowObject: Record) { if (window.hasOwnProperty("starknet_metamask")) { return } - const provider = await detectMetamaskSupport() - if (!provider) { + const metamaskWalletInfo = wallets.find((wallet) => wallet.id === "metamask") + if (!metamaskWalletInfo) { return } - const metamaskWalletInfo = wallets.find((wallet) => wallet.id === "metamask") - if (!metamaskWalletInfo) { + const provider = await detectMetamaskSupport(windowObject) + if (!provider) { return } + window.starknet_metamask = createMetaMaskProviderWrapper( metamaskWalletInfo, provider, From 9319a74cc93434f1ebfeea4ecada4289418e7dce Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 24 Apr 2024 10:41:12 +0300 Subject: [PATCH 17/20] - Set metamask wallet implementation url --- packages/core/src/wallet/metamaskBridge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index 3db27c5..c3c2915 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -130,7 +130,7 @@ function createMetaMaskProviderWrapper( name: "MetaMaskStarknetSnapWallet", alias: "MetaMaskStarknetSnapWallet", entry: - "https://s3.eu-central-1.amazonaws.com/dev.snaps.consensys.io/get-starknet/remoteEntry.js", + "https://snaps.consensys.io/starknet/get-starknet/v1/remoteEntry.js", }, ], }) From 05d95a17076be9fb9f18379336eae6fb64099a65 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 24 Apr 2024 11:21:39 +0300 Subject: [PATCH 18/20] - Fix test --- packages/core/src/__test__/main.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/__test__/main.test.ts b/packages/core/src/__test__/main.test.ts index 50d3830..f332559 100644 --- a/packages/core/src/__test__/main.test.ts +++ b/packages/core/src/__test__/main.test.ts @@ -131,7 +131,7 @@ describe("getDiscoveryWallets()", () => { it("should return all discovery wallets", async () => { const sn = getWallet({}) const discoveryWallets = await sn.getDiscoveryWallets() - expect(discoveryWallets.length).toBe(2) + expect(discoveryWallets.length).toBe(3) expect(discoveryWallets.map((w) => w.id)).contains(ArgentXMock.id) expect(discoveryWallets.map((w) => w.id)).contains(BraavosMock.id) }) From c6b2321507c093544290eef8a12f560587f8d8cc Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 24 Apr 2024 11:27:59 +0300 Subject: [PATCH 19/20] - Fix typo and test --- packages/core/src/__test__/main.test.ts | 2 +- packages/core/src/discovery.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/core/src/__test__/main.test.ts b/packages/core/src/__test__/main.test.ts index 8dd0500..52ff0ad 100644 --- a/packages/core/src/__test__/main.test.ts +++ b/packages/core/src/__test__/main.test.ts @@ -137,7 +137,7 @@ describe("getDiscoveryWallets()", () => { it("should return all discovery wallets", async () => { const sn = getWallet({}) const discoveryWallets = await sn.getDiscoveryWallets() - expect(discoveryWallets.length).toBe(3) + expect(discoveryWallets.length).toBe(4) expect(discoveryWallets.map((w) => w.id)).contains(ArgentXMock.id) expect(discoveryWallets.map((w) => w.id)).contains(BraavosMock.id) expect(discoveryWallets.map((w) => w.id)).contains(OKXMock.id) diff --git a/packages/core/src/discovery.ts b/packages/core/src/discovery.ts index 32e5b21..8c08a58 100644 --- a/packages/core/src/discovery.ts +++ b/packages/core/src/discovery.ts @@ -53,7 +53,8 @@ const wallets: WalletProvider[] = [ "https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn", firefox: "https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/", edge: "https://microsoftedge.microsoft.com/addons/detail/metamask/ejbalbakoplchlghecdalmeeeajnimhm?hl=en-US", - } + }, + }, ] export default wallets From dd9ad50e2e8c9de16ca21f49057a2a7c3c86bd42 Mon Sep 17 00:00:00 2001 From: NaorYe Date: Wed, 24 Apr 2024 11:35:27 +0300 Subject: [PATCH 20/20] - Fix import --- packages/core/src/wallet/metamaskBridge.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/src/wallet/metamaskBridge.ts b/packages/core/src/wallet/metamaskBridge.ts index c3c2915..6462f58 100644 --- a/packages/core/src/wallet/metamaskBridge.ts +++ b/packages/core/src/wallet/metamaskBridge.ts @@ -1,4 +1,3 @@ -import { loadRemote, init } from "@module-federation/runtime" import type { IStarknetWindowObject, RpcMessage, @@ -6,6 +5,8 @@ import type { WalletEvents, } from "../StarknetWindowObject" import wallets, { WalletProvider } from "../discovery" +import { init, loadRemote } from "@module-federation/runtime" + interface MetaMaskProvider { isMetaMask: boolean request(options: { method: string }): Promise