diff --git a/packages/milkomeda-wsc-provider/README.md b/packages/milkomeda-wsc-provider/README.md index 0b33999..e75ce16 100644 --- a/packages/milkomeda-wsc-provider/README.md +++ b/packages/milkomeda-wsc-provider/README.md @@ -1,5 +1,9 @@ # Provider -Injects the provider for wrapped smart contracts into the `window.ethereum` object. This provider invokes a l1 provider to abstract the milkomeda account on l2. +Injects the provider for wrapped smart contracts into: +1. [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) - the `window.ethereum` object +2. [EIP-6963](https://eips.ethereum.org/EIPS/eip-6963) with rdns `com.milkomeda.c1.wsc` / `com.milkomeda.a1.wsc` and UUID `d53bc7c3-e43a-4d0a-83d7-b6e7b7504beb` + +This provider invokes a L1 provider to abstract the Milkomeda account on L2. To see an example usage of this provider see the [example dapp](../dapp-example/). diff --git a/packages/milkomeda-wsc-provider/src/index.ts b/packages/milkomeda-wsc-provider/src/index.ts index 9635328..82a67c4 100644 --- a/packages/milkomeda-wsc-provider/src/index.ts +++ b/packages/milkomeda-wsc-provider/src/index.ts @@ -8,16 +8,66 @@ declare global { } } +// https://eips.ethereum.org/EIPS/eip-6963 +interface EIP6963ProviderInfo { + uuid: string; + name: string; + icon: string; + rdns: string; +} +interface EIP6963ProviderDetail { + info: EIP6963ProviderInfo; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + provider: any; // EIP1193 window.ethereum injected provider +} +interface EIP6963AnnounceProviderEvent extends CustomEvent { + type: "eip6963:announceProvider"; + detail: EIP6963ProviderDetail; +} +const milkomedaSvg = + "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzY3IiBoZWlnaHQ9IjM2NyIgdmlld0JveD0iMCAwIDM2NyAzNjciIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0xODMuNSAzNjdDMjg0Ljg0NCAzNjcgMzY3IDI4NC44NDQgMzY3IDE4My41QzM2NyA4Mi4xNTU3IDI4NC44NDQgMCAxODMuNSAwQzgyLjE1NTcgMCAwIDgyLjE1NTcgMCAxODMuNUMwIDI4NC44NDQgODIuMTU1NyAzNjcgMTgzLjUgMzY3WiIgZmlsbD0iYmxhY2siLz4KPHBhdGggZD0iTTI4OS40OSAxNjAuMjg3TDMwNi44MjMgMTkwLjMxMUwyMTUuNDk2IDI0My4wNDZDMjE1LjQ5NiAyNDMuMDQ2IDE1OS41NzEgMjc2Ljg1MiAxMTkuMzMgMjA3LjE2MUwxNDcuNzU5IDE5MC43NDJDMTQ3Ljc1OSAxOTAuNzQyIDE2Ni4yNzUgMjMxLjU5MiAxOTguMzA3IDIxMy4wNEMyMzAuMzM4IDE5NC40ODggMjg5LjQ5IDE2MC4yODcgMjg5LjQ5IDE2MC4yODdaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNNzcuNTExOCAyMDYuOTQ2TDYwLjE3ODYgMTc2LjkyMkwxNTMuMzg3IDEyMy4xNDdDMTUzLjM4NyAxMjMuMTQ3IDIwOS4zMyA4OS4zNDE0IDI0OS41MTggMTU4Ljk5N0wyMjEuMTQzIDE3NS4zOEMyMjEuMTQzIDE3NS4zOCAyMDIuNjYyIDEzNC42MDEgMTcwLjYzMSAxNTMuMDgyQzEzOC41OTkgMTcxLjU2MiA3Ny41MTE4IDIwNi45NDYgNzcuNTExOCAyMDYuOTQ2WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTE4NS4yNTcgMjA2LjNDMTkxLjI5NSAyMDYuMyAxOTcuMDg1IDIwMy45MDMgMjAxLjM1NyAxOTkuNjM3QzIwNS42MjkgMTk1LjM3IDIwOC4wMzIgMTg5LjU4MiAyMDguMDM5IDE4My41NDVDMjA4LjA0NiAxNzcuNTA3IDIwNS42NTYgMTcxLjcxNCAyMDEuMzk0IDE2Ny40MzdDMTk3LjEzMyAxNjMuMTYgMTkxLjM0OCAxNjAuNzUgMTg1LjMxIDE2MC43MzZDMTc5LjI3MyAxNjAuNzIyIDE3My40NzcgMTYzLjEwNSAxNjkuMTk1IDE2Ny4zNjJDMTY0LjkxMyAxNzEuNjE4IDE2Mi40OTYgMTc3LjQgMTYyLjQ3NSAxODMuNDM4QzE2Mi40NTQgMTg5LjQ3NSAxNjQuODMgMTk1LjI3NCAxNjkuMDgxIDE5OS41NjFDMTczLjMzMyAyMDMuODQ4IDE3OS4xMTIgMjA2LjI3MiAxODUuMTUgMjA2LjNDMTg1LjE4NSAyMDYuMyAxODUuMjIxIDIwNi4zIDE4NS4yNTcgMjA2LjNaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMjYzLjY2IDE1MC4wNTJDMjY2LjAxNCAxNTAuMDUyIDI2OC4zMTUgMTQ5LjM1NCAyNzAuMjczIDE0OC4wNDdDMjcyLjIzIDE0Ni43MzkgMjczLjc1NSAxNDQuODggMjc0LjY1NiAxNDIuNzA1QzI3NS41NTcgMTQwLjUzIDI3NS43OTMgMTM4LjEzNyAyNzUuMzMzIDEzNS44MjhDMjc0Ljg3NCAxMzMuNTIgMjczLjc0MSAxMzEuMzk5IDI3Mi4wNzYgMTI5LjczNEMyNzAuNDExIDEyOC4wNyAyNjguMjkxIDEyNi45MzYgMjY1Ljk4MiAxMjYuNDc3QzI2My42NzMgMTI2LjAxOCAyNjEuMjggMTI2LjI1NCAyNTkuMTA1IDEyNy4xNTRDMjU2LjkzIDEyOC4wNTUgMjU1LjA3MiAxMjkuNTgxIDI1My43NjQgMTMxLjUzOEMyNTIuNDU2IDEzMy40OTUgMjUxLjc1OCAxMzUuNzk2IDI1MS43NTggMTM4LjE1TDI1MS43NTggMTM4LjE4NkMyNTEuNzY4IDE0MS4zMzcgMjUzLjAyNiAxNDQuMzU1IDI1NS4yNTcgMTQ2LjU3OUMyNTcuNDg4IDE0OC44MDMgMjYwLjUxIDE1MC4wNTIgMjYzLjY2IDE1MC4wNTJaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMjg5LjQ5IDE2MC4yODdMMzA2LjgyMyAxOTAuMzExTDIxNS41MTQgMjQzLjA0NkMyMTUuNTE0IDI0My4wNDYgMTU5LjU3MSAyNzYuODUyIDExOS4zMyAyMDcuMTYxTDE0Ny43NTkgMTkwLjc0MkMxNDcuNzU5IDE5MC43NDIgMTY2LjI3NSAyMzEuNTkyIDE5OC4zMDcgMjEzLjA0QzIzMC4zMzggMTk0LjQ4OCAyODkuNDkgMTYwLjI4NyAyODkuNDkgMTYwLjI4N1oiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik03Ny41MTE4IDIwNi45NDZMNjAuMTc4NiAxNzYuOTIyTDE1My4zODcgMTIzLjE0N0MxNTMuMzg3IDEyMy4xNDcgMjA5LjMzIDg5LjM0MTQgMjQ5LjUxOCAxNTguOTk3TDIyMS4xNDMgMTc1LjM4QzIyMS4xNDMgMTc1LjM4IDIwMi42NjIgMTM0LjYwMSAxNzAuNjMxIDE1My4wODJDMTM4LjU5OSAxNzEuNTYyIDc3LjUxMTggMjA2Ljk0NiA3Ny41MTE4IDIwNi45NDZaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMTg1LjI1NyAyMDYuM0MxOTEuMjk1IDIwNi4zIDE5Ny4wODcgMjAzLjkwMyAyMDEuMzU4IDE5OS42MzVDMjA1LjYzIDE5NS4zNjcgMjA4LjAzMiAxODkuNTc4IDIwOC4wMzggMTgzLjU0QzIwOC4wNDQgMTc3LjUwMiAyMDUuNjUyIDE3MS43MDkgMjAxLjM4OCAxNjcuNDMzQzE5Ny4xMjUgMTYzLjE1NyAxOTEuMzM4IDE2MC43NDkgMTg1LjMgMTYwLjczN0MxNzkuMjYyIDE2MC43MjYgMTczLjQ2NiAxNjMuMTEyIDE2OS4xODYgMTY3LjM3MUMxNjQuOTA2IDE3MS42MyAxNjIuNDkyIDE3Ny40MTQgMTYyLjQ3NSAxODMuNDUyQzE2Mi40NTcgMTg5LjQ5MSAxNjQuODM4IDE5NS4yODkgMTY5LjA5MyAxOTkuNTczQzE3My4zNDggMjAzLjg1NyAxNzkuMTI5IDIwNi4yNzcgMTg1LjE2OCAyMDYuM0wxODUuMjU3IDIwNi4zWiIgZmlsbD0iI0ZGOTMxRSIvPgo8cGF0aCBkPSJNMTA0Ljc5MyAyNDEuNzkxQzEwNy4xNDcgMjQxLjc5MSAxMDkuNDQ4IDI0MS4wOTMgMTExLjQwNiAyMzkuNzg1QzExMy4zNjMgMjM4LjQ3OCAxMTQuODg4IDIzNi42MTkgMTE1Ljc4OSAyMzQuNDQ0QzExNi42OSAyMzIuMjY5IDExNi45MjYgMjI5Ljg3NiAxMTYuNDY3IDIyNy41NjdDMTE2LjAwNyAyMjUuMjU4IDExNC44NzQgMjIzLjEzOCAxMTMuMjA5IDIyMS40NzNDMTExLjU0NSAyMTkuODA5IDEwOS40MjQgMjE4LjY3NSAxMDcuMTE1IDIxOC4yMTZDMTA0LjgwNiAyMTcuNzU3IDEwMi40MTMgMjE3Ljk5MiAxMDAuMjM5IDIxOC44OTNDOTguMDYzNyAyMTkuNzk0IDk2LjIwNDkgMjIxLjMyIDk0Ljg5NzEgMjIzLjI3N0M5My41ODkzIDIyNS4yMzQgOTIuODkxMiAyMjcuNTM1IDkyLjg5MTIgMjI5Ljg4OUM5Mi44OTEyIDIzMy4wNDYgOTQuMTQ1MiAyMzYuMDczIDk2LjM3NzIgMjM4LjMwNUM5OC42MDkzIDI0MC41MzcgMTAxLjYzNyAyNDEuNzkxIDEwNC43OTMgMjQxLjc5MVoiIGZpbGw9IndoaXRlIi8+CjxwYXRoIGQ9Ik0yNjMuNjYgMTUwLjA1MkMyNjYuMDE0IDE1MC4wNTIgMjY4LjMxNSAxNDkuMzU0IDI3MC4yNzMgMTQ4LjA0N0MyNzIuMjMgMTQ2LjczOSAyNzMuNzU1IDE0NC44OCAyNzQuNjU2IDE0Mi43MDVDMjc1LjU1NyAxNDAuNTMgMjc1Ljc5MyAxMzguMTM3IDI3NS4zMzMgMTM1LjgyOEMyNzQuODc0IDEzMy41MiAyNzMuNzQxIDEzMS4zOTkgMjcyLjA3NiAxMjkuNzM0QzI3MC40MTEgMTI4LjA3IDI2OC4yOTEgMTI2LjkzNiAyNjUuOTgyIDEyNi40NzdDMjYzLjY3MyAxMjYuMDE4IDI2MS4yOCAxMjYuMjU0IDI1OS4xMDUgMTI3LjE1NEMyNTYuOTMgMTI4LjA1NSAyNTUuMDcyIDEyOS41ODEgMjUzLjc2NCAxMzEuNTM4QzI1Mi40NTYgMTMzLjQ5NSAyNTEuNzU4IDEzNS43OTYgMjUxLjc1OCAxMzguMTVMMjUxLjc1OCAxMzguMTg2QzI1MS43NjggMTQxLjMzNyAyNTMuMDI2IDE0NC4zNTUgMjU1LjI1NyAxNDYuNTc5QzI1Ny40ODggMTQ4LjgwMyAyNjAuNTEgMTUwLjA1MiAyNjMuNjYgMTUwLjA1MloiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo="; +const wscUuid = "d53bc7c3-e43a-4d0a-83d7-b6e7b7504beb"; + +const cardanoWscEip6963Info: EIP6963ProviderInfo = { + uuid: wscUuid, + name: "Cardano C1 WSC", + icon: milkomedaSvg, + rdns: "com.milkomeda.c1.wsc", +} as const; +const algorandWscEip6963Info: EIP6963ProviderInfo = { + uuid: wscUuid, + name: "Cardano A1 WSC", + icon: milkomedaSvg, + rdns: "com.milkomeda.a1.wsc", +} as const; + +function addEip6963Listener(provider: EIP6963ProviderInfo) { + const announceEvent = new CustomEvent("eip6963:announceProvider", { + detail: Object.freeze({ info: cardanoWscEip6963Info, provider }), + }) as EIP6963AnnounceProviderEvent; + + // send an event for any dApp that was already listening to let them know about the WSC provider + window.dispatchEvent(announceEvent); + + // create a listener to respond to any dApp with WSC info + window.addEventListener("eip6963:requestProvider", () => { + window.dispatchEvent(announceEvent); + }); +} export const injectCardano = (oracleUrl: string, jsonRpcProviderUrl: string) => { - window.ethereum = new Provider(oracleUrl, jsonRpcProviderUrl, PROVIDER_TYPES.CARDANO); + const provider = new Provider(oracleUrl, jsonRpcProviderUrl, PROVIDER_TYPES.CARDANO); + window.ethereum = provider; // note: other wallets may override this or block this from even being set + addEip6963Listener(cardanoWscEip6963Info); - return window.ethereum; + return provider; }; export const injectAlgorand = (oracleUrl: string, jsonRpcProviderUrl: string) => { - window.ethereum = new Provider(oracleUrl, jsonRpcProviderUrl, PROVIDER_TYPES.ALGORAND); + const provider = new Provider(oracleUrl, jsonRpcProviderUrl, PROVIDER_TYPES.ALGORAND); + window.ethereum = provider; // note: other wallets may override this or block this from even being set + addEip6963Listener(algorandWscEip6963Info); - return window.ethereum; + return provider; }; export type { CardanoProvider, MilkomedaProvider };