@dynamic-labs-sdk/metamask 0.0.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +19 -0
  2. package/dist/clearMetaMaskSessionStorage/clearMetaMaskSessionStorage.d.ts +10 -0
  3. package/dist/clearMetaMaskSessionStorage/clearMetaMaskSessionStorage.d.ts.map +1 -0
  4. package/dist/clearMetaMaskSessionStorage/index.d.ts +2 -0
  5. package/dist/clearMetaMaskSessionStorage/index.d.ts.map +1 -0
  6. package/dist/connectWithMetaMaskUri/connectWithMetaMaskUri.d.ts +30 -0
  7. package/dist/connectWithMetaMaskUri/connectWithMetaMaskUri.d.ts.map +1 -0
  8. package/dist/connectWithMetaMaskUri/index.d.ts +3 -0
  9. package/dist/connectWithMetaMaskUri/index.d.ts.map +1 -0
  10. package/dist/errors/MetaMaskDisplayUriMissingError/MetaMaskDisplayUriMissingError.d.ts +5 -0
  11. package/dist/errors/MetaMaskDisplayUriMissingError/MetaMaskDisplayUriMissingError.d.ts.map +1 -0
  12. package/dist/errors/MetaMaskDisplayUriMissingError/index.d.ts +2 -0
  13. package/dist/errors/MetaMaskDisplayUriMissingError/index.d.ts.map +1 -0
  14. package/dist/errors/MetaMaskWalletNotConnectedError/MetaMaskWalletNotConnectedError.d.ts +5 -0
  15. package/dist/errors/MetaMaskWalletNotConnectedError/MetaMaskWalletNotConnectedError.d.ts.map +1 -0
  16. package/dist/errors/MetaMaskWalletNotConnectedError/index.d.ts +2 -0
  17. package/dist/errors/MetaMaskWalletNotConnectedError/index.d.ts.map +1 -0
  18. package/dist/exports/index.d.ts +8 -0
  19. package/dist/exports/index.d.ts.map +1 -0
  20. package/dist/getMetaMaskExtensionWalletProviderKey/getMetaMaskExtensionWalletProviderKey.d.ts +19 -0
  21. package/dist/getMetaMaskExtensionWalletProviderKey/getMetaMaskExtensionWalletProviderKey.d.ts.map +1 -0
  22. package/dist/getMetaMaskExtensionWalletProviderKey/index.d.ts +2 -0
  23. package/dist/getMetaMaskExtensionWalletProviderKey/index.d.ts.map +1 -0
  24. package/dist/index.cjs +157 -0
  25. package/dist/index.cjs.map +1 -0
  26. package/dist/index.esm.js +153 -0
  27. package/dist/index.esm.js.map +1 -0
  28. package/dist/metamask.types.d.ts +23 -0
  29. package/dist/metamask.types.d.ts.map +1 -0
  30. package/dist/tsconfig.lib.tsbuildinfo +1 -0
  31. package/package.json +36 -1
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # @dynamic-labs-sdk/metamask
2
+
3
+ Chain-agnostic primitives for integrating the
4
+ [MetaMask SDK](https://docs.metamask.io/sdk/) (`@metamask/connect-multichain`
5
+ and its chain-specific facades such as `@metamask/connect-evm`) with the
6
+ Dynamic JS SDK.
7
+
8
+ This package is intended to be consumed by Dynamic's chain-specific
9
+ packages (`@dynamic-labs-sdk/evm`, `@dynamic-labs-sdk/solana`, …) and
10
+ exposes the building blocks they share — the extension-installed
11
+ guard, the IndexedDB session reset, the connect orchestration that
12
+ returns a `{ approval, uri }` pair, and a thin `MetaMaskController`
13
+ interface that chain-specific glue implements on top of the
14
+ chain-specific MetaMask SDK.
15
+
16
+ Application code should usually import from a chain-specific
17
+ sub-entrypoint instead, e.g. `@dynamic-labs-sdk/evm/metamask`, which
18
+ re-exports a chain-bound `connectWithMetaMaskEvm` /
19
+ `isMetaMaskExtensionInstalled` etc.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Deletes the MetaMask SDK's IndexedDB session storage so the next connect call
3
+ * emits a fresh `display_uri` synchronously instead of spending the SDK's
4
+ * 10-second resume timeout reviving a dead pairing. Safe in SSR (no-op) and
5
+ * when the DB is held open by another tab (resolves on `blocked`).
6
+ *
7
+ * @not-instrumented
8
+ */
9
+ export declare const clearMetaMaskSessionStorage: () => Promise<void>;
10
+ //# sourceMappingURL=clearMetaMaskSessionStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clearMetaMaskSessionStorage.d.ts","sourceRoot":"","sources":["../../src/clearMetaMaskSessionStorage/clearMetaMaskSessionStorage.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,QAAO,OAAO,CAAC,IAAI,CAsB1D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { clearMetaMaskSessionStorage } from './clearMetaMaskSessionStorage';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/clearMetaMaskSessionStorage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { Chain, DynamicClient, WalletProviderUriConnectionResult } from '@dynamic-labs-sdk/client';
2
+ import type { WalletProvider } from '@dynamic-labs-sdk/client/core';
3
+ import type { MetaMaskController } from '../metamask.types';
4
+ export type ConnectWithMetaMaskUriParams = {
5
+ /** Whether to add the connected wallet account to the Dynamic client. Defaults to `true`. */
6
+ addToDynamicWalletAccounts?: boolean;
7
+ /** Chain being connected; used to scope the extension-installed lookup. */
8
+ chain: Chain;
9
+ /** Returns the chain-specific `MetaMaskController` that drives the pairing. */
10
+ getController: (client: DynamicClient) => Promise<MetaMaskController>;
11
+ /**
12
+ * Builds the chain-specific `WalletProvider` AFTER the pairing has been
13
+ * approved. Must NOT include a `connect` method — the provider is registered
14
+ * purely for signing routing and would otherwise leak into the wallet picker.
15
+ */
16
+ walletProviderBuilder: (client: DynamicClient) => Promise<WalletProvider>;
17
+ };
18
+ /**
19
+ * Drives a MetaMask SDK pairing for any chain and returns `{ approval, uri }`
20
+ * so consumers can render the QR / hand the URI to a deeplink. Logs an
21
+ * advisory warning when the extension is already announced for the chain —
22
+ * pairing still proceeds, but the consumer is told which announced provider
23
+ * key to route through for the best UX. Builds and registers the chain-
24
+ * specific wallet provider only after pairing is approved; the provider
25
+ * therefore never appears in the wallet picker (no `connect` method).
26
+ *
27
+ * @not-instrumented
28
+ */
29
+ export declare const connectWithMetaMaskUri: ({ addToDynamicWalletAccounts, chain, getController, walletProviderBuilder, }: ConnectWithMetaMaskUriParams, client?: DynamicClient) => Promise<WalletProviderUriConnectionResult>;
30
+ //# sourceMappingURL=connectWithMetaMaskUri.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connectWithMetaMaskUri.d.ts","sourceRoot":"","sources":["../../src/connectWithMetaMaskUri/connectWithMetaMaskUri.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,aAAa,EAEb,iCAAiC,EAClC,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAapE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,MAAM,4BAA4B,GAAG;IACzC,6FAA6F;IAC7F,0BAA0B,CAAC,EAAE,OAAO,CAAC;IACrC,2EAA2E;IAC3E,KAAK,EAAE,KAAK,CAAC;IACb,+EAA+E;IAC/E,aAAa,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtE;;;;OAIG;IACH,qBAAqB,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;CAC3E,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,iFAM9B,4BAA4B,WACvB,aAAa,KACpB,OAAO,CAAC,iCAAiC,CAmF3C,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { connectWithMetaMaskUri } from './connectWithMetaMaskUri';
2
+ export type { ConnectWithMetaMaskUriParams } from './connectWithMetaMaskUri';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/connectWithMetaMaskUri/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,YAAY,EAAE,4BAA4B,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { BaseError } from '@dynamic-labs-sdk/client';
2
+ export declare class MetaMaskDisplayUriMissingError extends BaseError {
3
+ constructor();
4
+ }
5
+ //# sourceMappingURL=MetaMaskDisplayUriMissingError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetaMaskDisplayUriMissingError.d.ts","sourceRoot":"","sources":["../../../src/errors/MetaMaskDisplayUriMissingError/MetaMaskDisplayUriMissingError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,qBAAa,8BAA+B,SAAQ,SAAS;;CAW5D"}
@@ -0,0 +1,2 @@
1
+ export { MetaMaskDisplayUriMissingError } from './MetaMaskDisplayUriMissingError';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/errors/MetaMaskDisplayUriMissingError/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { BaseError } from '@dynamic-labs-sdk/client';
2
+ export declare class MetaMaskWalletNotConnectedError extends BaseError {
3
+ constructor();
4
+ }
5
+ //# sourceMappingURL=MetaMaskWalletNotConnectedError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetaMaskWalletNotConnectedError.d.ts","sourceRoot":"","sources":["../../../src/errors/MetaMaskWalletNotConnectedError/MetaMaskWalletNotConnectedError.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,qBAAa,+BAAgC,SAAQ,SAAS;;CAW7D"}
@@ -0,0 +1,2 @@
1
+ export { MetaMaskWalletNotConnectedError } from './MetaMaskWalletNotConnectedError';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/errors/MetaMaskWalletNotConnectedError/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { clearMetaMaskSessionStorage } from '../clearMetaMaskSessionStorage';
2
+ export { connectWithMetaMaskUri } from '../connectWithMetaMaskUri';
3
+ export type { ConnectWithMetaMaskUriParams } from '../connectWithMetaMaskUri';
4
+ export { MetaMaskDisplayUriMissingError } from '../errors/MetaMaskDisplayUriMissingError';
5
+ export { MetaMaskWalletNotConnectedError } from '../errors/MetaMaskWalletNotConnectedError';
6
+ export { getMetaMaskExtensionWalletProviderKey } from '../getMetaMaskExtensionWalletProviderKey';
7
+ export type { DisplayUriListener, MetaMaskController, } from '../metamask.types';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAC;AAC1F,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,EAAE,qCAAqC,EAAE,MAAM,0CAA0C,CAAC;AACjG,YAAY,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { Chain, DynamicClient } from '@dynamic-labs-sdk/client';
2
+ type GetMetaMaskExtensionWalletProviderKeyParams = {
3
+ /** Chain to scope the lookup to. */
4
+ chain: Chain;
5
+ };
6
+ /**
7
+ * Returns the wallet provider key of the MetaMask browser extension announced
8
+ * for the given chain (EIP-6963 on EVM, Wallet Standard on Solana), or
9
+ * `undefined` when none is announced. Matches on normalized display name to
10
+ * cover MetaMask, Flask, and other variants. Synchronous and safe to call from
11
+ * a React render. Pass the returned key to `connectWithWalletProvider` to route
12
+ * the connection through the announced provider; fall back to the chain's
13
+ * `connectWithMetaMaskUri<Chain>` helper when `undefined`.
14
+ *
15
+ * @not-instrumented
16
+ */
17
+ export declare const getMetaMaskExtensionWalletProviderKey: ({ chain }: GetMetaMaskExtensionWalletProviderKeyParams, client?: DynamicClient) => string | undefined;
18
+ export {};
19
+ //# sourceMappingURL=getMetaMaskExtensionWalletProviderKey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getMetaMaskExtensionWalletProviderKey.d.ts","sourceRoot":"","sources":["../../src/getMetaMaskExtensionWalletProviderKey/getMetaMaskExtensionWalletProviderKey.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AASrE,KAAK,2CAA2C,GAAG;IACjD,oCAAoC;IACpC,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qCAAqC,cACrC,2CAA2C,WAC9C,aAAa,KACpB,MAAM,GAAG,SAaX,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { getMetaMaskExtensionWalletProviderKey } from './getMetaMaskExtensionWalletProviderKey';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/getMetaMaskExtensionWalletProviderKey/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qCAAqC,EAAE,MAAM,yCAAyC,CAAC"}
package/dist/index.cjs ADDED
@@ -0,0 +1,157 @@
1
+ let _dynamic_labs_sdk_assert_package_version = require("@dynamic-labs-sdk/assert-package-version");
2
+ let _dynamic_labs_sdk_client = require("@dynamic-labs-sdk/client");
3
+ let _dynamic_labs_sdk_client_core = require("@dynamic-labs-sdk/client/core");
4
+ let _dynamic_labs_sdk_api_core = require("@dynamic-labs/sdk-api-core");
5
+
6
+ //#region package.json
7
+ var name = "@dynamic-labs-sdk/metamask";
8
+ var version = "1.5.0";
9
+
10
+ //#endregion
11
+ //#region src/clearMetaMaskSessionStorage/clearMetaMaskSessionStorage.ts
12
+ const METAMASK_SDK_IDB_NAME = "mmconnect-kv-store";
13
+ /**
14
+ * Deletes the MetaMask SDK's IndexedDB session storage so the next connect call
15
+ * emits a fresh `display_uri` synchronously instead of spending the SDK's
16
+ * 10-second resume timeout reviving a dead pairing. Safe in SSR (no-op) and
17
+ * when the DB is held open by another tab (resolves on `blocked`).
18
+ *
19
+ * @not-instrumented
20
+ */
21
+ const clearMetaMaskSessionStorage = () => {
22
+ if (typeof indexedDB === "undefined") return Promise.resolve();
23
+ return new Promise((resolve) => {
24
+ try {
25
+ const request = indexedDB.deleteDatabase(METAMASK_SDK_IDB_NAME);
26
+ request.onsuccess = () => resolve();
27
+ request.onerror = () => resolve();
28
+ request.onblocked = () => resolve();
29
+ } catch {
30
+ resolve();
31
+ }
32
+ });
33
+ };
34
+
35
+ //#endregion
36
+ //#region src/errors/MetaMaskDisplayUriMissingError/MetaMaskDisplayUriMissingError.ts
37
+ var MetaMaskDisplayUriMissingError = class extends _dynamic_labs_sdk_client.BaseError {
38
+ constructor() {
39
+ super({
40
+ cause: null,
41
+ code: "metamask_display_uri_missing",
42
+ docsUrl: null,
43
+ name: "MetaMaskDisplayUriMissingError",
44
+ shortMessage: "MetaMask SDK completed the connection without emitting a display_uri. The connect helper requires the SDK to produce a pairing URI. Please reach out to Dynamic about this error."
45
+ });
46
+ }
47
+ };
48
+
49
+ //#endregion
50
+ //#region src/getMetaMaskExtensionWalletProviderKey/getMetaMaskExtensionWalletProviderKey.ts
51
+ const METAMASK_NAME_NEEDLE = "metamask";
52
+ /**
53
+ * Returns the wallet provider key of the MetaMask browser extension announced
54
+ * for the given chain (EIP-6963 on EVM, Wallet Standard on Solana), or
55
+ * `undefined` when none is announced. Matches on normalized display name to
56
+ * cover MetaMask, Flask, and other variants. Synchronous and safe to call from
57
+ * a React render. Pass the returned key to `connectWithWalletProvider` to route
58
+ * the connection through the announced provider; fall back to the chain's
59
+ * `connectWithMetaMaskUri<Chain>` helper when `undefined`.
60
+ *
61
+ * @not-instrumented
62
+ */
63
+ const getMetaMaskExtensionWalletProviderKey = ({ chain }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
64
+ return (0, _dynamic_labs_sdk_client_core.getWalletProviderRegistry)(client).listProviders().find((provider) => provider.chain === chain && provider.walletProviderType === _dynamic_labs_sdk_api_core.WalletProviderEnum.BrowserExtension && provider.metadata.displayName?.toLowerCase().includes(METAMASK_NAME_NEEDLE))?.key;
65
+ };
66
+
67
+ //#endregion
68
+ //#region src/connectWithMetaMaskUri/connectWithMetaMaskUri.ts
69
+ /**
70
+ * Drives a MetaMask SDK pairing for any chain and returns `{ approval, uri }`
71
+ * so consumers can render the QR / hand the URI to a deeplink. Logs an
72
+ * advisory warning when the extension is already announced for the chain —
73
+ * pairing still proceeds, but the consumer is told which announced provider
74
+ * key to route through for the best UX. Builds and registers the chain-
75
+ * specific wallet provider only after pairing is approved; the provider
76
+ * therefore never appears in the wallet picker (no `connect` method).
77
+ *
78
+ * @not-instrumented
79
+ */
80
+ const connectWithMetaMaskUri = async ({ addToDynamicWalletAccounts = true, chain, getController, walletProviderBuilder }, client = (0, _dynamic_labs_sdk_client_core.getDefaultClient)()) => {
81
+ const announcedKey = getMetaMaskExtensionWalletProviderKey({ chain }, client);
82
+ if (announcedKey !== void 0) (0, _dynamic_labs_sdk_client_core.getCore)(client).logger.warn(`[metamask] MetaMask extension is announced for ${chain} as wallet provider "${announcedKey}"; proceeding with URI pairing. Consider connectWithWalletProvider({ walletProviderKey: "${announcedKey}" }) for the best user experience.`);
83
+ const controller = await getController(client);
84
+ const uriDeferred = (0, _dynamic_labs_sdk_client_core.createDeferredPromise)();
85
+ const unsubscribe = controller.onDisplayUri((displayUri) => {
86
+ uriDeferred.resolve(displayUri);
87
+ });
88
+ const connectPromise = controller.connect();
89
+ connectPromise.then(() => {
90
+ uriDeferred.reject(new MetaMaskDisplayUriMissingError());
91
+ }).catch((error) => {
92
+ uriDeferred.reject(error);
93
+ });
94
+ let uri;
95
+ try {
96
+ uri = await uriDeferred.promise;
97
+ } finally {
98
+ unsubscribe();
99
+ }
100
+ const approval = async () => {
101
+ await connectPromise;
102
+ const walletProvider = await walletProviderBuilder(client);
103
+ (0, _dynamic_labs_sdk_client_core.getWalletProviderRegistry)(client).register({
104
+ priority: _dynamic_labs_sdk_client_core.WalletProviderPriority.WALLET_SDK,
105
+ walletProvider
106
+ });
107
+ const { addresses } = await walletProvider.getConnectedAddresses();
108
+ const mainAddress = addresses[0];
109
+ if (mainAddress === void 0) throw new _dynamic_labs_sdk_client.NoAddressFoundError();
110
+ return { walletAccounts: (0, _dynamic_labs_sdk_client_core.reconcileWalletAccountsAgainstClient)({
111
+ addToDynamicWalletAccounts,
112
+ walletAccounts: [{
113
+ address: mainAddress,
114
+ chain: walletProvider.chain,
115
+ id: (0, _dynamic_labs_sdk_client_core.formatWalletAccountId)({
116
+ address: mainAddress,
117
+ chain: walletProvider.chain,
118
+ walletProviderKey: walletProvider.key
119
+ }),
120
+ lastSelectedAt: null,
121
+ verifiedCredentialId: null,
122
+ walletProviderKey: walletProvider.key
123
+ }],
124
+ walletProviderKey: walletProvider.key
125
+ }, client) };
126
+ };
127
+ return {
128
+ approval,
129
+ uri
130
+ };
131
+ };
132
+
133
+ //#endregion
134
+ //#region src/errors/MetaMaskWalletNotConnectedError/MetaMaskWalletNotConnectedError.ts
135
+ var MetaMaskWalletNotConnectedError = class extends _dynamic_labs_sdk_client.BaseError {
136
+ constructor() {
137
+ super({
138
+ cause: null,
139
+ code: "metamask_wallet_not_connected",
140
+ docsUrl: null,
141
+ name: "MetaMaskWalletNotConnectedError",
142
+ shortMessage: "MetaMask SDK has no connected wallet account. Complete the URI pairing (await the connect approval) before building the MetaMask wallet provider."
143
+ });
144
+ }
145
+ };
146
+
147
+ //#endregion
148
+ //#region src/exports/index.ts
149
+ (0, _dynamic_labs_sdk_assert_package_version.assertPackageVersion)(name, version);
150
+
151
+ //#endregion
152
+ exports.MetaMaskDisplayUriMissingError = MetaMaskDisplayUriMissingError;
153
+ exports.MetaMaskWalletNotConnectedError = MetaMaskWalletNotConnectedError;
154
+ exports.clearMetaMaskSessionStorage = clearMetaMaskSessionStorage;
155
+ exports.connectWithMetaMaskUri = connectWithMetaMaskUri;
156
+ exports.getMetaMaskExtensionWalletProviderKey = getMetaMaskExtensionWalletProviderKey;
157
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["BaseError","WalletProviderEnum","uri: string","WalletProviderPriority","NoAddressFoundError","BaseError"],"sources":["../package.json","../src/clearMetaMaskSessionStorage/clearMetaMaskSessionStorage.ts","../src/errors/MetaMaskDisplayUriMissingError/MetaMaskDisplayUriMissingError.ts","../src/getMetaMaskExtensionWalletProviderKey/getMetaMaskExtensionWalletProviderKey.ts","../src/connectWithMetaMaskUri/connectWithMetaMaskUri.ts","../src/errors/MetaMaskWalletNotConnectedError/MetaMaskWalletNotConnectedError.ts","../src/exports/index.ts"],"sourcesContent":["","// MetaMask SDK persists session state in this IndexedDB database.\n// Hardcoded inside `@metamask/connect-multichain` (the SDK shared by\n// every chain-specific connect-* facade) as `${DB_NAME}${dbNameSuffix}`\n// → `mmconnect` + `-kv-store` on web.\nconst METAMASK_SDK_IDB_NAME = 'mmconnect-kv-store';\n\n/**\n * Deletes the MetaMask SDK's IndexedDB session storage so the next connect call\n * emits a fresh `display_uri` synchronously instead of spending the SDK's\n * 10-second resume timeout reviving a dead pairing. Safe in SSR (no-op) and\n * when the DB is held open by another tab (resolves on `blocked`).\n *\n * @not-instrumented\n */\nexport const clearMetaMaskSessionStorage = (): Promise<void> => {\n if (typeof indexedDB === 'undefined') {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve) => {\n try {\n const request = indexedDB.deleteDatabase(METAMASK_SDK_IDB_NAME);\n request.onsuccess = () => resolve();\n // `onerror` / `onblocked` fire when a concurrent tab holds the\n // DB open. We still resolve so the consumer's connect flow is\n // not stalled indefinitely; the next tab close drops the lock\n // and subsequent runs reach the empty database. The Promise\n // executor already ignores subsequent resolve calls, so no\n // extra guard is needed when multiple lifecycle events fire on\n // the same request.\n request.onerror = () => resolve();\n request.onblocked = () => resolve();\n } catch {\n resolve();\n }\n });\n};\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class MetaMaskDisplayUriMissingError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'metamask_display_uri_missing',\n docsUrl: null,\n name: 'MetaMaskDisplayUriMissingError',\n shortMessage:\n 'MetaMask SDK completed the connection without emitting a display_uri. The connect helper requires the SDK to produce a pairing URI. Please reach out to Dynamic about this error.',\n });\n }\n}\n","import type { Chain, DynamicClient } from '@dynamic-labs-sdk/client';\nimport {\n getDefaultClient,\n getWalletProviderRegistry,\n} from '@dynamic-labs-sdk/client/core';\nimport { WalletProviderEnum } from '@dynamic-labs/sdk-api-core';\n\nconst METAMASK_NAME_NEEDLE = 'metamask';\n\ntype GetMetaMaskExtensionWalletProviderKeyParams = {\n /** Chain to scope the lookup to. */\n chain: Chain;\n};\n\n/**\n * Returns the wallet provider key of the MetaMask browser extension announced\n * for the given chain (EIP-6963 on EVM, Wallet Standard on Solana), or\n * `undefined` when none is announced. Matches on normalized display name to\n * cover MetaMask, Flask, and other variants. Synchronous and safe to call from\n * a React render. Pass the returned key to `connectWithWalletProvider` to route\n * the connection through the announced provider; fall back to the chain's\n * `connectWithMetaMaskUri<Chain>` helper when `undefined`.\n *\n * @not-instrumented\n */\nexport const getMetaMaskExtensionWalletProviderKey = (\n { chain }: GetMetaMaskExtensionWalletProviderKeyParams,\n client: DynamicClient = getDefaultClient()\n): string | undefined => {\n const providers = getWalletProviderRegistry(client).listProviders();\n\n const match = providers.find(\n (provider) =>\n provider.chain === chain &&\n provider.walletProviderType === WalletProviderEnum.BrowserExtension &&\n provider.metadata.displayName\n ?.toLowerCase()\n .includes(METAMASK_NAME_NEEDLE)\n );\n\n return match?.key;\n};\n","import type {\n Chain,\n DynamicClient,\n WalletAccount,\n WalletProviderUriConnectionResult,\n} from '@dynamic-labs-sdk/client';\nimport { NoAddressFoundError } from '@dynamic-labs-sdk/client';\nimport type { WalletProvider } from '@dynamic-labs-sdk/client/core';\nimport {\n WalletProviderPriority,\n createDeferredPromise,\n formatWalletAccountId,\n getCore,\n getDefaultClient,\n getWalletProviderRegistry,\n reconcileWalletAccountsAgainstClient,\n} from '@dynamic-labs-sdk/client/core';\n\nimport { MetaMaskDisplayUriMissingError } from '../errors/MetaMaskDisplayUriMissingError';\nimport { getMetaMaskExtensionWalletProviderKey } from '../getMetaMaskExtensionWalletProviderKey';\nimport type { MetaMaskController } from '../metamask.types';\n\nexport type ConnectWithMetaMaskUriParams = {\n /** Whether to add the connected wallet account to the Dynamic client. Defaults to `true`. */\n addToDynamicWalletAccounts?: boolean;\n /** Chain being connected; used to scope the extension-installed lookup. */\n chain: Chain;\n /** Returns the chain-specific `MetaMaskController` that drives the pairing. */\n getController: (client: DynamicClient) => Promise<MetaMaskController>;\n /**\n * Builds the chain-specific `WalletProvider` AFTER the pairing has been\n * approved. Must NOT include a `connect` method — the provider is registered\n * purely for signing routing and would otherwise leak into the wallet picker.\n */\n walletProviderBuilder: (client: DynamicClient) => Promise<WalletProvider>;\n};\n\n/**\n * Drives a MetaMask SDK pairing for any chain and returns `{ approval, uri }`\n * so consumers can render the QR / hand the URI to a deeplink. Logs an\n * advisory warning when the extension is already announced for the chain —\n * pairing still proceeds, but the consumer is told which announced provider\n * key to route through for the best UX. Builds and registers the chain-\n * specific wallet provider only after pairing is approved; the provider\n * therefore never appears in the wallet picker (no `connect` method).\n *\n * @not-instrumented\n */\nexport const connectWithMetaMaskUri = async (\n {\n addToDynamicWalletAccounts = true,\n chain,\n getController,\n walletProviderBuilder,\n }: ConnectWithMetaMaskUriParams,\n client: DynamicClient = getDefaultClient()\n): Promise<WalletProviderUriConnectionResult> => {\n const announcedKey = getMetaMaskExtensionWalletProviderKey({ chain }, client);\n\n if (announcedKey !== undefined) {\n getCore(client).logger.warn(\n `[metamask] MetaMask extension is announced for ${chain} as wallet provider \"${announcedKey}\"; proceeding with URI pairing. Consider connectWithWalletProvider({ walletProviderKey: \"${announcedKey}\" }) for the best user experience.`\n );\n }\n\n const controller = await getController(client);\n\n const uriDeferred = createDeferredPromise<string>();\n\n const unsubscribe = controller.onDisplayUri((displayUri) => {\n uriDeferred.resolve(displayUri);\n });\n\n const connectPromise = controller.connect();\n\n // If `connect` settles before a `display_uri` is emitted, no URI was made\n // available and the pairing is unusable. Reject the deferred so the caller\n // surfaces `MetaMaskDisplayUriMissingError` (or the underlying failure).\n connectPromise\n .then(() => {\n uriDeferred.reject(new MetaMaskDisplayUriMissingError());\n })\n .catch((error: unknown) => {\n uriDeferred.reject(error);\n });\n\n let uri: string;\n try {\n uri = await uriDeferred.promise;\n } finally {\n unsubscribe();\n }\n\n const approval = async (): Promise<{ walletAccounts: WalletAccount[] }> => {\n await connectPromise;\n\n const walletProvider = await walletProviderBuilder(client);\n\n getWalletProviderRegistry(client).register({\n priority: WalletProviderPriority.WALLET_SDK,\n walletProvider,\n });\n\n const { addresses } = await walletProvider.getConnectedAddresses();\n\n // MetaMask SDK exposes a single active address per pairing (same model as\n // EIP-1193 `eth_accounts`); we only materialize the first one.\n const mainAddress = addresses[0];\n\n if (mainAddress === undefined) {\n throw new NoAddressFoundError();\n }\n\n const walletAccount: WalletAccount = {\n address: mainAddress,\n chain: walletProvider.chain,\n id: formatWalletAccountId({\n address: mainAddress,\n chain: walletProvider.chain,\n walletProviderKey: walletProvider.key,\n }),\n lastSelectedAt: null,\n verifiedCredentialId: null,\n walletProviderKey: walletProvider.key,\n };\n\n const walletAccounts = reconcileWalletAccountsAgainstClient(\n {\n addToDynamicWalletAccounts,\n walletAccounts: [walletAccount],\n walletProviderKey: walletProvider.key,\n },\n client\n );\n\n return { walletAccounts };\n };\n\n return { approval, uri };\n};\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class MetaMaskWalletNotConnectedError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'metamask_wallet_not_connected',\n docsUrl: null,\n name: 'MetaMaskWalletNotConnectedError',\n shortMessage:\n 'MetaMask SDK has no connected wallet account. Complete the URI pairing (await the connect approval) before building the MetaMask wallet provider.',\n });\n }\n}\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport { name, version } from '../../package.json';\n\nassertPackageVersion(name, version);\n\nexport { clearMetaMaskSessionStorage } from '../clearMetaMaskSessionStorage';\nexport { connectWithMetaMaskUri } from '../connectWithMetaMaskUri';\nexport type { ConnectWithMetaMaskUriParams } from '../connectWithMetaMaskUri';\nexport { MetaMaskDisplayUriMissingError } from '../errors/MetaMaskDisplayUriMissingError';\nexport { MetaMaskWalletNotConnectedError } from '../errors/MetaMaskWalletNotConnectedError';\nexport { getMetaMaskExtensionWalletProviderKey } from '../getMetaMaskExtensionWalletProviderKey';\nexport type {\n DisplayUriListener,\n MetaMaskController,\n} from '../metamask.types';\n"],"mappings":";;;;;;;;;;;ACIA,MAAM,wBAAwB;;;;;;;;;AAU9B,MAAa,oCAAmD;AAC9D,KAAI,OAAO,cAAc,YACvB,QAAO,QAAQ,SAAS;AAG1B,QAAO,IAAI,SAAe,YAAY;AACpC,MAAI;GACF,MAAM,UAAU,UAAU,eAAe,sBAAsB;AAC/D,WAAQ,kBAAkB,SAAS;AAQnC,WAAQ,gBAAgB,SAAS;AACjC,WAAQ,kBAAkB,SAAS;UAC7B;AACN,YAAS;;GAEX;;;;;ACjCJ,IAAa,iCAAb,cAAoDA,mCAAU;CAC5D,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cACE;GACH,CAAC;;;;;;ACJN,MAAM,uBAAuB;;;;;;;;;;;;AAkB7B,MAAa,yCACX,EAAE,SACF,8DAA0C,KACnB;AAYvB,qEAX4C,OAAO,CAAC,eAAe,CAE3C,MACrB,aACC,SAAS,UAAU,SACnB,SAAS,uBAAuBC,8CAAmB,oBACnD,SAAS,SAAS,aACd,aAAa,CACd,SAAS,qBAAqB,CACpC,EAEa;;;;;;;;;;;;;;;;ACQhB,MAAa,yBAAyB,OACpC,EACE,6BAA6B,MAC7B,OACA,eACA,yBAEF,8DAA0C,KACK;CAC/C,MAAM,eAAe,sCAAsC,EAAE,OAAO,EAAE,OAAO;AAE7E,KAAI,iBAAiB,OACnB,4CAAQ,OAAO,CAAC,OAAO,KACrB,kDAAkD,MAAM,uBAAuB,aAAa,2FAA2F,aAAa,oCACrM;CAGH,MAAM,aAAa,MAAM,cAAc,OAAO;CAE9C,MAAM,wEAA6C;CAEnD,MAAM,cAAc,WAAW,cAAc,eAAe;AAC1D,cAAY,QAAQ,WAAW;GAC/B;CAEF,MAAM,iBAAiB,WAAW,SAAS;AAK3C,gBACG,WAAW;AACV,cAAY,OAAO,IAAI,gCAAgC,CAAC;GACxD,CACD,OAAO,UAAmB;AACzB,cAAY,OAAO,MAAM;GACzB;CAEJ,IAAIC;AACJ,KAAI;AACF,QAAM,MAAM,YAAY;WAChB;AACR,eAAa;;CAGf,MAAM,WAAW,YAA0D;AACzE,QAAM;EAEN,MAAM,iBAAiB,MAAM,sBAAsB,OAAO;AAE1D,+DAA0B,OAAO,CAAC,SAAS;GACzC,UAAUC,qDAAuB;GACjC;GACD,CAAC;EAEF,MAAM,EAAE,cAAc,MAAM,eAAe,uBAAuB;EAIlE,MAAM,cAAc,UAAU;AAE9B,MAAI,gBAAgB,OAClB,OAAM,IAAIC,8CAAqB;AAyBjC,SAAO,EAAE,wFARP;GACE;GACA,gBAAgB,CAhBiB;IACnC,SAAS;IACT,OAAO,eAAe;IACtB,6DAA0B;KACxB,SAAS;KACT,OAAO,eAAe;KACtB,mBAAmB,eAAe;KACnC,CAAC;IACF,gBAAgB;IAChB,sBAAsB;IACtB,mBAAmB,eAAe;IACnC,CAKkC;GAC/B,mBAAmB,eAAe;GACnC,EACD,OACD,EAEwB;;AAG3B,QAAO;EAAE;EAAU;EAAK;;;;;ACxI1B,IAAa,kCAAb,cAAqDC,mCAAU;CAC7D,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cACE;GACH,CAAC;;;;;;mECPe,MAAM,QAAQ"}
@@ -0,0 +1,153 @@
1
+ import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
2
+ import { BaseError, NoAddressFoundError } from "@dynamic-labs-sdk/client";
3
+ import { WalletProviderPriority, createDeferredPromise, formatWalletAccountId, getCore, getDefaultClient, getWalletProviderRegistry, reconcileWalletAccountsAgainstClient } from "@dynamic-labs-sdk/client/core";
4
+ import { WalletProviderEnum } from "@dynamic-labs/sdk-api-core";
5
+
6
+ //#region package.json
7
+ var name = "@dynamic-labs-sdk/metamask";
8
+ var version = "1.5.0";
9
+
10
+ //#endregion
11
+ //#region src/clearMetaMaskSessionStorage/clearMetaMaskSessionStorage.ts
12
+ const METAMASK_SDK_IDB_NAME = "mmconnect-kv-store";
13
+ /**
14
+ * Deletes the MetaMask SDK's IndexedDB session storage so the next connect call
15
+ * emits a fresh `display_uri` synchronously instead of spending the SDK's
16
+ * 10-second resume timeout reviving a dead pairing. Safe in SSR (no-op) and
17
+ * when the DB is held open by another tab (resolves on `blocked`).
18
+ *
19
+ * @not-instrumented
20
+ */
21
+ const clearMetaMaskSessionStorage = () => {
22
+ if (typeof indexedDB === "undefined") return Promise.resolve();
23
+ return new Promise((resolve) => {
24
+ try {
25
+ const request = indexedDB.deleteDatabase(METAMASK_SDK_IDB_NAME);
26
+ request.onsuccess = () => resolve();
27
+ request.onerror = () => resolve();
28
+ request.onblocked = () => resolve();
29
+ } catch {
30
+ resolve();
31
+ }
32
+ });
33
+ };
34
+
35
+ //#endregion
36
+ //#region src/errors/MetaMaskDisplayUriMissingError/MetaMaskDisplayUriMissingError.ts
37
+ var MetaMaskDisplayUriMissingError = class extends BaseError {
38
+ constructor() {
39
+ super({
40
+ cause: null,
41
+ code: "metamask_display_uri_missing",
42
+ docsUrl: null,
43
+ name: "MetaMaskDisplayUriMissingError",
44
+ shortMessage: "MetaMask SDK completed the connection without emitting a display_uri. The connect helper requires the SDK to produce a pairing URI. Please reach out to Dynamic about this error."
45
+ });
46
+ }
47
+ };
48
+
49
+ //#endregion
50
+ //#region src/getMetaMaskExtensionWalletProviderKey/getMetaMaskExtensionWalletProviderKey.ts
51
+ const METAMASK_NAME_NEEDLE = "metamask";
52
+ /**
53
+ * Returns the wallet provider key of the MetaMask browser extension announced
54
+ * for the given chain (EIP-6963 on EVM, Wallet Standard on Solana), or
55
+ * `undefined` when none is announced. Matches on normalized display name to
56
+ * cover MetaMask, Flask, and other variants. Synchronous and safe to call from
57
+ * a React render. Pass the returned key to `connectWithWalletProvider` to route
58
+ * the connection through the announced provider; fall back to the chain's
59
+ * `connectWithMetaMaskUri<Chain>` helper when `undefined`.
60
+ *
61
+ * @not-instrumented
62
+ */
63
+ const getMetaMaskExtensionWalletProviderKey = ({ chain }, client = getDefaultClient()) => {
64
+ return getWalletProviderRegistry(client).listProviders().find((provider) => provider.chain === chain && provider.walletProviderType === WalletProviderEnum.BrowserExtension && provider.metadata.displayName?.toLowerCase().includes(METAMASK_NAME_NEEDLE))?.key;
65
+ };
66
+
67
+ //#endregion
68
+ //#region src/connectWithMetaMaskUri/connectWithMetaMaskUri.ts
69
+ /**
70
+ * Drives a MetaMask SDK pairing for any chain and returns `{ approval, uri }`
71
+ * so consumers can render the QR / hand the URI to a deeplink. Logs an
72
+ * advisory warning when the extension is already announced for the chain —
73
+ * pairing still proceeds, but the consumer is told which announced provider
74
+ * key to route through for the best UX. Builds and registers the chain-
75
+ * specific wallet provider only after pairing is approved; the provider
76
+ * therefore never appears in the wallet picker (no `connect` method).
77
+ *
78
+ * @not-instrumented
79
+ */
80
+ const connectWithMetaMaskUri = async ({ addToDynamicWalletAccounts = true, chain, getController, walletProviderBuilder }, client = getDefaultClient()) => {
81
+ const announcedKey = getMetaMaskExtensionWalletProviderKey({ chain }, client);
82
+ if (announcedKey !== void 0) getCore(client).logger.warn(`[metamask] MetaMask extension is announced for ${chain} as wallet provider "${announcedKey}"; proceeding with URI pairing. Consider connectWithWalletProvider({ walletProviderKey: "${announcedKey}" }) for the best user experience.`);
83
+ const controller = await getController(client);
84
+ const uriDeferred = createDeferredPromise();
85
+ const unsubscribe = controller.onDisplayUri((displayUri) => {
86
+ uriDeferred.resolve(displayUri);
87
+ });
88
+ const connectPromise = controller.connect();
89
+ connectPromise.then(() => {
90
+ uriDeferred.reject(new MetaMaskDisplayUriMissingError());
91
+ }).catch((error) => {
92
+ uriDeferred.reject(error);
93
+ });
94
+ let uri;
95
+ try {
96
+ uri = await uriDeferred.promise;
97
+ } finally {
98
+ unsubscribe();
99
+ }
100
+ const approval = async () => {
101
+ await connectPromise;
102
+ const walletProvider = await walletProviderBuilder(client);
103
+ getWalletProviderRegistry(client).register({
104
+ priority: WalletProviderPriority.WALLET_SDK,
105
+ walletProvider
106
+ });
107
+ const { addresses } = await walletProvider.getConnectedAddresses();
108
+ const mainAddress = addresses[0];
109
+ if (mainAddress === void 0) throw new NoAddressFoundError();
110
+ return { walletAccounts: reconcileWalletAccountsAgainstClient({
111
+ addToDynamicWalletAccounts,
112
+ walletAccounts: [{
113
+ address: mainAddress,
114
+ chain: walletProvider.chain,
115
+ id: formatWalletAccountId({
116
+ address: mainAddress,
117
+ chain: walletProvider.chain,
118
+ walletProviderKey: walletProvider.key
119
+ }),
120
+ lastSelectedAt: null,
121
+ verifiedCredentialId: null,
122
+ walletProviderKey: walletProvider.key
123
+ }],
124
+ walletProviderKey: walletProvider.key
125
+ }, client) };
126
+ };
127
+ return {
128
+ approval,
129
+ uri
130
+ };
131
+ };
132
+
133
+ //#endregion
134
+ //#region src/errors/MetaMaskWalletNotConnectedError/MetaMaskWalletNotConnectedError.ts
135
+ var MetaMaskWalletNotConnectedError = class extends BaseError {
136
+ constructor() {
137
+ super({
138
+ cause: null,
139
+ code: "metamask_wallet_not_connected",
140
+ docsUrl: null,
141
+ name: "MetaMaskWalletNotConnectedError",
142
+ shortMessage: "MetaMask SDK has no connected wallet account. Complete the URI pairing (await the connect approval) before building the MetaMask wallet provider."
143
+ });
144
+ }
145
+ };
146
+
147
+ //#endregion
148
+ //#region src/exports/index.ts
149
+ assertPackageVersion(name, version);
150
+
151
+ //#endregion
152
+ export { MetaMaskDisplayUriMissingError, MetaMaskWalletNotConnectedError, clearMetaMaskSessionStorage, connectWithMetaMaskUri, getMetaMaskExtensionWalletProviderKey };
153
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","names":["uri: string"],"sources":["../package.json","../src/clearMetaMaskSessionStorage/clearMetaMaskSessionStorage.ts","../src/errors/MetaMaskDisplayUriMissingError/MetaMaskDisplayUriMissingError.ts","../src/getMetaMaskExtensionWalletProviderKey/getMetaMaskExtensionWalletProviderKey.ts","../src/connectWithMetaMaskUri/connectWithMetaMaskUri.ts","../src/errors/MetaMaskWalletNotConnectedError/MetaMaskWalletNotConnectedError.ts","../src/exports/index.ts"],"sourcesContent":["","// MetaMask SDK persists session state in this IndexedDB database.\n// Hardcoded inside `@metamask/connect-multichain` (the SDK shared by\n// every chain-specific connect-* facade) as `${DB_NAME}${dbNameSuffix}`\n// → `mmconnect` + `-kv-store` on web.\nconst METAMASK_SDK_IDB_NAME = 'mmconnect-kv-store';\n\n/**\n * Deletes the MetaMask SDK's IndexedDB session storage so the next connect call\n * emits a fresh `display_uri` synchronously instead of spending the SDK's\n * 10-second resume timeout reviving a dead pairing. Safe in SSR (no-op) and\n * when the DB is held open by another tab (resolves on `blocked`).\n *\n * @not-instrumented\n */\nexport const clearMetaMaskSessionStorage = (): Promise<void> => {\n if (typeof indexedDB === 'undefined') {\n return Promise.resolve();\n }\n\n return new Promise<void>((resolve) => {\n try {\n const request = indexedDB.deleteDatabase(METAMASK_SDK_IDB_NAME);\n request.onsuccess = () => resolve();\n // `onerror` / `onblocked` fire when a concurrent tab holds the\n // DB open. We still resolve so the consumer's connect flow is\n // not stalled indefinitely; the next tab close drops the lock\n // and subsequent runs reach the empty database. The Promise\n // executor already ignores subsequent resolve calls, so no\n // extra guard is needed when multiple lifecycle events fire on\n // the same request.\n request.onerror = () => resolve();\n request.onblocked = () => resolve();\n } catch {\n resolve();\n }\n });\n};\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class MetaMaskDisplayUriMissingError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'metamask_display_uri_missing',\n docsUrl: null,\n name: 'MetaMaskDisplayUriMissingError',\n shortMessage:\n 'MetaMask SDK completed the connection without emitting a display_uri. The connect helper requires the SDK to produce a pairing URI. Please reach out to Dynamic about this error.',\n });\n }\n}\n","import type { Chain, DynamicClient } from '@dynamic-labs-sdk/client';\nimport {\n getDefaultClient,\n getWalletProviderRegistry,\n} from '@dynamic-labs-sdk/client/core';\nimport { WalletProviderEnum } from '@dynamic-labs/sdk-api-core';\n\nconst METAMASK_NAME_NEEDLE = 'metamask';\n\ntype GetMetaMaskExtensionWalletProviderKeyParams = {\n /** Chain to scope the lookup to. */\n chain: Chain;\n};\n\n/**\n * Returns the wallet provider key of the MetaMask browser extension announced\n * for the given chain (EIP-6963 on EVM, Wallet Standard on Solana), or\n * `undefined` when none is announced. Matches on normalized display name to\n * cover MetaMask, Flask, and other variants. Synchronous and safe to call from\n * a React render. Pass the returned key to `connectWithWalletProvider` to route\n * the connection through the announced provider; fall back to the chain's\n * `connectWithMetaMaskUri<Chain>` helper when `undefined`.\n *\n * @not-instrumented\n */\nexport const getMetaMaskExtensionWalletProviderKey = (\n { chain }: GetMetaMaskExtensionWalletProviderKeyParams,\n client: DynamicClient = getDefaultClient()\n): string | undefined => {\n const providers = getWalletProviderRegistry(client).listProviders();\n\n const match = providers.find(\n (provider) =>\n provider.chain === chain &&\n provider.walletProviderType === WalletProviderEnum.BrowserExtension &&\n provider.metadata.displayName\n ?.toLowerCase()\n .includes(METAMASK_NAME_NEEDLE)\n );\n\n return match?.key;\n};\n","import type {\n Chain,\n DynamicClient,\n WalletAccount,\n WalletProviderUriConnectionResult,\n} from '@dynamic-labs-sdk/client';\nimport { NoAddressFoundError } from '@dynamic-labs-sdk/client';\nimport type { WalletProvider } from '@dynamic-labs-sdk/client/core';\nimport {\n WalletProviderPriority,\n createDeferredPromise,\n formatWalletAccountId,\n getCore,\n getDefaultClient,\n getWalletProviderRegistry,\n reconcileWalletAccountsAgainstClient,\n} from '@dynamic-labs-sdk/client/core';\n\nimport { MetaMaskDisplayUriMissingError } from '../errors/MetaMaskDisplayUriMissingError';\nimport { getMetaMaskExtensionWalletProviderKey } from '../getMetaMaskExtensionWalletProviderKey';\nimport type { MetaMaskController } from '../metamask.types';\n\nexport type ConnectWithMetaMaskUriParams = {\n /** Whether to add the connected wallet account to the Dynamic client. Defaults to `true`. */\n addToDynamicWalletAccounts?: boolean;\n /** Chain being connected; used to scope the extension-installed lookup. */\n chain: Chain;\n /** Returns the chain-specific `MetaMaskController` that drives the pairing. */\n getController: (client: DynamicClient) => Promise<MetaMaskController>;\n /**\n * Builds the chain-specific `WalletProvider` AFTER the pairing has been\n * approved. Must NOT include a `connect` method — the provider is registered\n * purely for signing routing and would otherwise leak into the wallet picker.\n */\n walletProviderBuilder: (client: DynamicClient) => Promise<WalletProvider>;\n};\n\n/**\n * Drives a MetaMask SDK pairing for any chain and returns `{ approval, uri }`\n * so consumers can render the QR / hand the URI to a deeplink. Logs an\n * advisory warning when the extension is already announced for the chain —\n * pairing still proceeds, but the consumer is told which announced provider\n * key to route through for the best UX. Builds and registers the chain-\n * specific wallet provider only after pairing is approved; the provider\n * therefore never appears in the wallet picker (no `connect` method).\n *\n * @not-instrumented\n */\nexport const connectWithMetaMaskUri = async (\n {\n addToDynamicWalletAccounts = true,\n chain,\n getController,\n walletProviderBuilder,\n }: ConnectWithMetaMaskUriParams,\n client: DynamicClient = getDefaultClient()\n): Promise<WalletProviderUriConnectionResult> => {\n const announcedKey = getMetaMaskExtensionWalletProviderKey({ chain }, client);\n\n if (announcedKey !== undefined) {\n getCore(client).logger.warn(\n `[metamask] MetaMask extension is announced for ${chain} as wallet provider \"${announcedKey}\"; proceeding with URI pairing. Consider connectWithWalletProvider({ walletProviderKey: \"${announcedKey}\" }) for the best user experience.`\n );\n }\n\n const controller = await getController(client);\n\n const uriDeferred = createDeferredPromise<string>();\n\n const unsubscribe = controller.onDisplayUri((displayUri) => {\n uriDeferred.resolve(displayUri);\n });\n\n const connectPromise = controller.connect();\n\n // If `connect` settles before a `display_uri` is emitted, no URI was made\n // available and the pairing is unusable. Reject the deferred so the caller\n // surfaces `MetaMaskDisplayUriMissingError` (or the underlying failure).\n connectPromise\n .then(() => {\n uriDeferred.reject(new MetaMaskDisplayUriMissingError());\n })\n .catch((error: unknown) => {\n uriDeferred.reject(error);\n });\n\n let uri: string;\n try {\n uri = await uriDeferred.promise;\n } finally {\n unsubscribe();\n }\n\n const approval = async (): Promise<{ walletAccounts: WalletAccount[] }> => {\n await connectPromise;\n\n const walletProvider = await walletProviderBuilder(client);\n\n getWalletProviderRegistry(client).register({\n priority: WalletProviderPriority.WALLET_SDK,\n walletProvider,\n });\n\n const { addresses } = await walletProvider.getConnectedAddresses();\n\n // MetaMask SDK exposes a single active address per pairing (same model as\n // EIP-1193 `eth_accounts`); we only materialize the first one.\n const mainAddress = addresses[0];\n\n if (mainAddress === undefined) {\n throw new NoAddressFoundError();\n }\n\n const walletAccount: WalletAccount = {\n address: mainAddress,\n chain: walletProvider.chain,\n id: formatWalletAccountId({\n address: mainAddress,\n chain: walletProvider.chain,\n walletProviderKey: walletProvider.key,\n }),\n lastSelectedAt: null,\n verifiedCredentialId: null,\n walletProviderKey: walletProvider.key,\n };\n\n const walletAccounts = reconcileWalletAccountsAgainstClient(\n {\n addToDynamicWalletAccounts,\n walletAccounts: [walletAccount],\n walletProviderKey: walletProvider.key,\n },\n client\n );\n\n return { walletAccounts };\n };\n\n return { approval, uri };\n};\n","import { BaseError } from '@dynamic-labs-sdk/client';\n\nexport class MetaMaskWalletNotConnectedError extends BaseError {\n constructor() {\n super({\n cause: null,\n code: 'metamask_wallet_not_connected',\n docsUrl: null,\n name: 'MetaMaskWalletNotConnectedError',\n shortMessage:\n 'MetaMask SDK has no connected wallet account. Complete the URI pairing (await the connect approval) before building the MetaMask wallet provider.',\n });\n }\n}\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport { name, version } from '../../package.json';\n\nassertPackageVersion(name, version);\n\nexport { clearMetaMaskSessionStorage } from '../clearMetaMaskSessionStorage';\nexport { connectWithMetaMaskUri } from '../connectWithMetaMaskUri';\nexport type { ConnectWithMetaMaskUriParams } from '../connectWithMetaMaskUri';\nexport { MetaMaskDisplayUriMissingError } from '../errors/MetaMaskDisplayUriMissingError';\nexport { MetaMaskWalletNotConnectedError } from '../errors/MetaMaskWalletNotConnectedError';\nexport { getMetaMaskExtensionWalletProviderKey } from '../getMetaMaskExtensionWalletProviderKey';\nexport type {\n DisplayUriListener,\n MetaMaskController,\n} from '../metamask.types';\n"],"mappings":";;;;;;;;;;;ACIA,MAAM,wBAAwB;;;;;;;;;AAU9B,MAAa,oCAAmD;AAC9D,KAAI,OAAO,cAAc,YACvB,QAAO,QAAQ,SAAS;AAG1B,QAAO,IAAI,SAAe,YAAY;AACpC,MAAI;GACF,MAAM,UAAU,UAAU,eAAe,sBAAsB;AAC/D,WAAQ,kBAAkB,SAAS;AAQnC,WAAQ,gBAAgB,SAAS;AACjC,WAAQ,kBAAkB,SAAS;UAC7B;AACN,YAAS;;GAEX;;;;;ACjCJ,IAAa,iCAAb,cAAoD,UAAU;CAC5D,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cACE;GACH,CAAC;;;;;;ACJN,MAAM,uBAAuB;;;;;;;;;;;;AAkB7B,MAAa,yCACX,EAAE,SACF,SAAwB,kBAAkB,KACnB;AAYvB,QAXkB,0BAA0B,OAAO,CAAC,eAAe,CAE3C,MACrB,aACC,SAAS,UAAU,SACnB,SAAS,uBAAuB,mBAAmB,oBACnD,SAAS,SAAS,aACd,aAAa,CACd,SAAS,qBAAqB,CACpC,EAEa;;;;;;;;;;;;;;;;ACQhB,MAAa,yBAAyB,OACpC,EACE,6BAA6B,MAC7B,OACA,eACA,yBAEF,SAAwB,kBAAkB,KACK;CAC/C,MAAM,eAAe,sCAAsC,EAAE,OAAO,EAAE,OAAO;AAE7E,KAAI,iBAAiB,OACnB,SAAQ,OAAO,CAAC,OAAO,KACrB,kDAAkD,MAAM,uBAAuB,aAAa,2FAA2F,aAAa,oCACrM;CAGH,MAAM,aAAa,MAAM,cAAc,OAAO;CAE9C,MAAM,cAAc,uBAA+B;CAEnD,MAAM,cAAc,WAAW,cAAc,eAAe;AAC1D,cAAY,QAAQ,WAAW;GAC/B;CAEF,MAAM,iBAAiB,WAAW,SAAS;AAK3C,gBACG,WAAW;AACV,cAAY,OAAO,IAAI,gCAAgC,CAAC;GACxD,CACD,OAAO,UAAmB;AACzB,cAAY,OAAO,MAAM;GACzB;CAEJ,IAAIA;AACJ,KAAI;AACF,QAAM,MAAM,YAAY;WAChB;AACR,eAAa;;CAGf,MAAM,WAAW,YAA0D;AACzE,QAAM;EAEN,MAAM,iBAAiB,MAAM,sBAAsB,OAAO;AAE1D,4BAA0B,OAAO,CAAC,SAAS;GACzC,UAAU,uBAAuB;GACjC;GACD,CAAC;EAEF,MAAM,EAAE,cAAc,MAAM,eAAe,uBAAuB;EAIlE,MAAM,cAAc,UAAU;AAE9B,MAAI,gBAAgB,OAClB,OAAM,IAAI,qBAAqB;AAyBjC,SAAO,EAAE,gBATc,qCACrB;GACE;GACA,gBAAgB,CAhBiB;IACnC,SAAS;IACT,OAAO,eAAe;IACtB,IAAI,sBAAsB;KACxB,SAAS;KACT,OAAO,eAAe;KACtB,mBAAmB,eAAe;KACnC,CAAC;IACF,gBAAgB;IAChB,sBAAsB;IACtB,mBAAmB,eAAe;IACnC,CAKkC;GAC/B,mBAAmB,eAAe;GACnC,EACD,OACD,EAEwB;;AAG3B,QAAO;EAAE;EAAU;EAAK;;;;;ACxI1B,IAAa,kCAAb,cAAqD,UAAU;CAC7D,cAAc;AACZ,QAAM;GACJ,OAAO;GACP,MAAM;GACN,SAAS;GACT,MAAM;GACN,cACE;GACH,CAAC;;;;;;ACPN,qBAAqB,MAAM,QAAQ"}
@@ -0,0 +1,23 @@
1
+ /** Listener invoked with each MetaMask SDK pairing `display_uri` emission. */
2
+ export type DisplayUriListener = (uri: string) => void;
3
+ /**
4
+ * Chain-agnostic surface chain-specific packages adapt their MetaMask SDK
5
+ * instance to (e.g. `@metamask/connect-evm`, `@metamask/connect-solana`).
6
+ * Owns the SDK pairing drive (`connect`) and the cached-`display_uri`
7
+ * bookkeeping (`onDisplayUri` / `getLatestDisplayUri` / `clearCachedDisplayUri`).
8
+ */
9
+ export type MetaMaskController = {
10
+ /** Drops the cached `display_uri` value without touching the SDK. */
11
+ clearCachedDisplayUri: () => void;
12
+ /**
13
+ * Drives the SDK pairing. Implementations should clear any stale
14
+ * "connecting" state on the underlying SDK first. Resolves once the
15
+ * pairing is approved by the wallet; rejects on rejection / timeout.
16
+ */
17
+ connect: () => Promise<void>;
18
+ /** Returns the latest URI captured by the SDK's `displayUri` handler, or `undefined`. */
19
+ getLatestDisplayUri: () => string | undefined;
20
+ /** Subscribes to `display_uri` emissions and replays the latest cached URI. Returns an unsubscribe. */
21
+ onDisplayUri: (listener: DisplayUriListener) => () => void;
22
+ };
23
+ //# sourceMappingURL=metamask.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metamask.types.d.ts","sourceRoot":"","sources":["../src/metamask.types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,MAAM,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,qEAAqE;IACrE,qBAAqB,EAAE,MAAM,IAAI,CAAC;IAClC;;;;OAIG;IACH,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,yFAAyF;IACzF,mBAAmB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAC9C,uGAAuG;IACvG,YAAY,EAAE,CAAC,QAAQ,EAAE,kBAAkB,KAAK,MAAM,IAAI,CAAC;CAC5D,CAAC"}