diff --git a/apps/desktop/src/setupTests.tsx b/apps/desktop/src/setupTests.tsx index 9099669db..3b80d2a8a 100644 --- a/apps/desktop/src/setupTests.tsx +++ b/apps/desktop/src/setupTests.tsx @@ -113,3 +113,15 @@ jest.spyOn(console, "error").mockImplementation((...args) => { } originalError(...args); }); + +jest.mock("@walletconnect/core", () => ({ + Core: jest.fn().mockImplementation(config => ({ + projectId: config.projectId, + })), +})); +jest.mock("@reown/walletkit", () => ({ + WalletKit: jest.fn(), +})); +jest.mock("@walletconnect/utils", () => ({ + WalletConnect: jest.fn(), +})); diff --git a/apps/web/package.json b/apps/web/package.json index 6f6cffb0c..3fbde0ede 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -34,6 +34,7 @@ "@emotion/styled": "^11.13.5", "@hookform/resolvers": "^3.9.1", "@reduxjs/toolkit": "^2.3.0", + "@reown/walletkit": "^1.0.1", "@tanstack/react-query": "^5.61.5", "@taquito/beacon-wallet": "^20.1.0", "@taquito/ledger-signer": "^20.1.0", @@ -50,6 +51,9 @@ "@umami/state": "workspace:^", "@umami/tezos": "workspace:^", "@umami/tzkt": "workspace:^", + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/types": "^2.16.2", + "@walletconnect/utils": "^2.16.2", "bignumber.js": "^9.1.2", "bip39": "^3.1.0", "cross-env": "^7.0.3", diff --git a/apps/web/src/components/App/App.test.tsx b/apps/web/src/components/App/App.test.tsx index 164170629..f1a31b1da 100644 --- a/apps/web/src/components/App/App.test.tsx +++ b/apps/web/src/components/App/App.test.tsx @@ -9,7 +9,29 @@ jest.mock("@chakra-ui/react", () => ({ useBreakpointValue: jest.fn(map => map["lg"]), })); +jest.mock("@umami/state", () => { + const mockedEmitter = { + removeAllListeners: jest.fn(), + }; + return { + ...jest.requireActual("@umami/state"), + walletKit: { + core: {}, + metadata: { + name: "Umami Wallet", + description: "Umami Wallet with WalletConnect", + url: "https://umamiwallet.com", + icons: ["https://umamiwallet.com/assets/favicon-32-45gq0g6M.png"], + }, + on: jest.fn().mockReturnValue(mockedEmitter), + }, + createWalletKit: jest.fn(), + }; +}); + describe("", () => { + afterEach(() => jest.restoreAllMocks()); + it("renders welcome screen for a new user", () => { render(); diff --git a/apps/web/src/components/App/App.tsx b/apps/web/src/components/App/App.tsx index bb63400b4..160c292d2 100644 --- a/apps/web/src/components/App/App.tsx +++ b/apps/web/src/components/App/App.tsx @@ -3,13 +3,16 @@ import { useCurrentAccount } from "@umami/state"; import { Layout } from "../../Layout"; import { Welcome } from "../../views/Welcome"; import { BeaconProvider } from "../beacon"; +import { WalletConnectProvider } from "../WalletConnect/WalletConnectProvider"; export const App = () => { const currentAccount = useCurrentAccount(); return currentAccount ? ( - + + + ) : ( diff --git a/apps/web/src/components/Menu/AppsMenu/AppsMenu.tsx b/apps/web/src/components/Menu/AppsMenu/AppsMenu.tsx index 568afcfa3..1bef31a11 100644 --- a/apps/web/src/components/Menu/AppsMenu/AppsMenu.tsx +++ b/apps/web/src/components/Menu/AppsMenu/AppsMenu.tsx @@ -2,23 +2,31 @@ import { Button, Text } from "@chakra-ui/react"; import { useAddPeer } from "@umami/state"; import { BeaconPeers } from "../../beacon"; +import { useOnWalletConnect } from "../../WalletConnect"; import { DrawerContentWrapper } from "../DrawerContentWrapper"; export const AppsMenu = () => { - const addPeer = useAddPeer(); + const onBeaconConnect = useAddPeer(); + const onWalletConnect = useOnWalletConnect(); return ( - Connect with Pairing Request + Connect with Pairing Request for Beacon or WalletConnect + + + + + ); +}; diff --git a/apps/web/src/components/WalletConnect/VerifyInfobox.tsx b/apps/web/src/components/WalletConnect/VerifyInfobox.tsx new file mode 100644 index 000000000..b23006571 --- /dev/null +++ b/apps/web/src/components/WalletConnect/VerifyInfobox.tsx @@ -0,0 +1,17 @@ +import { Box, Card, HStack, Icon, VStack } from "@chakra-ui/react"; + +import { AlertCircleIcon } from "../../assets/icons"; + +export const VerifyInfobox = () => ( + + + + + Unknown domain + + + This domain was not verified. To be implemented. + + + +); diff --git a/apps/web/src/components/WalletConnect/WalletConnectProvider.tsx b/apps/web/src/components/WalletConnect/WalletConnectProvider.tsx new file mode 100644 index 000000000..cf72f55f3 --- /dev/null +++ b/apps/web/src/components/WalletConnect/WalletConnectProvider.tsx @@ -0,0 +1,180 @@ +import type EventEmitter from "events"; + +import { type NetworkType } from "@airgap/beacon-wallet"; +import { useToast } from "@chakra-ui/react"; +import { type WalletKitTypes } from "@reown/walletkit"; +import { useDynamicModalContext } from "@umami/components"; +import { + createWalletKit, + useAsyncActionHandler, + useAvailableNetworks, + walletKit, +} from "@umami/state"; +import { type Network } from "@umami/tezos"; +import { formatJsonRpcError } from "@walletconnect/jsonrpc-utils"; +import { type SessionTypes } from "@walletconnect/types"; +import { getSdkError } from "@walletconnect/utils"; +import { type PropsWithChildren, useCallback, useEffect, useRef } from "react"; + +import { SessionProposalModal } from "./SessionProposalModal"; + +enum WalletKitState { + NOT_INITIALIZED, + INITIALIZING, + READY, +} + +export const WalletConnectProvider = ({ children }: PropsWithChildren) => { + const walletKitState = useRef(WalletKitState.NOT_INITIALIZED); + const eventEmitters = useRef([]); + const { handleAsyncActionUnsafe } = useAsyncActionHandler(); + const { openWith } = useDynamicModalContext(); + const toast = useToast(); + + const availableNetworks: Network[] = useAvailableNetworks(); + + const onSessionProposal = useCallback( + (proposal: WalletKitTypes.SessionProposal) => + handleAsyncActionUnsafe(async () => { + // dApp sends in the session proposal the required networks and the optional networks. + // The response must contain all the required networks but Umami supports just one per request. + // So if the list of required networks is more than one or the required network is not supported, we can only reject the proposal. + const requiredNetworks = Object.entries(proposal.params.requiredNamespaces) + .map(([key, values]) => (key.includes(":") ? key : (values.chains ?? []))) + .flat() + .filter(Boolean); + + if (requiredNetworks.length !== 1) { + throw new Error( + `Umami supports only one network per request, got required networks: ${requiredNetworks}` + ); + } + const network = requiredNetworks[0] as NetworkType; + const availablenetworks = availableNetworks.map(network => network.name); + // the network contains a namespace, e.g. tezos:mainnet + if (!availablenetworks.includes(network.split(":")[1])) { + throw new Error( + `The requested required network "${network}" is not supported. Available: ${availablenetworks}` + ); + } + + await openWith(, {}); + console.log("Session proposal from dApp", proposal, walletKit.getActiveSessions()); + }).catch(async () => { + // dApp is waiting so we need to notify it + await walletKit.rejectSession({ + id: proposal.id, + reason: getSdkError("UNSUPPORTED_CHAINS"), + }); + }), + [availableNetworks, openWith, handleAsyncActionUnsafe] + ); + + const onSessionDelete = useCallback( + (event: WalletKitTypes.SessionDelete) => { + // by that time the session is already deleted from WalletKit so we cannot find the dApp name + console.log("WC session deleted by peer dApp", event); + toast({ + description: "Session deleted by peer dApp", + status: "info", + }); + }, + [toast] + ); + + const onSessionRequest = useCallback( + async (event: WalletKitTypes.SessionRequest) => { + try { + const activeSessions: Record = walletKit.getActiveSessions(); + if (!(event.topic in activeSessions)) { + console.error("WalletConnect session request failed. Session not found", event); + throw new Error("WalletConnect session request failed. Session not found"); + } + + const session = activeSessions[event.topic]; + + toast({ + description: `Session request from dApp ${session.peer.metadata.name}`, + status: "info", + }); + toast({ + description: "Request handling is not implemented yet. Rejecting the request.", + status: "error", + }); + } catch (error) { + const { id, topic } = event; + const activeSessions: Record = walletKit.getActiveSessions(); + console.error("WalletConnect session request failed", event, error); + if (event.topic in activeSessions) { + const session = activeSessions[event.topic]; + toast({ + description: `Session request for dApp ${session.peer.metadata.name} failed. It was rejected.`, + status: "error", + }); + } else { + toast({ + description: `Session request for dApp ${topic} failed. It was rejected. Peer not found by topic.`, + status: "error", + }); + } + // dApp is waiting so we need to notify it + const response = formatJsonRpcError(id, getSdkError("INVALID_METHOD").message); + await walletKit.respondSessionRequest({ topic, response }); + } + }, + [toast] + ); + + useEffect(() => { + const session_proposal_listener = (event: WalletKitTypes.SessionProposal) => + void onSessionProposal(event); + const session_request_listener = (event: WalletKitTypes.SessionRequest) => + void onSessionRequest(event); + const session_delete_listener = (event: WalletKitTypes.SessionDelete) => + void onSessionDelete(event); + + const addListeners = () => { + const emitters = [ + walletKit.on("session_proposal", session_proposal_listener), + walletKit.on("session_request", session_request_listener), + walletKit.on("session_delete", session_delete_listener), + ].filter(Boolean) as EventEmitter[]; + eventEmitters.current.push(...emitters); + }; + const removeListeners = () => { + eventEmitters.current.forEach(emitter => { + emitter.removeAllListeners(); + }); + eventEmitters.current = []; + }; + + const initializeWallet = async () => { + // create the wallet just once + if (walletKitState.current === WalletKitState.NOT_INITIALIZED) { + // setting the flag now prevents subsequent render cycles from triggering + // another createWalletKit call during the first execution + walletKitState.current = WalletKitState.INITIALIZING; + await createWalletKit(); + walletKitState.current = WalletKitState.READY; + } + if (walletKitState.current === WalletKitState.READY) { + addListeners(); + } + // subscribe after the wallet is created + }; + void initializeWallet(); + + return () => { + if (walletKitState.current === WalletKitState.READY) { + removeListeners(); + } + }; + }, [onSessionProposal, onSessionRequest, onSessionDelete]); + + return children; +}; + +export const useOnWalletConnect = () => { + const { handleAsyncAction } = useAsyncActionHandler(); + return (uri: string) => handleAsyncAction(() => walletKit.pair({ uri })); +}; diff --git a/apps/web/src/components/WalletConnect/index.tsx b/apps/web/src/components/WalletConnect/index.tsx new file mode 100644 index 000000000..1a1760470 --- /dev/null +++ b/apps/web/src/components/WalletConnect/index.tsx @@ -0,0 +1 @@ +export * from "./WalletConnectProvider"; diff --git a/apps/web/src/setupTests.ts b/apps/web/src/setupTests.ts index 3cf352c0b..2556a09cb 100644 --- a/apps/web/src/setupTests.ts +++ b/apps/web/src/setupTests.ts @@ -59,3 +59,15 @@ jest.spyOn(console, "error").mockImplementation((...args) => { } originalError(...args); }); + +jest.mock("@walletconnect/core", () => ({ + Core: jest.fn().mockImplementation(config => ({ + projectId: config.projectId, + })), +})); +jest.mock("@reown/walletkit", () => ({ + WalletKit: jest.fn(), +})); +jest.mock("@walletconnect/utils", () => ({ + WalletConnect: jest.fn(), +})); diff --git a/packages/components/src/setupTests.ts b/packages/components/src/setupTests.ts index 36562bdff..2c7504978 100644 --- a/packages/components/src/setupTests.ts +++ b/packages/components/src/setupTests.ts @@ -7,3 +7,15 @@ Object.assign(navigator, { writeText, }, }); + +jest.mock("@walletconnect/core", () => ({ + Core: jest.fn().mockImplementation(config => ({ + projectId: config.projectId, + })), +})); +jest.mock("@reown/walletkit", () => ({ + WalletKit: jest.fn(), +})); +jest.mock("@walletconnect/utils", () => ({ + WalletConnect: jest.fn(), +})); diff --git a/packages/data-polling/src/setupTests.ts b/packages/data-polling/src/setupTests.ts index 341d367cf..d1a073595 100644 --- a/packages/data-polling/src/setupTests.ts +++ b/packages/data-polling/src/setupTests.ts @@ -15,3 +15,15 @@ jest.mock("@chakra-ui/react", () => ({ ...jest.requireActual("@chakra-ui/react"), useToast: () => mockToast, })); + +jest.mock("@walletconnect/core", () => ({ + Core: jest.fn().mockImplementation(config => ({ + projectId: config.projectId, + })), +})); +jest.mock("@reown/walletkit", () => ({ + WalletKit: jest.fn(), +})); +jest.mock("@walletconnect/utils", () => ({ + WalletConnect: jest.fn(), +})); diff --git a/packages/state/package.json b/packages/state/package.json index 0ffc05802..e6fcade38 100644 --- a/packages/state/package.json +++ b/packages/state/package.json @@ -70,6 +70,7 @@ "@emotion/react": "^11.13.5", "@emotion/styled": "^11.13.5", "@reduxjs/toolkit": "^2.3.0", + "@reown/walletkit": "^1.0.1", "@tanstack/react-query": "^5.61.5", "@taquito/signer": "^20.1.0", "@taquito/utils": "^20.1.0", @@ -80,6 +81,9 @@ "@umami/social-auth": "workspace:^", "@umami/tezos": "workspace:^", "@umami/tzkt": "workspace:^", + "@walletconnect/core": "^2.16.2", + "@walletconnect/jsonrpc-utils": "^1.0.8", + "@walletconnect/utils": "^2.16.2", "bip39": "^3.1.0", "framer-motion": "^11.12.0", "immer": "^10.1.1", diff --git a/packages/state/src/index.ts b/packages/state/src/index.ts index 6cb4c0ce1..f69b02ae3 100644 --- a/packages/state/src/index.ts +++ b/packages/state/src/index.ts @@ -8,3 +8,4 @@ export * from "./hooks"; export * from "./migrations"; export * from "./slices"; export * from "./thunks"; +export * from "./walletConnect"; diff --git a/packages/state/src/setupTests.ts b/packages/state/src/setupTests.ts index dc84c8811..9dfb03ae8 100644 --- a/packages/state/src/setupTests.ts +++ b/packages/state/src/setupTests.ts @@ -24,6 +24,33 @@ jest.mock("./beacon/WalletClient", () => ({ }, })); +jest.mock("@walletconnect/core", () => ({ + Core: jest.fn().mockImplementation(config => ({ + projectId: config.projectId, + })), +})); +jest.mock("@reown/walletkit", () => { + const mockOn = jest.fn(); + const mockOff = jest.fn(); + + const mockWalletKit = { + init: jest.fn().mockResolvedValue({ + core: {}, + metadata: { + name: "Umami Wallet", + description: "Umami Wallet with WalletConnect", + url: "https://umamiwallet.com", + icons: ["https://umamiwallet.com/assets/favicon-32-45gq0g6M.png"], + }, + on: mockOn, + off: mockOff, + }), + }; + return { + WalletKit: mockWalletKit, + }; +}); + beforeEach(() => Object.defineProperty(window, "localStorage", { value: mockLocalStorage(), diff --git a/packages/state/src/walletConnect/WalletKit.ts b/packages/state/src/walletConnect/WalletKit.ts new file mode 100644 index 000000000..f4f924d7d --- /dev/null +++ b/packages/state/src/walletConnect/WalletKit.ts @@ -0,0 +1,27 @@ +import { type IWalletKit, WalletKit } from "@reown/walletkit"; +import { Core } from "@walletconnect/core"; + +export let walletKit: IWalletKit; + +export const createWalletKit = async () => { + const core = new Core({ + projectId: "252533b433e70f85a0e5c8b53b97faea", + }); + + walletKit = await WalletKit.init({ + core, + metadata: { + name: "Umami Wallet", + description: "Umami Wallet with WalletConnect", + url: "https://umamiwallet.com", + icons: ["https://umamiwallet.com/assets/favicon-32-45gq0g6M.png"], + }, + }); + + try { + const clientId = await walletKit.engine.signClient.core.crypto.getClientId(); + console.log("WalletConnect ClientID: ", clientId); + } catch (error) { + console.error("Failed to set WalletConnect clientId in localStorage: ", error); + } +}; diff --git a/packages/state/src/walletConnect/index.ts b/packages/state/src/walletConnect/index.ts new file mode 100644 index 000000000..dd940fb0f --- /dev/null +++ b/packages/state/src/walletConnect/index.ts @@ -0,0 +1 @@ +export * from "./WalletKit"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3442f235b..b9ac7d8da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -827,6 +827,9 @@ importers: '@reduxjs/toolkit': specifier: ^2.3.0 version: 2.3.0(react-redux@9.1.2(@types/react@18.3.12)(react@18.3.1)(redux@5.0.1))(react@18.3.1) + '@reown/walletkit': + specifier: ^1.0.1 + version: 1.0.1 '@tanstack/react-query': specifier: ^5.61.5 version: 5.61.5(react@18.3.1) @@ -875,6 +878,15 @@ importers: '@umami/tzkt': specifier: workspace:^ version: link:../../packages/tzkt + '@walletconnect/jsonrpc-utils': + specifier: ^1.0.8 + version: 1.0.8 + '@walletconnect/types': + specifier: ^2.16.2 + version: 2.16.2 + '@walletconnect/utils': + specifier: ^2.16.2 + version: 2.17.2 bignumber.js: specifier: ^9.1.2 version: 9.1.2 @@ -1749,6 +1761,9 @@ importers: '@reduxjs/toolkit': specifier: ^2.3.0 version: 2.3.0(react-redux@9.1.2(@types/react@18.3.12)(react@18.3.1)(redux@5.0.1))(react@18.3.1) + '@reown/walletkit': + specifier: ^1.0.1 + version: 1.0.1 '@tanstack/react-query': specifier: ^5.61.5 version: 5.61.5(react@18.3.1) @@ -1779,6 +1794,15 @@ importers: '@umami/tzkt': specifier: workspace:^ version: link:../tzkt + '@walletconnect/core': + specifier: ^2.16.2 + version: 2.16.2 + '@walletconnect/jsonrpc-utils': + specifier: ^1.0.8 + version: 1.0.8 + '@walletconnect/utils': + specifier: ^2.16.2 + version: 2.17.2 bip39: specifier: ^3.1.0 version: 3.1.0 @@ -4025,6 +4049,57 @@ packages: resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@ethersproject/abstract-provider@5.7.0': + resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} + + '@ethersproject/abstract-signer@5.7.0': + resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} + + '@ethersproject/address@5.7.0': + resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} + + '@ethersproject/base64@5.7.0': + resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} + + '@ethersproject/bignumber@5.7.0': + resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} + + '@ethersproject/bytes@5.7.0': + resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} + + '@ethersproject/constants@5.7.0': + resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} + + '@ethersproject/hash@5.7.0': + resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} + + '@ethersproject/keccak256@5.7.0': + resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} + + '@ethersproject/logger@5.7.0': + resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} + + '@ethersproject/networks@5.7.1': + resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} + + '@ethersproject/properties@5.7.0': + resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} + + '@ethersproject/rlp@5.7.0': + resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} + + '@ethersproject/signing-key@5.7.0': + resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} + + '@ethersproject/strings@5.7.0': + resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} + + '@ethersproject/transactions@5.7.0': + resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} + + '@ethersproject/web@5.7.1': + resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} + '@exodus/schemasafe@1.3.0': resolution: {integrity: sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==} @@ -4568,6 +4643,9 @@ packages: resolution: {integrity: sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==} engines: {node: '>=14.0.0'} + '@reown/walletkit@1.0.1': + resolution: {integrity: sha512-h/KP22V05V5tlFPiP++krxROfz0eGYbr925eN9cnmcw4FZmy3uCLOecDQcJiPPvPZLw7rqMPMOzx1PGUK5uJNQ==} + '@rollup/plugin-inject@5.0.5': resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} engines: {node: '>=14.0.0'} @@ -6288,6 +6366,10 @@ packages: '@walletconnect/core@2.11.2': resolution: {integrity: sha512-bB4SiXX8hX3/hyBfVPC5gwZCXCl+OPj+/EDVM71iAO3TDsh78KPbrVAbDnnsbHzZVHlsMohtXX3j5XVsheN3+g==} + '@walletconnect/core@2.16.2': + resolution: {integrity: sha512-Xf1SqLSB8KffNsgUGDE/CguAcKMD+3EKfqfqNhWpimxe1QDZDUw8xq+nnxfx6MAb8fdx9GYe6Lvknx2SAAeAHw==} + engines: {node: '>=18'} + '@walletconnect/environment@1.0.1': resolution: {integrity: sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg==} @@ -6297,9 +6379,15 @@ packages: '@walletconnect/heartbeat@1.2.1': resolution: {integrity: sha512-yVzws616xsDLJxuG/28FqtZ5rzrTA4gUjdEMTbWB5Y8V1XHRmqq4efAxCw5ie7WjbXFSUyBHaWlMR+2/CpQC5Q==} + '@walletconnect/heartbeat@1.2.2': + resolution: {integrity: sha512-uASiRmC5MwhuRuf05vq4AT48Pq8RMi876zV8rr8cV969uTOzWdB/k+Lj5yI2PBtB1bGQisGen7MM1GcZlQTBXw==} + '@walletconnect/jsonrpc-provider@1.0.13': resolution: {integrity: sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g==} + '@walletconnect/jsonrpc-provider@1.0.14': + resolution: {integrity: sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==} + '@walletconnect/jsonrpc-types@1.0.3': resolution: {integrity: sha512-iIQ8hboBl3o5ufmJ8cuduGad0CQm3ZlsHtujv9Eu16xq89q+BG7Nh5VLxxUgmtpnrePgFkTwXirCTkwJH1v+Yw==} @@ -6323,8 +6411,8 @@ packages: '@walletconnect/logger@2.1.2': resolution: {integrity: sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==} - '@walletconnect/relay-api@1.0.10': - resolution: {integrity: sha512-tqrdd4zU9VBNqUaXXQASaexklv6A54yEyQQEXYOCr+Jz8Ket0dmPBDyg19LVSNUN2cipAghQc45/KVmfFJ0cYw==} + '@walletconnect/relay-api@1.0.11': + resolution: {integrity: sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==} '@walletconnect/relay-auth@1.0.4': resolution: {integrity: sha512-kKJcS6+WxYq5kshpPaxGHdwf5y98ZwbfuS4EE/NkQzqrDFm5Cj+dP8LofzWvjrrLkZq7Afy7WrQMXdLy8Sx7HQ==} @@ -6335,15 +6423,30 @@ packages: '@walletconnect/sign-client@2.11.2': resolution: {integrity: sha512-MfBcuSz2GmMH+P7MrCP46mVE5qhP0ZyWA0FyIH6/WuxQ6G+MgKsGfaITqakpRPsykWOJq8tXMs3XvUPDU413OQ==} + '@walletconnect/sign-client@2.16.2': + resolution: {integrity: sha512-R/hk2P3UN5u3FV22E7h9S/Oy8IbDwaBGH7St/BzOpJCjFmf6CF5S3GZVjrXPBesvRF94CROkqMF89wz5HkZepA==} + '@walletconnect/time@1.0.2': resolution: {integrity: sha512-uzdd9woDcJ1AaBZRhqy5rNC9laqWGErfc4dxA9a87mPdKOgWMD85mcFo9dIYIts/Jwocfwn07EC6EzclKubk/g==} '@walletconnect/types@2.11.2': resolution: {integrity: sha512-p632MFB+lJbip2cvtXPBQslpUdiw1sDtQ5y855bOlAGquay+6fZ4h1DcDePeKQDQM3P77ax2a9aNPZxV6y/h1Q==} + '@walletconnect/types@2.16.2': + resolution: {integrity: sha512-IIV9kQh6b/WpwhfgPixpziE+8XK/FtdnfvN1oOMs5h+lgwr46OJknPY2p7eS6vvdvEP3xMEc1Kbu1i4tlnroiw==} + + '@walletconnect/types@2.17.2': + resolution: {integrity: sha512-j/+0WuO00lR8ntu7b1+MKe/r59hNwYLFzW0tTmozzhfAlDL+dYwWasDBNq4AH8NbVd7vlPCQWmncH7/6FVtOfQ==} + '@walletconnect/utils@2.11.2': resolution: {integrity: sha512-LyfdmrnZY6dWqlF4eDrx5jpUwsB2bEPjoqR5Z6rXPiHJKUOdJt7az+mNOn5KTSOlRpd1DmozrBrWr+G9fFLYVw==} + '@walletconnect/utils@2.16.2': + resolution: {integrity: sha512-CEMxMCIqvwXd8YIEXfBoCiWY8DtUevJ/w14Si+cmTHWHBDWKRZll7+QUXgICIBx5kyX3GMAKNABaTlg2A2CPSg==} + + '@walletconnect/utils@2.17.2': + resolution: {integrity: sha512-T7eLRiuw96fgwUy2A5NZB5Eu87ukX8RCVoO9lji34RFV4o2IGU9FhTEWyd4QQKI8OuQRjSknhbJs0tU0r0faPw==} + '@walletconnect/window-getters@1.0.1': resolution: {integrity: sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q==} @@ -9295,6 +9398,9 @@ packages: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} + js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -11920,6 +12026,9 @@ packages: ufo@1.5.4: resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + uint8arrays@3.1.0: + resolution: {integrity: sha512-ei5rfKtoRO8OyOIor2Rz5fhzjThwIHJZ3uyDPnDHTXbP0aMQ1RN/6AI5B5d9dBxJOU+BvOAk7ZQ1xphsX8Lrog==} + uint8arrays@3.1.1: resolution: {integrity: sha512-+QJa8QRnbdXVpHYjLoTpJIdCTiw9Ir62nocClWuXIq2JIh4Uta0cQsTSpFL678p2CN8B+XSApwcU+pQEqVpKWg==} @@ -15162,6 +15271,117 @@ snapshots: '@eslint/js@8.57.0': {} + '@ethersproject/abstract-provider@5.7.0': + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 + + '@ethersproject/abstract-signer@5.7.0': + dependencies: + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + + '@ethersproject/address@5.7.0': + dependencies: + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/rlp': 5.7.0 + + '@ethersproject/base64@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + + '@ethersproject/bignumber@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + bn.js: 5.2.1 + + '@ethersproject/bytes@5.7.0': + dependencies: + '@ethersproject/logger': 5.7.0 + + '@ethersproject/constants@5.7.0': + dependencies: + '@ethersproject/bignumber': 5.7.0 + + '@ethersproject/hash@5.7.0': + dependencies: + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/base64': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + + '@ethersproject/keccak256@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + js-sha3: 0.8.0 + + '@ethersproject/logger@5.7.0': {} + + '@ethersproject/networks@5.7.1': + dependencies: + '@ethersproject/logger': 5.7.0 + + '@ethersproject/properties@5.7.0': + dependencies: + '@ethersproject/logger': 5.7.0 + + '@ethersproject/rlp@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + + '@ethersproject/signing-key@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + bn.js: 5.2.1 + elliptic: 6.6.1 + hash.js: 1.1.7 + + '@ethersproject/strings@5.7.0': + dependencies: + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + + '@ethersproject/transactions@5.7.0': + dependencies: + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + + '@ethersproject/web@5.7.1': + dependencies: + '@ethersproject/base64': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@exodus/schemasafe@1.3.0': {} '@floating-ui/core@1.6.8': @@ -16097,6 +16317,33 @@ snapshots: '@remix-run/router@1.19.1': {} + '@reown/walletkit@1.0.1': + dependencies: + '@walletconnect/core': 2.16.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/sign-client': 2.16.2 + '@walletconnect/types': 2.16.2 + '@walletconnect/utils': 2.16.2 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - ioredis + - uWebSockets.js + - utf-8-validate + '@rollup/plugin-inject@5.0.5(rollup@4.26.0)': dependencies: '@rollup/pluginutils': 5.1.3(rollup@4.26.0) @@ -18591,7 +18838,7 @@ snapshots: '@walletconnect/jsonrpc-ws-connection': 1.0.14 '@walletconnect/keyvaluestorage': 1.1.1 '@walletconnect/logger': 2.1.2 - '@walletconnect/relay-api': 1.0.10 + '@walletconnect/relay-api': 1.0.11 '@walletconnect/relay-auth': 1.0.4 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 @@ -18620,6 +18867,42 @@ snapshots: - uWebSockets.js - utf-8-validate + '@walletconnect/core@2.16.2': + dependencies: + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-provider': 1.0.14 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/jsonrpc-ws-connection': 1.0.14 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.0.4 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.16.2 + '@walletconnect/utils': 2.16.2 + events: 3.3.0 + lodash.isequal: 4.5.0 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - ioredis + - uWebSockets.js + - utf-8-validate + '@walletconnect/environment@1.0.1': dependencies: tslib: 1.14.1 @@ -18635,12 +18918,24 @@ snapshots: '@walletconnect/time': 1.0.2 tslib: 1.14.1 + '@walletconnect/heartbeat@1.2.2': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/time': 1.0.2 + events: 3.3.0 + '@walletconnect/jsonrpc-provider@1.0.13': dependencies: '@walletconnect/jsonrpc-utils': 1.0.8 '@walletconnect/safe-json': 1.0.2 tslib: 1.14.1 + '@walletconnect/jsonrpc-provider@1.0.14': + dependencies: + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/safe-json': 1.0.2 + events: 3.3.0 + '@walletconnect/jsonrpc-types@1.0.3': dependencies: keyvaluestorage-interface: 1.0.0 @@ -18692,7 +18987,7 @@ snapshots: '@walletconnect/safe-json': 1.0.2 pino: 7.11.0 - '@walletconnect/relay-api@1.0.10': + '@walletconnect/relay-api@1.0.11': dependencies: '@walletconnect/jsonrpc-types': 1.0.4 @@ -18739,6 +19034,35 @@ snapshots: - uWebSockets.js - utf-8-validate + '@walletconnect/sign-client@2.16.2': + dependencies: + '@walletconnect/core': 2.16.2 + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/logger': 2.1.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.16.2 + '@walletconnect/utils': 2.16.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - ioredis + - uWebSockets.js + - utf-8-validate + '@walletconnect/time@1.0.2': dependencies: tslib: 1.14.1 @@ -18767,6 +19091,54 @@ snapshots: - ioredis - uWebSockets.js + '@walletconnect/types@2.16.2': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + + '@walletconnect/types@2.17.2': + dependencies: + '@walletconnect/events': 1.0.1 + '@walletconnect/heartbeat': 1.2.2 + '@walletconnect/jsonrpc-types': 1.0.4 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/logger': 2.1.2 + events: 3.3.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + '@walletconnect/utils@2.11.2': dependencies: '@stablelib/chacha20poly1305': 1.0.1 @@ -18774,7 +19146,7 @@ snapshots: '@stablelib/random': 1.0.2 '@stablelib/sha256': 1.0.1 '@stablelib/x25519': 1.0.3 - '@walletconnect/relay-api': 1.0.10 + '@walletconnect/relay-api': 1.0.11 '@walletconnect/safe-json': 1.0.2 '@walletconnect/time': 1.0.2 '@walletconnect/types': 2.11.2 @@ -18799,6 +19171,78 @@ snapshots: - ioredis - uWebSockets.js + '@walletconnect/utils@2.16.2': + dependencies: + '@stablelib/chacha20poly1305': 1.0.1 + '@stablelib/hkdf': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + '@stablelib/x25519': 1.0.3 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.0.4 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.16.2 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + detect-browser: 5.3.0 + elliptic: 6.6.1 + query-string: 7.1.3 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + + '@walletconnect/utils@2.17.2': + dependencies: + '@ethersproject/hash': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@stablelib/chacha20poly1305': 1.0.1 + '@stablelib/hkdf': 1.0.1 + '@stablelib/random': 1.0.2 + '@stablelib/sha256': 1.0.1 + '@stablelib/x25519': 1.0.3 + '@walletconnect/jsonrpc-utils': 1.0.8 + '@walletconnect/keyvaluestorage': 1.1.1 + '@walletconnect/relay-api': 1.0.11 + '@walletconnect/relay-auth': 1.0.4 + '@walletconnect/safe-json': 1.0.2 + '@walletconnect/time': 1.0.2 + '@walletconnect/types': 2.17.2 + '@walletconnect/window-getters': 1.0.1 + '@walletconnect/window-metadata': 1.0.1 + detect-browser: 5.3.0 + elliptic: 6.6.1 + query-string: 7.1.3 + uint8arrays: 3.1.0 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@upstash/redis' + - '@vercel/kv' + - ioredis + - uWebSockets.js + '@walletconnect/window-getters@1.0.1': dependencies: tslib: 1.14.1 @@ -22499,6 +22943,8 @@ snapshots: joycon@3.1.1: {} + js-sha3@0.8.0: {} + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -25561,6 +26007,10 @@ snapshots: ufo@1.5.4: {} + uint8arrays@3.1.0: + dependencies: + multiformats: 9.9.0 + uint8arrays@3.1.1: dependencies: multiformats: 9.9.0