@dynamic-labs-sdk/wagmi 1.33.1 → 1.33.2

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.
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_syncDynamicWagmi = require('./syncDynamicWagmi-D6GEqPQ7.cjs');
1
+ const require_syncDynamicWagmi = require('./syncDynamicWagmi-DHH-mn2l.cjs');
2
2
  let _dynamic_labs_sdk_assert_package_version = require("@dynamic-labs-sdk/assert-package-version");
3
3
 
4
4
  //#region src/exports/index.ts
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as version, i as name, n as createDynamicWagmiConnector, r as NotEvmWalletAccountError, t as syncDynamicWagmi } from "./syncDynamicWagmi-DNk1KZar.esm.js";
1
+ import { a as version, i as name, n as createDynamicWagmiConnector, r as NotEvmWalletAccountError, t as syncDynamicWagmi } from "./syncDynamicWagmi-BJmIwjhg.esm.js";
2
2
  import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
3
3
 
4
4
  //#region src/exports/index.ts
package/dist/react.cjs CHANGED
@@ -1,4 +1,4 @@
1
- const require_syncDynamicWagmi = require('./syncDynamicWagmi-D6GEqPQ7.cjs');
1
+ const require_syncDynamicWagmi = require('./syncDynamicWagmi-DHH-mn2l.cjs');
2
2
  let _dynamic_labs_sdk_assert_package_version = require("@dynamic-labs-sdk/assert-package-version");
3
3
  let _dynamic_labs_sdk_client = require("@dynamic-labs-sdk/client");
4
4
  let react = require("react");
package/dist/react.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as version, i as name, t as syncDynamicWagmi } from "./syncDynamicWagmi-DNk1KZar.esm.js";
1
+ import { a as version, i as name, t as syncDynamicWagmi } from "./syncDynamicWagmi-BJmIwjhg.esm.js";
2
2
  import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
3
3
  import { getDefaultClient } from "@dynamic-labs-sdk/client";
4
4
  import { useEffect } from "react";
@@ -8,7 +8,7 @@ import { isEvmWalletAccount } from "@dynamic-labs-sdk/evm";
8
8
 
9
9
  //#region package.json
10
10
  var name = "@dynamic-labs-sdk/wagmi";
11
- var version = "1.33.1";
11
+ var version = "1.33.2";
12
12
 
13
13
  //#endregion
14
14
  //#region src/errors/NotEvmWalletAccountError/NotEvmWalletAccountError.ts
@@ -300,4 +300,4 @@ const syncDynamicWagmi = ({ config }, client = getDefaultClient$1()) => {
300
300
 
301
301
  //#endregion
302
302
  export { version as a, name as i, createDynamicWagmiConnector as n, NotEvmWalletAccountError as r, syncDynamicWagmi as t };
303
- //# sourceMappingURL=syncDynamicWagmi-DNk1KZar.esm.js.map
303
+ //# sourceMappingURL=syncDynamicWagmi-BJmIwjhg.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncDynamicWagmi-DNk1KZar.esm.js","names":["detachProviderEvents: (() => void) | undefined","getDefaultClient","syncedWalletAccountId: string | null | undefined","mirroredConnector: Connector | undefined","pendingDisconnect: Promise<void> | undefined"],"sources":["../package.json","../src/errors/NotEvmWalletAccountError/NotEvmWalletAccountError.ts","../src/createDynamicWagmiConnector/createDynamicWagmiConnector.ts","../src/syncDynamicWagmi/syncDynamicWagmi.ts"],"sourcesContent":["","import { BaseError } from '@dynamic-labs-sdk/client';\n\n/**\n * Thrown when a wallet account passed to the wagmi bridge does not resolve to\n * an EVM wallet provider. wagmi/viem only speak EVM, so non-EVM accounts\n * (Solana, Sui, etc.) cannot be surfaced as a wagmi connector.\n *\n * @example\n * ```ts\n * try {\n * createDynamicWagmiConnector({ walletAccount });\n * } catch (error) {\n * if (error instanceof NotEvmWalletAccountError) {\n * // the account is not an EVM account\n * }\n * }\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link isEvmWalletProvider}\n */\nexport class NotEvmWalletAccountError extends BaseError {\n // eslint-disable-next-line custom-rules/require-single-object-param -- mirrors the other SDK error constructors which take a plain message\n constructor(address: string) {\n super({\n cause: null,\n code: 'not_evm_wallet_account_error',\n docsUrl: null,\n name: 'NotEvmWalletAccountError',\n shortMessage: `${address} is not an EVM wallet account`,\n });\n }\n}\n","import {\n getDefaultClient,\n getWalletProviderFromWalletAccount,\n} from '@dynamic-labs-sdk/client/core';\nimport type {\n EvmWalletAccount,\n EvmWalletProvider,\n} from '@dynamic-labs-sdk/evm';\nimport { isEvmWalletProvider } from '@dynamic-labs-sdk/evm/core';\nimport { createWalletClientForWalletAccount } from '@dynamic-labs-sdk/evm/viem';\nimport {\n ChainNotConfiguredError,\n SwitchChainNotSupportedError,\n createConnector,\n} from '@wagmi/core';\nimport type { CreateConnectorFn } from '@wagmi/core';\nimport type { Address, Chain, Client, Hex } from 'viem';\nimport { getAddress } from 'viem';\n\nimport { NotEvmWalletAccountError } from '../errors/NotEvmWalletAccountError';\n\n/**\n * Human-readable connector name surfaced by wagmi (e.g. in `useConnect`).\n */\nconst DYNAMIC_CONNECTOR_NAME = 'Dynamic';\n\n/**\n * wagmi connector `type` discriminator. Kept stable so consumers can detect a\n * Dynamic-backed connector via `connector.type === 'dynamic'`.\n */\nconst DYNAMIC_CONNECTOR_TYPE = 'dynamic';\n\n/**\n * Parameters for {@link createDynamicWagmiConnector}.\n *\n * @example\n * ```ts\n * const params: CreateDynamicWagmiConnectorParams = { walletAccount };\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link EvmWalletAccount}\n */\nexport type CreateDynamicWagmiConnectorParams = {\n /**\n * The Dynamic EVM wallet account to expose as a wagmi connector. The\n * underlying wallet provider (embedded/OTP or external) is derived from it,\n * so callers never pass a provider directly.\n */\n walletAccount: EvmWalletAccount;\n};\n\n/**\n * Bridges a Dynamic EVM wallet account into a wagmi connector so it can drive\n * the entire wagmi/viem hook ecosystem (`useAccount`, `useSendTransaction`,\n * `useReadContract`, …) while Dynamic remains the source of truth for wallet\n * state.\n *\n * The connector derives the EVM wallet provider from the account and reuses the\n * SDK's own viem integration (`createWalletClientForWalletAccount`) so custom\n * wallet clients (e.g. smart accounts) keep working. Wallet events emitted by\n * the provider (account / network / disconnect) are forwarded to wagmi so its\n * cache stays in sync.\n *\n * This is the low-level primitive: it bridges the one account you pass in and\n * never follows Dynamic's selected account on its own. To have wagmi track\n * Dynamic's selection automatically, use `syncDynamicWagmi` (vanilla JS) or\n * `useSyncDynamicWagmi` / `SyncDynamicWagmi` (React, in\n * `@dynamic-labs-sdk/wagmi/react`), both of which build this connector for you.\n *\n * @example\n * ```ts\n * // Create the wagmi config once at startup, with no Dynamic connector.\n * const config = createConfig({ chains, transports });\n *\n * // Once the user has a Dynamic EVM wallet account, build the connector and\n * // connect. `connect` accepts a connector function, so the config is untouched.\n * const connector = createDynamicWagmiConnector({ walletAccount });\n * await connect(config, { connector });\n * ```\n *\n * Not every Dynamic wallet provider can change networks: when the underlying\n * provider has no `switchActiveNetwork`, `switchChain` (and `connect` with a\n * `chainId` that differs from the wallet's active network) rejects with wagmi's\n * `SwitchChainNotSupportedError` rather than pretending the switch happened.\n *\n * @param params.walletAccount - The Dynamic EVM wallet account to bridge.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A wagmi `CreateConnectorFn` to pass to `connect(config, { connector })`.\n * @throws {@link NotEvmWalletAccountError} when the account does not resolve to an EVM wallet provider.\n * @throws `SwitchChainNotSupportedError` when a network switch is requested and the wallet provider cannot switch networks.\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link NotEvmWalletAccountError}\n * @notInstrumented\n */\nexport const createDynamicWagmiConnector = (\n { walletAccount }: CreateDynamicWagmiConnectorParams,\n client = getDefaultClient()\n): CreateConnectorFn<EvmWalletProvider> =>\n createConnector((config) => {\n const walletProvider = getWalletProviderFromWalletAccount(\n { walletAccount },\n client\n );\n\n if (!isEvmWalletProvider(walletProvider)) {\n throw new NotEvmWalletAccountError(walletAccount.address);\n }\n\n const address = getAddress(walletAccount.address as Hex);\n\n const getChainId = async (): Promise<number> => {\n const { networkId } = await walletProvider.getActiveNetworkId();\n return Number(networkId);\n };\n\n // Retained so provider event subscriptions can be torn down on disconnect.\n let detachProviderEvents: (() => void) | undefined;\n\n const detachProviderEventsIfAttached = (): void => {\n detachProviderEvents?.();\n detachProviderEvents = undefined;\n };\n\n const emitDisconnect = (): void => {\n config.emitter.emit('disconnect');\n detachProviderEventsIfAttached();\n };\n\n const emitConnectedAddresses = ({\n addresses,\n }: {\n addresses: string[];\n }): void => {\n // The connector is bound to a single account and only ever signs with it,\n // so mirror that account's presence rather than whatever the underlying\n // wallet now reports; otherwise wagmi would surface an address whose\n // transactions this connection cannot actually sign.\n const isBoundAccountConnected = addresses.some(\n (candidate) => getAddress(candidate as Hex) === address\n );\n\n if (!isBoundAccountConnected) {\n emitDisconnect();\n return;\n }\n\n config.emitter.emit('change', { accounts: [address] });\n };\n\n const emitChainId = ({ chainId }: { chainId: number }): void => {\n config.emitter.emit('change', { chainId });\n };\n\n const switchToChain = async ({\n chainId,\n }: {\n chainId: number;\n }): Promise<Chain> => {\n const chain = config.chains.find((current) => current.id === chainId);\n\n if (!chain) {\n throw new ChainNotConfiguredError();\n }\n\n // `switchActiveNetwork` is optional on the provider. Emitting `change`\n // when it is absent would tell wagmi the switch succeeded while the\n // wallet stayed on its old network, so surface it as unsupported.\n if (!walletProvider.switchActiveNetwork) {\n // The error only reads the connector's `name`, but its type is the\n // fully-resolved wagmi `Connector` (id/type narrowed, emitter and\n // storage attached), which only exists once wagmi has set the connector\n // up — hence the cast around the one field it touches.\n throw new SwitchChainNotSupportedError({\n connector: { name: DYNAMIC_CONNECTOR_NAME } as never,\n });\n }\n\n await walletProvider.switchActiveNetwork({\n networkId: String(chainId),\n });\n\n emitChainId({ chainId });\n\n return chain;\n };\n\n // wagmi lets callers request a chain at connect time (`connect(config, {\n // connector, chainId })`) and expects the connector to move the wallet\n // there, so honour it through the same switch path as `switchChain` instead\n // of silently reporting whichever network the wallet happens to be on.\n const resolveChainIdForConnection = async ({\n requestedChainId,\n }: {\n requestedChainId: number | undefined;\n }): Promise<number> => {\n const activeChainId = await getChainId();\n\n const isSwitchNeeded =\n requestedChainId !== undefined && requestedChainId !== activeChainId;\n\n if (!isSwitchNeeded) {\n return activeChainId;\n }\n\n const chain = await switchToChain({ chainId: requestedChainId });\n\n return chain.id;\n };\n\n // Forward Dynamic wallet-provider events into wagmi. The listeners are the\n // same functions the connector's own `on*` handlers delegate to, so a\n // provider event and a wagmi-driven event take exactly one code path — and\n // none of them depend on the connector object existing yet.\n const attachProviderEvents = (): void => {\n const { events } = walletProvider;\n\n if (detachProviderEvents || !events) {\n return;\n }\n\n // Only the network payload needs translating; the other two already match\n // the shape the emit helpers take.\n const handleNetworkChanged = ({\n networkId,\n }: {\n networkId: string;\n }): void => emitChainId({ chainId: Number(networkId) });\n\n events.on('accountsChanged', emitConnectedAddresses);\n events.on('networkChanged', handleNetworkChanged);\n events.on('disconnected', emitDisconnect);\n\n detachProviderEvents = () => {\n events.off('accountsChanged', emitConnectedAddresses);\n events.off('networkChanged', handleNetworkChanged);\n events.off('disconnected', emitDisconnect);\n };\n };\n\n return {\n connect: async (parameters?: {\n chainId?: number;\n isReconnecting?: boolean;\n withCapabilities?: boolean;\n }) => {\n // Resolved before subscribing because it can reject (unconfigured or\n // unswitchable chain), and a failed attempt must not leave listeners\n // behind on the wallet.\n const chainId = await resolveChainIdForConnection({\n requestedChainId: parameters?.chainId,\n });\n\n attachProviderEvents();\n\n // wagmi v3 can ask connect() for per-account ERC-7846 connect\n // capabilities (Sign-In With Ethereum, spend permissions, ...), which\n // a wallet only reports through a `wallet_connect` handshake. Dynamic\n // connects the account itself, so there is nothing to report — wagmi's\n // own injected connector returns an empty map here for the same reason.\n // This says nothing about EIP-5792 execution capabilities (atomic\n // batching, paymaster service): those are answered by\n // `wallet_getCapabilities` on the provider, which external wallets pass\n // straight through while embedded wallets expose no `request` method at\n // all. Advertising Dynamic's own batching / sponsorship there is a\n // follow-up for if the need arises.\n const accounts = parameters?.withCapabilities\n ? [{ address, capabilities: {} }]\n : [address];\n\n // wagmi types `accounts` as conditional on the `withCapabilities`\n // generic, which it only infers from a literal argument — a value\n // branched at runtime satisfies neither side of the conditional, so the\n // cast is unavoidable. wagmi's own injected and mock connectors cast to\n // `never` here for exactly this reason.\n return {\n accounts: accounts as never,\n chainId,\n };\n },\n\n disconnect: async () => detachProviderEventsIfAttached(),\n\n getAccounts: async () => [address] as readonly Address[],\n\n getChainId,\n\n // Delegating to the SDK keeps custom wallet clients (e.g. smart accounts)\n // working instead of hand-rolling a `custom(provider)` transport. Dynamic\n // is the source of truth for the active network, so the requested\n // `chainId` is not used to re-scope the client here.\n getClient: async (): Promise<Client> => {\n const walletClient = await createWalletClientForWalletAccount(\n { walletAccount },\n client\n );\n\n // The SDK and wagmi can resolve different viem versions in the\n // monorepo; their structurally-identical client types are otherwise\n // nominally incompatible, so we bridge them here.\n return walletClient as unknown as Client;\n },\n\n // A required wagmi connector method: wagmi keeps the provider type opaque\n // through the `provider` generic of `CreateConnectorFn`, which this\n // connector fixes to `EvmWalletProvider`. Consumers reaching for the\n // underlying provider (`connector.getProvider()`) therefore get Dynamic's\n // typed wallet provider instead of an unknown.\n getProvider: async () => walletProvider,\n\n // wagmi requires a stable, unique connector id. The wallet account id is\n // already the SDK's canonical identifier for the account, so reuse it\n // rather than re-deriving the id contract here.\n id: `dynamic-${walletAccount.id}`,\n\n isAuthorized: async () => {\n const { addresses } = await walletProvider.getConnectedAddresses();\n return addresses.some(\n (connected) => getAddress(connected as Hex) === address\n );\n },\n\n name: DYNAMIC_CONNECTOR_NAME,\n\n onAccountsChanged: (addresses: string[]) =>\n emitConnectedAddresses({ addresses }),\n\n onChainChanged: (chainId: string) =>\n emitChainId({ chainId: Number(chainId) }),\n\n onDisconnect: emitDisconnect,\n\n switchChain: switchToChain,\n\n type: DYNAMIC_CONNECTOR_TYPE,\n };\n });\n","import {\n getDefaultClient,\n getSelectedWalletAccount,\n onEvent,\n} from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\nimport { isEvmWalletAccount } from '@dynamic-labs-sdk/evm';\nimport type { Config, Connector } from '@wagmi/core';\nimport { connect, disconnect } from '@wagmi/core';\n\nimport { createDynamicWagmiConnector } from '../createDynamicWagmiConnector';\n\n/**\n * Parameters for {@link syncDynamicWagmi}.\n *\n * @example\n * ```ts\n * const params: SyncDynamicWagmiParams = { config };\n * ```\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n */\nexport type SyncDynamicWagmiParams = {\n /**\n * The wagmi config to keep in sync with Dynamic's selected EVM wallet account.\n */\n config: Config;\n};\n\n/**\n * Keeps a wagmi `Config` in sync with Dynamic's selected EVM wallet account.\n *\n * This is the vanilla-JS counterpart to the `useSyncDynamicWagmi` React hook: it\n * subscribes to Dynamic's wallet events and, whenever the selected EVM account\n * changes (login, wallet switch, logout), rebuilds a Dynamic wagmi connector and\n * drives wagmi's `connect` / `disconnect` so `useAccount` and the rest of the\n * wagmi hooks/actions mirror Dynamic. Dynamic stays the source of truth; wagmi is\n * a read-only mirror.\n *\n * Unlike `createDynamicWagmiConnector` — which bridges a single account you pass\n * in and never switches on its own — this reacts to Dynamic's selection, so\n * calling `setSelectedWalletAccount` is enough to move wagmi. Call the returned\n * function to stop syncing and tear down the mirrored connection.\n *\n * Only the connection this sync created is ever disconnected, so wallets the\n * consumer connects to wagmi themselves keep working alongside Dynamic's.\n *\n * @example\n * ```ts\n * const stopSync = syncDynamicWagmi({ config });\n * // Later, wagmi follows Dynamic's selection automatically:\n * await setSelectedWalletAccount({ walletAccount: nextWalletAccount });\n * // When you're done:\n * stopSync();\n * ```\n *\n * @param params.config - The wagmi config to synchronize.\n * @param [client] - The Dynamic client instance. Only required when using\n * multiple Dynamic clients.\n * @returns A function that stops the sync, unsubscribes from Dynamic events, and\n * disconnects the mirrored wagmi connection.\n * @see {@link createDynamicWagmiConnector}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link SyncDynamicWagmi}\n * @notInstrumented\n */\nexport const syncDynamicWagmi = (\n { config }: SyncDynamicWagmiParams,\n client = getDefaultClient()\n): (() => void) => {\n // The id of the wallet account currently mirrored into wagmi, so repeated\n // events for the same account don't trigger redundant reconnects.\n let syncedWalletAccountId: string | null | undefined;\n\n // The connector instance backing the mirrored connection, kept so teardown\n // can target it explicitly. wagmi supports several concurrent connections and\n // `disconnect(config)` drops whichever one is currently active — which may\n // well be a wallet the consumer connected to wagmi themselves — so the sync\n // must never disconnect without naming its own connector.\n let mirroredConnector: Connector | undefined;\n\n // The disconnect currently in flight, so an overlapping caller (a sync run\n // switching accounts and the teardown, say) waits on it instead of asking\n // wagmi to disconnect the same connector twice.\n let pendingDisconnect: Promise<void> | undefined;\n\n const disconnectMirroredConnection = async (): Promise<void> => {\n if (pendingDisconnect) {\n await pendingDisconnect;\n return;\n }\n\n if (!mirroredConnector) {\n return;\n }\n\n const connectorToDisconnect = mirroredConnector;\n pendingDisconnect = disconnect(config, {\n connector: connectorToDisconnect,\n });\n\n try {\n await pendingDisconnect;\n\n // Dropped only once wagmi confirmed the disconnect, so a failed attempt\n // keeps the reference a later switch or teardown needs to retry with.\n mirroredConnector = undefined;\n } finally {\n pendingDisconnect = undefined;\n }\n };\n\n // Guards against overlapping runs: concurrent `sync()` calls would interleave\n // their connect/disconnect steps and corrupt the mirrored-account bookkeeping.\n let isSyncing = false;\n let resyncRequested = false;\n\n // Set once the sync is stopped so an in-flight `sync()` started before\n // teardown can bail out instead of racing the teardown's disconnect and\n // re-establishing a connection that outlives the subscription.\n let isCancelled = false;\n\n const syncOnce = async (): Promise<void> => {\n const selectedWallet = getSelectedWalletAccount(client);\n\n const evmWalletAccount =\n selectedWallet && isEvmWalletAccount(selectedWallet)\n ? selectedWallet\n : null;\n\n const nextWalletAccountId = evmWalletAccount?.id ?? null;\n\n if (nextWalletAccountId === syncedWalletAccountId) {\n return;\n }\n\n try {\n // Replace any previously mirrored connection first — wagmi's `connect`\n // adds to its connection registry without removing others, so without\n // this a switched-away wallet lingers and can reappear after logout.\n await disconnectMirroredConnection();\n\n if (!evmWalletAccount) {\n syncedWalletAccountId = nextWalletAccountId;\n return;\n }\n\n // The sync was stopped while this run was awaiting; teardown has already\n // disconnected, so skip connecting to avoid leaking a connection that\n // outlives the subscription.\n if (isCancelled) {\n return;\n }\n\n // Registering the connector up front (the same call `connect` makes for\n // a connector factory) yields the instance wagmi will store, which is\n // what later disconnects have to name.\n const connector = config._internal.connectors.setup(\n createDynamicWagmiConnector({ walletAccount: evmWalletAccount }, client)\n );\n\n await connect(config, { connector });\n\n mirroredConnector = connector;\n syncedWalletAccountId = nextWalletAccountId;\n } catch (error) {\n // Left `undefined` — \"nothing mirrored yet\" — rather than the account\n // this run failed on or the one it failed to leave: both compare equal to\n // a value a later event can legitimately report, which would make the\n // equality guard swallow the retry (a failed logout disconnect would keep\n // wagmi on the logged-out wallet forever).\n syncedWalletAccountId = undefined;\n getCore(client).logger.error(\n 'Failed to sync Dynamic wallet account with wagmi',\n error\n );\n }\n };\n\n const sync = async (): Promise<void> => {\n // Serialize runs: if one is in flight, flag a re-run so the latest selected\n // account is picked up once it finishes, rather than racing it.\n if (isSyncing) {\n resyncRequested = true;\n return;\n }\n isSyncing = true;\n\n try {\n // Draining the queued re-runs in a loop — rather than kicking off a\n // fire-and-forget follow-up run — keeps them inside this promise, so\n // awaiting `sync()` guarantees wagmi caught up with Dynamic's latest\n // selection.\n do {\n resyncRequested = false;\n await syncOnce();\n } while (resyncRequested);\n } finally {\n isSyncing = false;\n }\n };\n\n void sync();\n\n const unsubscribeFromWalletAccounts = onEvent(\n { event: 'walletAccountsChanged', listener: () => void sync() },\n client\n );\n\n const unsubscribeFromUser = onEvent(\n { event: 'userChanged', listener: () => void sync() },\n client\n );\n\n return () => {\n isCancelled = true;\n\n unsubscribeFromWalletAccounts();\n unsubscribeFromUser();\n\n // Tear down the mirrored connection so a stopped sync doesn't leave wagmi\n // connected to an account it's no longer tracking. wagmi rejects when the\n // connection is already gone (e.g. the wallet disconnected itself), which is\n // nothing to act on during teardown, so log instead of leaving an unhandled\n // rejection behind.\n void disconnectMirroredConnection().catch((error: unknown) => {\n getCore(client).logger.error(\n 'Failed to disconnect Dynamic wallet account from wagmi',\n error\n );\n });\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"syncDynamicWagmi-BJmIwjhg.esm.js","names":["detachProviderEvents: (() => void) | undefined","getDefaultClient","syncedWalletAccountId: string | null | undefined","mirroredConnector: Connector | undefined","pendingDisconnect: Promise<void> | undefined"],"sources":["../package.json","../src/errors/NotEvmWalletAccountError/NotEvmWalletAccountError.ts","../src/createDynamicWagmiConnector/createDynamicWagmiConnector.ts","../src/syncDynamicWagmi/syncDynamicWagmi.ts"],"sourcesContent":["","import { BaseError } from '@dynamic-labs-sdk/client';\n\n/**\n * Thrown when a wallet account passed to the wagmi bridge does not resolve to\n * an EVM wallet provider. wagmi/viem only speak EVM, so non-EVM accounts\n * (Solana, Sui, etc.) cannot be surfaced as a wagmi connector.\n *\n * @example\n * ```ts\n * try {\n * createDynamicWagmiConnector({ walletAccount });\n * } catch (error) {\n * if (error instanceof NotEvmWalletAccountError) {\n * // the account is not an EVM account\n * }\n * }\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link isEvmWalletProvider}\n */\nexport class NotEvmWalletAccountError extends BaseError {\n // eslint-disable-next-line custom-rules/require-single-object-param -- mirrors the other SDK error constructors which take a plain message\n constructor(address: string) {\n super({\n cause: null,\n code: 'not_evm_wallet_account_error',\n docsUrl: null,\n name: 'NotEvmWalletAccountError',\n shortMessage: `${address} is not an EVM wallet account`,\n });\n }\n}\n","import {\n getDefaultClient,\n getWalletProviderFromWalletAccount,\n} from '@dynamic-labs-sdk/client/core';\nimport type {\n EvmWalletAccount,\n EvmWalletProvider,\n} from '@dynamic-labs-sdk/evm';\nimport { isEvmWalletProvider } from '@dynamic-labs-sdk/evm/core';\nimport { createWalletClientForWalletAccount } from '@dynamic-labs-sdk/evm/viem';\nimport {\n ChainNotConfiguredError,\n SwitchChainNotSupportedError,\n createConnector,\n} from '@wagmi/core';\nimport type { CreateConnectorFn } from '@wagmi/core';\nimport type { Address, Chain, Client, Hex } from 'viem';\nimport { getAddress } from 'viem';\n\nimport { NotEvmWalletAccountError } from '../errors/NotEvmWalletAccountError';\n\n/**\n * Human-readable connector name surfaced by wagmi (e.g. in `useConnect`).\n */\nconst DYNAMIC_CONNECTOR_NAME = 'Dynamic';\n\n/**\n * wagmi connector `type` discriminator. Kept stable so consumers can detect a\n * Dynamic-backed connector via `connector.type === 'dynamic'`.\n */\nconst DYNAMIC_CONNECTOR_TYPE = 'dynamic';\n\n/**\n * Parameters for {@link createDynamicWagmiConnector}.\n *\n * @example\n * ```ts\n * const params: CreateDynamicWagmiConnectorParams = { walletAccount };\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link EvmWalletAccount}\n */\nexport type CreateDynamicWagmiConnectorParams = {\n /**\n * The Dynamic EVM wallet account to expose as a wagmi connector. The\n * underlying wallet provider (embedded/OTP or external) is derived from it,\n * so callers never pass a provider directly.\n */\n walletAccount: EvmWalletAccount;\n};\n\n/**\n * Bridges a Dynamic EVM wallet account into a wagmi connector so it can drive\n * the entire wagmi/viem hook ecosystem (`useAccount`, `useSendTransaction`,\n * `useReadContract`, …) while Dynamic remains the source of truth for wallet\n * state.\n *\n * The connector derives the EVM wallet provider from the account and reuses the\n * SDK's own viem integration (`createWalletClientForWalletAccount`) so custom\n * wallet clients (e.g. smart accounts) keep working. Wallet events emitted by\n * the provider (account / network / disconnect) are forwarded to wagmi so its\n * cache stays in sync.\n *\n * This is the low-level primitive: it bridges the one account you pass in and\n * never follows Dynamic's selected account on its own. To have wagmi track\n * Dynamic's selection automatically, use `syncDynamicWagmi` (vanilla JS) or\n * `useSyncDynamicWagmi` / `SyncDynamicWagmi` (React, in\n * `@dynamic-labs-sdk/wagmi/react`), both of which build this connector for you.\n *\n * @example\n * ```ts\n * // Create the wagmi config once at startup, with no Dynamic connector.\n * const config = createConfig({ chains, transports });\n *\n * // Once the user has a Dynamic EVM wallet account, build the connector and\n * // connect. `connect` accepts a connector function, so the config is untouched.\n * const connector = createDynamicWagmiConnector({ walletAccount });\n * await connect(config, { connector });\n * ```\n *\n * Not every Dynamic wallet provider can change networks: when the underlying\n * provider has no `switchActiveNetwork`, `switchChain` (and `connect` with a\n * `chainId` that differs from the wallet's active network) rejects with wagmi's\n * `SwitchChainNotSupportedError` rather than pretending the switch happened.\n *\n * @param params.walletAccount - The Dynamic EVM wallet account to bridge.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A wagmi `CreateConnectorFn` to pass to `connect(config, { connector })`.\n * @throws {@link NotEvmWalletAccountError} when the account does not resolve to an EVM wallet provider.\n * @throws `SwitchChainNotSupportedError` when a network switch is requested and the wallet provider cannot switch networks.\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link NotEvmWalletAccountError}\n * @notInstrumented\n */\nexport const createDynamicWagmiConnector = (\n { walletAccount }: CreateDynamicWagmiConnectorParams,\n client = getDefaultClient()\n): CreateConnectorFn<EvmWalletProvider> =>\n createConnector((config) => {\n const walletProvider = getWalletProviderFromWalletAccount(\n { walletAccount },\n client\n );\n\n if (!isEvmWalletProvider(walletProvider)) {\n throw new NotEvmWalletAccountError(walletAccount.address);\n }\n\n const address = getAddress(walletAccount.address as Hex);\n\n const getChainId = async (): Promise<number> => {\n const { networkId } = await walletProvider.getActiveNetworkId();\n return Number(networkId);\n };\n\n // Retained so provider event subscriptions can be torn down on disconnect.\n let detachProviderEvents: (() => void) | undefined;\n\n const detachProviderEventsIfAttached = (): void => {\n detachProviderEvents?.();\n detachProviderEvents = undefined;\n };\n\n const emitDisconnect = (): void => {\n config.emitter.emit('disconnect');\n detachProviderEventsIfAttached();\n };\n\n const emitConnectedAddresses = ({\n addresses,\n }: {\n addresses: string[];\n }): void => {\n // The connector is bound to a single account and only ever signs with it,\n // so mirror that account's presence rather than whatever the underlying\n // wallet now reports; otherwise wagmi would surface an address whose\n // transactions this connection cannot actually sign.\n const isBoundAccountConnected = addresses.some(\n (candidate) => getAddress(candidate as Hex) === address\n );\n\n if (!isBoundAccountConnected) {\n emitDisconnect();\n return;\n }\n\n config.emitter.emit('change', { accounts: [address] });\n };\n\n const emitChainId = ({ chainId }: { chainId: number }): void => {\n config.emitter.emit('change', { chainId });\n };\n\n const switchToChain = async ({\n chainId,\n }: {\n chainId: number;\n }): Promise<Chain> => {\n const chain = config.chains.find((current) => current.id === chainId);\n\n if (!chain) {\n throw new ChainNotConfiguredError();\n }\n\n // `switchActiveNetwork` is optional on the provider. Emitting `change`\n // when it is absent would tell wagmi the switch succeeded while the\n // wallet stayed on its old network, so surface it as unsupported.\n if (!walletProvider.switchActiveNetwork) {\n // The error only reads the connector's `name`, but its type is the\n // fully-resolved wagmi `Connector` (id/type narrowed, emitter and\n // storage attached), which only exists once wagmi has set the connector\n // up — hence the cast around the one field it touches.\n throw new SwitchChainNotSupportedError({\n connector: { name: DYNAMIC_CONNECTOR_NAME } as never,\n });\n }\n\n await walletProvider.switchActiveNetwork({\n networkId: String(chainId),\n });\n\n emitChainId({ chainId });\n\n return chain;\n };\n\n // wagmi lets callers request a chain at connect time (`connect(config, {\n // connector, chainId })`) and expects the connector to move the wallet\n // there, so honour it through the same switch path as `switchChain` instead\n // of silently reporting whichever network the wallet happens to be on.\n const resolveChainIdForConnection = async ({\n requestedChainId,\n }: {\n requestedChainId: number | undefined;\n }): Promise<number> => {\n const activeChainId = await getChainId();\n\n const isSwitchNeeded =\n requestedChainId !== undefined && requestedChainId !== activeChainId;\n\n if (!isSwitchNeeded) {\n return activeChainId;\n }\n\n const chain = await switchToChain({ chainId: requestedChainId });\n\n return chain.id;\n };\n\n // Forward Dynamic wallet-provider events into wagmi. The listeners are the\n // same functions the connector's own `on*` handlers delegate to, so a\n // provider event and a wagmi-driven event take exactly one code path — and\n // none of them depend on the connector object existing yet.\n const attachProviderEvents = (): void => {\n const { events } = walletProvider;\n\n if (detachProviderEvents || !events) {\n return;\n }\n\n // Only the network payload needs translating; the other two already match\n // the shape the emit helpers take.\n const handleNetworkChanged = ({\n networkId,\n }: {\n networkId: string;\n }): void => emitChainId({ chainId: Number(networkId) });\n\n events.on('accountsChanged', emitConnectedAddresses);\n events.on('networkChanged', handleNetworkChanged);\n events.on('disconnected', emitDisconnect);\n\n detachProviderEvents = () => {\n events.off('accountsChanged', emitConnectedAddresses);\n events.off('networkChanged', handleNetworkChanged);\n events.off('disconnected', emitDisconnect);\n };\n };\n\n return {\n connect: async (parameters?: {\n chainId?: number;\n isReconnecting?: boolean;\n withCapabilities?: boolean;\n }) => {\n // Resolved before subscribing because it can reject (unconfigured or\n // unswitchable chain), and a failed attempt must not leave listeners\n // behind on the wallet.\n const chainId = await resolveChainIdForConnection({\n requestedChainId: parameters?.chainId,\n });\n\n attachProviderEvents();\n\n // wagmi v3 can ask connect() for per-account ERC-7846 connect\n // capabilities (Sign-In With Ethereum, spend permissions, ...), which\n // a wallet only reports through a `wallet_connect` handshake. Dynamic\n // connects the account itself, so there is nothing to report — wagmi's\n // own injected connector returns an empty map here for the same reason.\n // This says nothing about EIP-5792 execution capabilities (atomic\n // batching, paymaster service): those are answered by\n // `wallet_getCapabilities` on the provider, which external wallets pass\n // straight through while embedded wallets expose no `request` method at\n // all. Advertising Dynamic's own batching / sponsorship there is a\n // follow-up for if the need arises.\n const accounts = parameters?.withCapabilities\n ? [{ address, capabilities: {} }]\n : [address];\n\n // wagmi types `accounts` as conditional on the `withCapabilities`\n // generic, which it only infers from a literal argument — a value\n // branched at runtime satisfies neither side of the conditional, so the\n // cast is unavoidable. wagmi's own injected and mock connectors cast to\n // `never` here for exactly this reason.\n return {\n accounts: accounts as never,\n chainId,\n };\n },\n\n disconnect: async () => detachProviderEventsIfAttached(),\n\n getAccounts: async () => [address] as readonly Address[],\n\n getChainId,\n\n // Delegating to the SDK keeps custom wallet clients (e.g. smart accounts)\n // working instead of hand-rolling a `custom(provider)` transport. Dynamic\n // is the source of truth for the active network, so the requested\n // `chainId` is not used to re-scope the client here.\n getClient: async (): Promise<Client> => {\n const walletClient = await createWalletClientForWalletAccount(\n { walletAccount },\n client\n );\n\n // The SDK and wagmi can resolve different viem versions in the\n // monorepo; their structurally-identical client types are otherwise\n // nominally incompatible, so we bridge them here.\n return walletClient as unknown as Client;\n },\n\n // A required wagmi connector method: wagmi keeps the provider type opaque\n // through the `provider` generic of `CreateConnectorFn`, which this\n // connector fixes to `EvmWalletProvider`. Consumers reaching for the\n // underlying provider (`connector.getProvider()`) therefore get Dynamic's\n // typed wallet provider instead of an unknown.\n getProvider: async () => walletProvider,\n\n // wagmi requires a stable, unique connector id. The wallet account id is\n // already the SDK's canonical identifier for the account, so reuse it\n // rather than re-deriving the id contract here.\n id: `dynamic-${walletAccount.id}`,\n\n isAuthorized: async () => {\n const { addresses } = await walletProvider.getConnectedAddresses();\n return addresses.some(\n (connected) => getAddress(connected as Hex) === address\n );\n },\n\n name: DYNAMIC_CONNECTOR_NAME,\n\n onAccountsChanged: (addresses: string[]) =>\n emitConnectedAddresses({ addresses }),\n\n onChainChanged: (chainId: string) =>\n emitChainId({ chainId: Number(chainId) }),\n\n onDisconnect: emitDisconnect,\n\n switchChain: switchToChain,\n\n type: DYNAMIC_CONNECTOR_TYPE,\n };\n });\n","import {\n getDefaultClient,\n getSelectedWalletAccount,\n onEvent,\n} from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\nimport { isEvmWalletAccount } from '@dynamic-labs-sdk/evm';\nimport type { Config, Connector } from '@wagmi/core';\nimport { connect, disconnect } from '@wagmi/core';\n\nimport { createDynamicWagmiConnector } from '../createDynamicWagmiConnector';\n\n/**\n * Parameters for {@link syncDynamicWagmi}.\n *\n * @example\n * ```ts\n * const params: SyncDynamicWagmiParams = { config };\n * ```\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n */\nexport type SyncDynamicWagmiParams = {\n /**\n * The wagmi config to keep in sync with Dynamic's selected EVM wallet account.\n */\n config: Config;\n};\n\n/**\n * Keeps a wagmi `Config` in sync with Dynamic's selected EVM wallet account.\n *\n * This is the vanilla-JS counterpart to the `useSyncDynamicWagmi` React hook: it\n * subscribes to Dynamic's wallet events and, whenever the selected EVM account\n * changes (login, wallet switch, logout), rebuilds a Dynamic wagmi connector and\n * drives wagmi's `connect` / `disconnect` so `useAccount` and the rest of the\n * wagmi hooks/actions mirror Dynamic. Dynamic stays the source of truth; wagmi is\n * a read-only mirror.\n *\n * Unlike `createDynamicWagmiConnector` — which bridges a single account you pass\n * in and never switches on its own — this reacts to Dynamic's selection, so\n * calling `setSelectedWalletAccount` is enough to move wagmi. Call the returned\n * function to stop syncing and tear down the mirrored connection.\n *\n * Only the connection this sync created is ever disconnected, so wallets the\n * consumer connects to wagmi themselves keep working alongside Dynamic's.\n *\n * @example\n * ```ts\n * const stopSync = syncDynamicWagmi({ config });\n * // Later, wagmi follows Dynamic's selection automatically:\n * await setSelectedWalletAccount({ walletAccount: nextWalletAccount });\n * // When you're done:\n * stopSync();\n * ```\n *\n * @param params.config - The wagmi config to synchronize.\n * @param [client] - The Dynamic client instance. Only required when using\n * multiple Dynamic clients.\n * @returns A function that stops the sync, unsubscribes from Dynamic events, and\n * disconnects the mirrored wagmi connection.\n * @see {@link createDynamicWagmiConnector}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link SyncDynamicWagmi}\n * @notInstrumented\n */\nexport const syncDynamicWagmi = (\n { config }: SyncDynamicWagmiParams,\n client = getDefaultClient()\n): (() => void) => {\n // The id of the wallet account currently mirrored into wagmi, so repeated\n // events for the same account don't trigger redundant reconnects.\n let syncedWalletAccountId: string | null | undefined;\n\n // The connector instance backing the mirrored connection, kept so teardown\n // can target it explicitly. wagmi supports several concurrent connections and\n // `disconnect(config)` drops whichever one is currently active — which may\n // well be a wallet the consumer connected to wagmi themselves — so the sync\n // must never disconnect without naming its own connector.\n let mirroredConnector: Connector | undefined;\n\n // The disconnect currently in flight, so an overlapping caller (a sync run\n // switching accounts and the teardown, say) waits on it instead of asking\n // wagmi to disconnect the same connector twice.\n let pendingDisconnect: Promise<void> | undefined;\n\n const disconnectMirroredConnection = async (): Promise<void> => {\n if (pendingDisconnect) {\n await pendingDisconnect;\n return;\n }\n\n if (!mirroredConnector) {\n return;\n }\n\n const connectorToDisconnect = mirroredConnector;\n pendingDisconnect = disconnect(config, {\n connector: connectorToDisconnect,\n });\n\n try {\n await pendingDisconnect;\n\n // Dropped only once wagmi confirmed the disconnect, so a failed attempt\n // keeps the reference a later switch or teardown needs to retry with.\n mirroredConnector = undefined;\n } finally {\n pendingDisconnect = undefined;\n }\n };\n\n // Guards against overlapping runs: concurrent `sync()` calls would interleave\n // their connect/disconnect steps and corrupt the mirrored-account bookkeeping.\n let isSyncing = false;\n let resyncRequested = false;\n\n // Set once the sync is stopped so an in-flight `sync()` started before\n // teardown can bail out instead of racing the teardown's disconnect and\n // re-establishing a connection that outlives the subscription.\n let isCancelled = false;\n\n const syncOnce = async (): Promise<void> => {\n const selectedWallet = getSelectedWalletAccount(client);\n\n const evmWalletAccount =\n selectedWallet && isEvmWalletAccount(selectedWallet)\n ? selectedWallet\n : null;\n\n const nextWalletAccountId = evmWalletAccount?.id ?? null;\n\n if (nextWalletAccountId === syncedWalletAccountId) {\n return;\n }\n\n try {\n // Replace any previously mirrored connection first — wagmi's `connect`\n // adds to its connection registry without removing others, so without\n // this a switched-away wallet lingers and can reappear after logout.\n await disconnectMirroredConnection();\n\n if (!evmWalletAccount) {\n syncedWalletAccountId = nextWalletAccountId;\n return;\n }\n\n // The sync was stopped while this run was awaiting; teardown has already\n // disconnected, so skip connecting to avoid leaking a connection that\n // outlives the subscription.\n if (isCancelled) {\n return;\n }\n\n // Registering the connector up front (the same call `connect` makes for\n // a connector factory) yields the instance wagmi will store, which is\n // what later disconnects have to name.\n const connector = config._internal.connectors.setup(\n createDynamicWagmiConnector({ walletAccount: evmWalletAccount }, client)\n );\n\n await connect(config, { connector });\n\n mirroredConnector = connector;\n syncedWalletAccountId = nextWalletAccountId;\n } catch (error) {\n // Left `undefined` — \"nothing mirrored yet\" — rather than the account\n // this run failed on or the one it failed to leave: both compare equal to\n // a value a later event can legitimately report, which would make the\n // equality guard swallow the retry (a failed logout disconnect would keep\n // wagmi on the logged-out wallet forever).\n syncedWalletAccountId = undefined;\n getCore(client).logger.error(\n 'Failed to sync Dynamic wallet account with wagmi',\n error\n );\n }\n };\n\n const sync = async (): Promise<void> => {\n // Serialize runs: if one is in flight, flag a re-run so the latest selected\n // account is picked up once it finishes, rather than racing it.\n if (isSyncing) {\n resyncRequested = true;\n return;\n }\n isSyncing = true;\n\n try {\n // Draining the queued re-runs in a loop — rather than kicking off a\n // fire-and-forget follow-up run — keeps them inside this promise, so\n // awaiting `sync()` guarantees wagmi caught up with Dynamic's latest\n // selection.\n do {\n resyncRequested = false;\n await syncOnce();\n } while (resyncRequested);\n } finally {\n isSyncing = false;\n }\n };\n\n void sync();\n\n const unsubscribeFromWalletAccounts = onEvent(\n { event: 'walletAccountsChanged', listener: () => void sync() },\n client\n );\n\n const unsubscribeFromUser = onEvent(\n { event: 'userChanged', listener: () => void sync() },\n client\n );\n\n return () => {\n isCancelled = true;\n\n unsubscribeFromWalletAccounts();\n unsubscribeFromUser();\n\n // Tear down the mirrored connection so a stopped sync doesn't leave wagmi\n // connected to an account it's no longer tracking. wagmi rejects when the\n // connection is already gone (e.g. the wallet disconnected itself), which is\n // nothing to act on during teardown, so log instead of leaving an unhandled\n // rejection behind.\n void disconnectMirroredConnection().catch((error: unknown) => {\n getCore(client).logger.error(\n 'Failed to disconnect Dynamic wallet account from wagmi',\n error\n );\n });\n };\n};\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ let _dynamic_labs_sdk_evm = require("@dynamic-labs-sdk/evm");
8
8
 
9
9
  //#region package.json
10
10
  var name = "@dynamic-labs-sdk/wagmi";
11
- var version = "1.33.1";
11
+ var version = "1.33.2";
12
12
 
13
13
  //#endregion
14
14
  //#region src/errors/NotEvmWalletAccountError/NotEvmWalletAccountError.ts
@@ -329,4 +329,4 @@ Object.defineProperty(exports, 'version', {
329
329
  return version;
330
330
  }
331
331
  });
332
- //# sourceMappingURL=syncDynamicWagmi-D6GEqPQ7.cjs.map
332
+ //# sourceMappingURL=syncDynamicWagmi-DHH-mn2l.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncDynamicWagmi-D6GEqPQ7.cjs","names":["BaseError","detachProviderEvents: (() => void) | undefined","ChainNotConfiguredError","SwitchChainNotSupportedError","syncedWalletAccountId: string | null | undefined","mirroredConnector: Connector | undefined","pendingDisconnect: Promise<void> | undefined"],"sources":["../package.json","../src/errors/NotEvmWalletAccountError/NotEvmWalletAccountError.ts","../src/createDynamicWagmiConnector/createDynamicWagmiConnector.ts","../src/syncDynamicWagmi/syncDynamicWagmi.ts"],"sourcesContent":["","import { BaseError } from '@dynamic-labs-sdk/client';\n\n/**\n * Thrown when a wallet account passed to the wagmi bridge does not resolve to\n * an EVM wallet provider. wagmi/viem only speak EVM, so non-EVM accounts\n * (Solana, Sui, etc.) cannot be surfaced as a wagmi connector.\n *\n * @example\n * ```ts\n * try {\n * createDynamicWagmiConnector({ walletAccount });\n * } catch (error) {\n * if (error instanceof NotEvmWalletAccountError) {\n * // the account is not an EVM account\n * }\n * }\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link isEvmWalletProvider}\n */\nexport class NotEvmWalletAccountError extends BaseError {\n // eslint-disable-next-line custom-rules/require-single-object-param -- mirrors the other SDK error constructors which take a plain message\n constructor(address: string) {\n super({\n cause: null,\n code: 'not_evm_wallet_account_error',\n docsUrl: null,\n name: 'NotEvmWalletAccountError',\n shortMessage: `${address} is not an EVM wallet account`,\n });\n }\n}\n","import {\n getDefaultClient,\n getWalletProviderFromWalletAccount,\n} from '@dynamic-labs-sdk/client/core';\nimport type {\n EvmWalletAccount,\n EvmWalletProvider,\n} from '@dynamic-labs-sdk/evm';\nimport { isEvmWalletProvider } from '@dynamic-labs-sdk/evm/core';\nimport { createWalletClientForWalletAccount } from '@dynamic-labs-sdk/evm/viem';\nimport {\n ChainNotConfiguredError,\n SwitchChainNotSupportedError,\n createConnector,\n} from '@wagmi/core';\nimport type { CreateConnectorFn } from '@wagmi/core';\nimport type { Address, Chain, Client, Hex } from 'viem';\nimport { getAddress } from 'viem';\n\nimport { NotEvmWalletAccountError } from '../errors/NotEvmWalletAccountError';\n\n/**\n * Human-readable connector name surfaced by wagmi (e.g. in `useConnect`).\n */\nconst DYNAMIC_CONNECTOR_NAME = 'Dynamic';\n\n/**\n * wagmi connector `type` discriminator. Kept stable so consumers can detect a\n * Dynamic-backed connector via `connector.type === 'dynamic'`.\n */\nconst DYNAMIC_CONNECTOR_TYPE = 'dynamic';\n\n/**\n * Parameters for {@link createDynamicWagmiConnector}.\n *\n * @example\n * ```ts\n * const params: CreateDynamicWagmiConnectorParams = { walletAccount };\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link EvmWalletAccount}\n */\nexport type CreateDynamicWagmiConnectorParams = {\n /**\n * The Dynamic EVM wallet account to expose as a wagmi connector. The\n * underlying wallet provider (embedded/OTP or external) is derived from it,\n * so callers never pass a provider directly.\n */\n walletAccount: EvmWalletAccount;\n};\n\n/**\n * Bridges a Dynamic EVM wallet account into a wagmi connector so it can drive\n * the entire wagmi/viem hook ecosystem (`useAccount`, `useSendTransaction`,\n * `useReadContract`, …) while Dynamic remains the source of truth for wallet\n * state.\n *\n * The connector derives the EVM wallet provider from the account and reuses the\n * SDK's own viem integration (`createWalletClientForWalletAccount`) so custom\n * wallet clients (e.g. smart accounts) keep working. Wallet events emitted by\n * the provider (account / network / disconnect) are forwarded to wagmi so its\n * cache stays in sync.\n *\n * This is the low-level primitive: it bridges the one account you pass in and\n * never follows Dynamic's selected account on its own. To have wagmi track\n * Dynamic's selection automatically, use `syncDynamicWagmi` (vanilla JS) or\n * `useSyncDynamicWagmi` / `SyncDynamicWagmi` (React, in\n * `@dynamic-labs-sdk/wagmi/react`), both of which build this connector for you.\n *\n * @example\n * ```ts\n * // Create the wagmi config once at startup, with no Dynamic connector.\n * const config = createConfig({ chains, transports });\n *\n * // Once the user has a Dynamic EVM wallet account, build the connector and\n * // connect. `connect` accepts a connector function, so the config is untouched.\n * const connector = createDynamicWagmiConnector({ walletAccount });\n * await connect(config, { connector });\n * ```\n *\n * Not every Dynamic wallet provider can change networks: when the underlying\n * provider has no `switchActiveNetwork`, `switchChain` (and `connect` with a\n * `chainId` that differs from the wallet's active network) rejects with wagmi's\n * `SwitchChainNotSupportedError` rather than pretending the switch happened.\n *\n * @param params.walletAccount - The Dynamic EVM wallet account to bridge.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A wagmi `CreateConnectorFn` to pass to `connect(config, { connector })`.\n * @throws {@link NotEvmWalletAccountError} when the account does not resolve to an EVM wallet provider.\n * @throws `SwitchChainNotSupportedError` when a network switch is requested and the wallet provider cannot switch networks.\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link NotEvmWalletAccountError}\n * @notInstrumented\n */\nexport const createDynamicWagmiConnector = (\n { walletAccount }: CreateDynamicWagmiConnectorParams,\n client = getDefaultClient()\n): CreateConnectorFn<EvmWalletProvider> =>\n createConnector((config) => {\n const walletProvider = getWalletProviderFromWalletAccount(\n { walletAccount },\n client\n );\n\n if (!isEvmWalletProvider(walletProvider)) {\n throw new NotEvmWalletAccountError(walletAccount.address);\n }\n\n const address = getAddress(walletAccount.address as Hex);\n\n const getChainId = async (): Promise<number> => {\n const { networkId } = await walletProvider.getActiveNetworkId();\n return Number(networkId);\n };\n\n // Retained so provider event subscriptions can be torn down on disconnect.\n let detachProviderEvents: (() => void) | undefined;\n\n const detachProviderEventsIfAttached = (): void => {\n detachProviderEvents?.();\n detachProviderEvents = undefined;\n };\n\n const emitDisconnect = (): void => {\n config.emitter.emit('disconnect');\n detachProviderEventsIfAttached();\n };\n\n const emitConnectedAddresses = ({\n addresses,\n }: {\n addresses: string[];\n }): void => {\n // The connector is bound to a single account and only ever signs with it,\n // so mirror that account's presence rather than whatever the underlying\n // wallet now reports; otherwise wagmi would surface an address whose\n // transactions this connection cannot actually sign.\n const isBoundAccountConnected = addresses.some(\n (candidate) => getAddress(candidate as Hex) === address\n );\n\n if (!isBoundAccountConnected) {\n emitDisconnect();\n return;\n }\n\n config.emitter.emit('change', { accounts: [address] });\n };\n\n const emitChainId = ({ chainId }: { chainId: number }): void => {\n config.emitter.emit('change', { chainId });\n };\n\n const switchToChain = async ({\n chainId,\n }: {\n chainId: number;\n }): Promise<Chain> => {\n const chain = config.chains.find((current) => current.id === chainId);\n\n if (!chain) {\n throw new ChainNotConfiguredError();\n }\n\n // `switchActiveNetwork` is optional on the provider. Emitting `change`\n // when it is absent would tell wagmi the switch succeeded while the\n // wallet stayed on its old network, so surface it as unsupported.\n if (!walletProvider.switchActiveNetwork) {\n // The error only reads the connector's `name`, but its type is the\n // fully-resolved wagmi `Connector` (id/type narrowed, emitter and\n // storage attached), which only exists once wagmi has set the connector\n // up — hence the cast around the one field it touches.\n throw new SwitchChainNotSupportedError({\n connector: { name: DYNAMIC_CONNECTOR_NAME } as never,\n });\n }\n\n await walletProvider.switchActiveNetwork({\n networkId: String(chainId),\n });\n\n emitChainId({ chainId });\n\n return chain;\n };\n\n // wagmi lets callers request a chain at connect time (`connect(config, {\n // connector, chainId })`) and expects the connector to move the wallet\n // there, so honour it through the same switch path as `switchChain` instead\n // of silently reporting whichever network the wallet happens to be on.\n const resolveChainIdForConnection = async ({\n requestedChainId,\n }: {\n requestedChainId: number | undefined;\n }): Promise<number> => {\n const activeChainId = await getChainId();\n\n const isSwitchNeeded =\n requestedChainId !== undefined && requestedChainId !== activeChainId;\n\n if (!isSwitchNeeded) {\n return activeChainId;\n }\n\n const chain = await switchToChain({ chainId: requestedChainId });\n\n return chain.id;\n };\n\n // Forward Dynamic wallet-provider events into wagmi. The listeners are the\n // same functions the connector's own `on*` handlers delegate to, so a\n // provider event and a wagmi-driven event take exactly one code path — and\n // none of them depend on the connector object existing yet.\n const attachProviderEvents = (): void => {\n const { events } = walletProvider;\n\n if (detachProviderEvents || !events) {\n return;\n }\n\n // Only the network payload needs translating; the other two already match\n // the shape the emit helpers take.\n const handleNetworkChanged = ({\n networkId,\n }: {\n networkId: string;\n }): void => emitChainId({ chainId: Number(networkId) });\n\n events.on('accountsChanged', emitConnectedAddresses);\n events.on('networkChanged', handleNetworkChanged);\n events.on('disconnected', emitDisconnect);\n\n detachProviderEvents = () => {\n events.off('accountsChanged', emitConnectedAddresses);\n events.off('networkChanged', handleNetworkChanged);\n events.off('disconnected', emitDisconnect);\n };\n };\n\n return {\n connect: async (parameters?: {\n chainId?: number;\n isReconnecting?: boolean;\n withCapabilities?: boolean;\n }) => {\n // Resolved before subscribing because it can reject (unconfigured or\n // unswitchable chain), and a failed attempt must not leave listeners\n // behind on the wallet.\n const chainId = await resolveChainIdForConnection({\n requestedChainId: parameters?.chainId,\n });\n\n attachProviderEvents();\n\n // wagmi v3 can ask connect() for per-account ERC-7846 connect\n // capabilities (Sign-In With Ethereum, spend permissions, ...), which\n // a wallet only reports through a `wallet_connect` handshake. Dynamic\n // connects the account itself, so there is nothing to report — wagmi's\n // own injected connector returns an empty map here for the same reason.\n // This says nothing about EIP-5792 execution capabilities (atomic\n // batching, paymaster service): those are answered by\n // `wallet_getCapabilities` on the provider, which external wallets pass\n // straight through while embedded wallets expose no `request` method at\n // all. Advertising Dynamic's own batching / sponsorship there is a\n // follow-up for if the need arises.\n const accounts = parameters?.withCapabilities\n ? [{ address, capabilities: {} }]\n : [address];\n\n // wagmi types `accounts` as conditional on the `withCapabilities`\n // generic, which it only infers from a literal argument — a value\n // branched at runtime satisfies neither side of the conditional, so the\n // cast is unavoidable. wagmi's own injected and mock connectors cast to\n // `never` here for exactly this reason.\n return {\n accounts: accounts as never,\n chainId,\n };\n },\n\n disconnect: async () => detachProviderEventsIfAttached(),\n\n getAccounts: async () => [address] as readonly Address[],\n\n getChainId,\n\n // Delegating to the SDK keeps custom wallet clients (e.g. smart accounts)\n // working instead of hand-rolling a `custom(provider)` transport. Dynamic\n // is the source of truth for the active network, so the requested\n // `chainId` is not used to re-scope the client here.\n getClient: async (): Promise<Client> => {\n const walletClient = await createWalletClientForWalletAccount(\n { walletAccount },\n client\n );\n\n // The SDK and wagmi can resolve different viem versions in the\n // monorepo; their structurally-identical client types are otherwise\n // nominally incompatible, so we bridge them here.\n return walletClient as unknown as Client;\n },\n\n // A required wagmi connector method: wagmi keeps the provider type opaque\n // through the `provider` generic of `CreateConnectorFn`, which this\n // connector fixes to `EvmWalletProvider`. Consumers reaching for the\n // underlying provider (`connector.getProvider()`) therefore get Dynamic's\n // typed wallet provider instead of an unknown.\n getProvider: async () => walletProvider,\n\n // wagmi requires a stable, unique connector id. The wallet account id is\n // already the SDK's canonical identifier for the account, so reuse it\n // rather than re-deriving the id contract here.\n id: `dynamic-${walletAccount.id}`,\n\n isAuthorized: async () => {\n const { addresses } = await walletProvider.getConnectedAddresses();\n return addresses.some(\n (connected) => getAddress(connected as Hex) === address\n );\n },\n\n name: DYNAMIC_CONNECTOR_NAME,\n\n onAccountsChanged: (addresses: string[]) =>\n emitConnectedAddresses({ addresses }),\n\n onChainChanged: (chainId: string) =>\n emitChainId({ chainId: Number(chainId) }),\n\n onDisconnect: emitDisconnect,\n\n switchChain: switchToChain,\n\n type: DYNAMIC_CONNECTOR_TYPE,\n };\n });\n","import {\n getDefaultClient,\n getSelectedWalletAccount,\n onEvent,\n} from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\nimport { isEvmWalletAccount } from '@dynamic-labs-sdk/evm';\nimport type { Config, Connector } from '@wagmi/core';\nimport { connect, disconnect } from '@wagmi/core';\n\nimport { createDynamicWagmiConnector } from '../createDynamicWagmiConnector';\n\n/**\n * Parameters for {@link syncDynamicWagmi}.\n *\n * @example\n * ```ts\n * const params: SyncDynamicWagmiParams = { config };\n * ```\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n */\nexport type SyncDynamicWagmiParams = {\n /**\n * The wagmi config to keep in sync with Dynamic's selected EVM wallet account.\n */\n config: Config;\n};\n\n/**\n * Keeps a wagmi `Config` in sync with Dynamic's selected EVM wallet account.\n *\n * This is the vanilla-JS counterpart to the `useSyncDynamicWagmi` React hook: it\n * subscribes to Dynamic's wallet events and, whenever the selected EVM account\n * changes (login, wallet switch, logout), rebuilds a Dynamic wagmi connector and\n * drives wagmi's `connect` / `disconnect` so `useAccount` and the rest of the\n * wagmi hooks/actions mirror Dynamic. Dynamic stays the source of truth; wagmi is\n * a read-only mirror.\n *\n * Unlike `createDynamicWagmiConnector` — which bridges a single account you pass\n * in and never switches on its own — this reacts to Dynamic's selection, so\n * calling `setSelectedWalletAccount` is enough to move wagmi. Call the returned\n * function to stop syncing and tear down the mirrored connection.\n *\n * Only the connection this sync created is ever disconnected, so wallets the\n * consumer connects to wagmi themselves keep working alongside Dynamic's.\n *\n * @example\n * ```ts\n * const stopSync = syncDynamicWagmi({ config });\n * // Later, wagmi follows Dynamic's selection automatically:\n * await setSelectedWalletAccount({ walletAccount: nextWalletAccount });\n * // When you're done:\n * stopSync();\n * ```\n *\n * @param params.config - The wagmi config to synchronize.\n * @param [client] - The Dynamic client instance. Only required when using\n * multiple Dynamic clients.\n * @returns A function that stops the sync, unsubscribes from Dynamic events, and\n * disconnects the mirrored wagmi connection.\n * @see {@link createDynamicWagmiConnector}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link SyncDynamicWagmi}\n * @notInstrumented\n */\nexport const syncDynamicWagmi = (\n { config }: SyncDynamicWagmiParams,\n client = getDefaultClient()\n): (() => void) => {\n // The id of the wallet account currently mirrored into wagmi, so repeated\n // events for the same account don't trigger redundant reconnects.\n let syncedWalletAccountId: string | null | undefined;\n\n // The connector instance backing the mirrored connection, kept so teardown\n // can target it explicitly. wagmi supports several concurrent connections and\n // `disconnect(config)` drops whichever one is currently active — which may\n // well be a wallet the consumer connected to wagmi themselves — so the sync\n // must never disconnect without naming its own connector.\n let mirroredConnector: Connector | undefined;\n\n // The disconnect currently in flight, so an overlapping caller (a sync run\n // switching accounts and the teardown, say) waits on it instead of asking\n // wagmi to disconnect the same connector twice.\n let pendingDisconnect: Promise<void> | undefined;\n\n const disconnectMirroredConnection = async (): Promise<void> => {\n if (pendingDisconnect) {\n await pendingDisconnect;\n return;\n }\n\n if (!mirroredConnector) {\n return;\n }\n\n const connectorToDisconnect = mirroredConnector;\n pendingDisconnect = disconnect(config, {\n connector: connectorToDisconnect,\n });\n\n try {\n await pendingDisconnect;\n\n // Dropped only once wagmi confirmed the disconnect, so a failed attempt\n // keeps the reference a later switch or teardown needs to retry with.\n mirroredConnector = undefined;\n } finally {\n pendingDisconnect = undefined;\n }\n };\n\n // Guards against overlapping runs: concurrent `sync()` calls would interleave\n // their connect/disconnect steps and corrupt the mirrored-account bookkeeping.\n let isSyncing = false;\n let resyncRequested = false;\n\n // Set once the sync is stopped so an in-flight `sync()` started before\n // teardown can bail out instead of racing the teardown's disconnect and\n // re-establishing a connection that outlives the subscription.\n let isCancelled = false;\n\n const syncOnce = async (): Promise<void> => {\n const selectedWallet = getSelectedWalletAccount(client);\n\n const evmWalletAccount =\n selectedWallet && isEvmWalletAccount(selectedWallet)\n ? selectedWallet\n : null;\n\n const nextWalletAccountId = evmWalletAccount?.id ?? null;\n\n if (nextWalletAccountId === syncedWalletAccountId) {\n return;\n }\n\n try {\n // Replace any previously mirrored connection first — wagmi's `connect`\n // adds to its connection registry without removing others, so without\n // this a switched-away wallet lingers and can reappear after logout.\n await disconnectMirroredConnection();\n\n if (!evmWalletAccount) {\n syncedWalletAccountId = nextWalletAccountId;\n return;\n }\n\n // The sync was stopped while this run was awaiting; teardown has already\n // disconnected, so skip connecting to avoid leaking a connection that\n // outlives the subscription.\n if (isCancelled) {\n return;\n }\n\n // Registering the connector up front (the same call `connect` makes for\n // a connector factory) yields the instance wagmi will store, which is\n // what later disconnects have to name.\n const connector = config._internal.connectors.setup(\n createDynamicWagmiConnector({ walletAccount: evmWalletAccount }, client)\n );\n\n await connect(config, { connector });\n\n mirroredConnector = connector;\n syncedWalletAccountId = nextWalletAccountId;\n } catch (error) {\n // Left `undefined` — \"nothing mirrored yet\" — rather than the account\n // this run failed on or the one it failed to leave: both compare equal to\n // a value a later event can legitimately report, which would make the\n // equality guard swallow the retry (a failed logout disconnect would keep\n // wagmi on the logged-out wallet forever).\n syncedWalletAccountId = undefined;\n getCore(client).logger.error(\n 'Failed to sync Dynamic wallet account with wagmi',\n error\n );\n }\n };\n\n const sync = async (): Promise<void> => {\n // Serialize runs: if one is in flight, flag a re-run so the latest selected\n // account is picked up once it finishes, rather than racing it.\n if (isSyncing) {\n resyncRequested = true;\n return;\n }\n isSyncing = true;\n\n try {\n // Draining the queued re-runs in a loop — rather than kicking off a\n // fire-and-forget follow-up run — keeps them inside this promise, so\n // awaiting `sync()` guarantees wagmi caught up with Dynamic's latest\n // selection.\n do {\n resyncRequested = false;\n await syncOnce();\n } while (resyncRequested);\n } finally {\n isSyncing = false;\n }\n };\n\n void sync();\n\n const unsubscribeFromWalletAccounts = onEvent(\n { event: 'walletAccountsChanged', listener: () => void sync() },\n client\n );\n\n const unsubscribeFromUser = onEvent(\n { event: 'userChanged', listener: () => void sync() },\n client\n );\n\n return () => {\n isCancelled = true;\n\n unsubscribeFromWalletAccounts();\n unsubscribeFromUser();\n\n // Tear down the mirrored connection so a stopped sync doesn't leave wagmi\n // connected to an account it's no longer tracking. wagmi rejects when the\n // connection is already gone (e.g. the wallet disconnected itself), which is\n // nothing to act on during teardown, so log instead of leaving an unhandled\n // rejection behind.\n void disconnectMirroredConnection().catch((error: unknown) => {\n getCore(client).logger.error(\n 'Failed to disconnect Dynamic wallet account from wagmi',\n error\n );\n });\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"syncDynamicWagmi-DHH-mn2l.cjs","names":["BaseError","detachProviderEvents: (() => void) | undefined","ChainNotConfiguredError","SwitchChainNotSupportedError","syncedWalletAccountId: string | null | undefined","mirroredConnector: Connector | undefined","pendingDisconnect: Promise<void> | undefined"],"sources":["../package.json","../src/errors/NotEvmWalletAccountError/NotEvmWalletAccountError.ts","../src/createDynamicWagmiConnector/createDynamicWagmiConnector.ts","../src/syncDynamicWagmi/syncDynamicWagmi.ts"],"sourcesContent":["","import { BaseError } from '@dynamic-labs-sdk/client';\n\n/**\n * Thrown when a wallet account passed to the wagmi bridge does not resolve to\n * an EVM wallet provider. wagmi/viem only speak EVM, so non-EVM accounts\n * (Solana, Sui, etc.) cannot be surfaced as a wagmi connector.\n *\n * @example\n * ```ts\n * try {\n * createDynamicWagmiConnector({ walletAccount });\n * } catch (error) {\n * if (error instanceof NotEvmWalletAccountError) {\n * // the account is not an EVM account\n * }\n * }\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link isEvmWalletProvider}\n */\nexport class NotEvmWalletAccountError extends BaseError {\n // eslint-disable-next-line custom-rules/require-single-object-param -- mirrors the other SDK error constructors which take a plain message\n constructor(address: string) {\n super({\n cause: null,\n code: 'not_evm_wallet_account_error',\n docsUrl: null,\n name: 'NotEvmWalletAccountError',\n shortMessage: `${address} is not an EVM wallet account`,\n });\n }\n}\n","import {\n getDefaultClient,\n getWalletProviderFromWalletAccount,\n} from '@dynamic-labs-sdk/client/core';\nimport type {\n EvmWalletAccount,\n EvmWalletProvider,\n} from '@dynamic-labs-sdk/evm';\nimport { isEvmWalletProvider } from '@dynamic-labs-sdk/evm/core';\nimport { createWalletClientForWalletAccount } from '@dynamic-labs-sdk/evm/viem';\nimport {\n ChainNotConfiguredError,\n SwitchChainNotSupportedError,\n createConnector,\n} from '@wagmi/core';\nimport type { CreateConnectorFn } from '@wagmi/core';\nimport type { Address, Chain, Client, Hex } from 'viem';\nimport { getAddress } from 'viem';\n\nimport { NotEvmWalletAccountError } from '../errors/NotEvmWalletAccountError';\n\n/**\n * Human-readable connector name surfaced by wagmi (e.g. in `useConnect`).\n */\nconst DYNAMIC_CONNECTOR_NAME = 'Dynamic';\n\n/**\n * wagmi connector `type` discriminator. Kept stable so consumers can detect a\n * Dynamic-backed connector via `connector.type === 'dynamic'`.\n */\nconst DYNAMIC_CONNECTOR_TYPE = 'dynamic';\n\n/**\n * Parameters for {@link createDynamicWagmiConnector}.\n *\n * @example\n * ```ts\n * const params: CreateDynamicWagmiConnectorParams = { walletAccount };\n * ```\n * @see {@link createDynamicWagmiConnector}\n * @see {@link EvmWalletAccount}\n */\nexport type CreateDynamicWagmiConnectorParams = {\n /**\n * The Dynamic EVM wallet account to expose as a wagmi connector. The\n * underlying wallet provider (embedded/OTP or external) is derived from it,\n * so callers never pass a provider directly.\n */\n walletAccount: EvmWalletAccount;\n};\n\n/**\n * Bridges a Dynamic EVM wallet account into a wagmi connector so it can drive\n * the entire wagmi/viem hook ecosystem (`useAccount`, `useSendTransaction`,\n * `useReadContract`, …) while Dynamic remains the source of truth for wallet\n * state.\n *\n * The connector derives the EVM wallet provider from the account and reuses the\n * SDK's own viem integration (`createWalletClientForWalletAccount`) so custom\n * wallet clients (e.g. smart accounts) keep working. Wallet events emitted by\n * the provider (account / network / disconnect) are forwarded to wagmi so its\n * cache stays in sync.\n *\n * This is the low-level primitive: it bridges the one account you pass in and\n * never follows Dynamic's selected account on its own. To have wagmi track\n * Dynamic's selection automatically, use `syncDynamicWagmi` (vanilla JS) or\n * `useSyncDynamicWagmi` / `SyncDynamicWagmi` (React, in\n * `@dynamic-labs-sdk/wagmi/react`), both of which build this connector for you.\n *\n * @example\n * ```ts\n * // Create the wagmi config once at startup, with no Dynamic connector.\n * const config = createConfig({ chains, transports });\n *\n * // Once the user has a Dynamic EVM wallet account, build the connector and\n * // connect. `connect` accepts a connector function, so the config is untouched.\n * const connector = createDynamicWagmiConnector({ walletAccount });\n * await connect(config, { connector });\n * ```\n *\n * Not every Dynamic wallet provider can change networks: when the underlying\n * provider has no `switchActiveNetwork`, `switchChain` (and `connect` with a\n * `chainId` that differs from the wallet's active network) rejects with wagmi's\n * `SwitchChainNotSupportedError` rather than pretending the switch happened.\n *\n * @param params.walletAccount - The Dynamic EVM wallet account to bridge.\n * @param [client] - The Dynamic client instance. Only required when using multiple Dynamic clients.\n * @returns A wagmi `CreateConnectorFn` to pass to `connect(config, { connector })`.\n * @throws {@link NotEvmWalletAccountError} when the account does not resolve to an EVM wallet provider.\n * @throws `SwitchChainNotSupportedError` when a network switch is requested and the wallet provider cannot switch networks.\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link NotEvmWalletAccountError}\n * @notInstrumented\n */\nexport const createDynamicWagmiConnector = (\n { walletAccount }: CreateDynamicWagmiConnectorParams,\n client = getDefaultClient()\n): CreateConnectorFn<EvmWalletProvider> =>\n createConnector((config) => {\n const walletProvider = getWalletProviderFromWalletAccount(\n { walletAccount },\n client\n );\n\n if (!isEvmWalletProvider(walletProvider)) {\n throw new NotEvmWalletAccountError(walletAccount.address);\n }\n\n const address = getAddress(walletAccount.address as Hex);\n\n const getChainId = async (): Promise<number> => {\n const { networkId } = await walletProvider.getActiveNetworkId();\n return Number(networkId);\n };\n\n // Retained so provider event subscriptions can be torn down on disconnect.\n let detachProviderEvents: (() => void) | undefined;\n\n const detachProviderEventsIfAttached = (): void => {\n detachProviderEvents?.();\n detachProviderEvents = undefined;\n };\n\n const emitDisconnect = (): void => {\n config.emitter.emit('disconnect');\n detachProviderEventsIfAttached();\n };\n\n const emitConnectedAddresses = ({\n addresses,\n }: {\n addresses: string[];\n }): void => {\n // The connector is bound to a single account and only ever signs with it,\n // so mirror that account's presence rather than whatever the underlying\n // wallet now reports; otherwise wagmi would surface an address whose\n // transactions this connection cannot actually sign.\n const isBoundAccountConnected = addresses.some(\n (candidate) => getAddress(candidate as Hex) === address\n );\n\n if (!isBoundAccountConnected) {\n emitDisconnect();\n return;\n }\n\n config.emitter.emit('change', { accounts: [address] });\n };\n\n const emitChainId = ({ chainId }: { chainId: number }): void => {\n config.emitter.emit('change', { chainId });\n };\n\n const switchToChain = async ({\n chainId,\n }: {\n chainId: number;\n }): Promise<Chain> => {\n const chain = config.chains.find((current) => current.id === chainId);\n\n if (!chain) {\n throw new ChainNotConfiguredError();\n }\n\n // `switchActiveNetwork` is optional on the provider. Emitting `change`\n // when it is absent would tell wagmi the switch succeeded while the\n // wallet stayed on its old network, so surface it as unsupported.\n if (!walletProvider.switchActiveNetwork) {\n // The error only reads the connector's `name`, but its type is the\n // fully-resolved wagmi `Connector` (id/type narrowed, emitter and\n // storage attached), which only exists once wagmi has set the connector\n // up — hence the cast around the one field it touches.\n throw new SwitchChainNotSupportedError({\n connector: { name: DYNAMIC_CONNECTOR_NAME } as never,\n });\n }\n\n await walletProvider.switchActiveNetwork({\n networkId: String(chainId),\n });\n\n emitChainId({ chainId });\n\n return chain;\n };\n\n // wagmi lets callers request a chain at connect time (`connect(config, {\n // connector, chainId })`) and expects the connector to move the wallet\n // there, so honour it through the same switch path as `switchChain` instead\n // of silently reporting whichever network the wallet happens to be on.\n const resolveChainIdForConnection = async ({\n requestedChainId,\n }: {\n requestedChainId: number | undefined;\n }): Promise<number> => {\n const activeChainId = await getChainId();\n\n const isSwitchNeeded =\n requestedChainId !== undefined && requestedChainId !== activeChainId;\n\n if (!isSwitchNeeded) {\n return activeChainId;\n }\n\n const chain = await switchToChain({ chainId: requestedChainId });\n\n return chain.id;\n };\n\n // Forward Dynamic wallet-provider events into wagmi. The listeners are the\n // same functions the connector's own `on*` handlers delegate to, so a\n // provider event and a wagmi-driven event take exactly one code path — and\n // none of them depend on the connector object existing yet.\n const attachProviderEvents = (): void => {\n const { events } = walletProvider;\n\n if (detachProviderEvents || !events) {\n return;\n }\n\n // Only the network payload needs translating; the other two already match\n // the shape the emit helpers take.\n const handleNetworkChanged = ({\n networkId,\n }: {\n networkId: string;\n }): void => emitChainId({ chainId: Number(networkId) });\n\n events.on('accountsChanged', emitConnectedAddresses);\n events.on('networkChanged', handleNetworkChanged);\n events.on('disconnected', emitDisconnect);\n\n detachProviderEvents = () => {\n events.off('accountsChanged', emitConnectedAddresses);\n events.off('networkChanged', handleNetworkChanged);\n events.off('disconnected', emitDisconnect);\n };\n };\n\n return {\n connect: async (parameters?: {\n chainId?: number;\n isReconnecting?: boolean;\n withCapabilities?: boolean;\n }) => {\n // Resolved before subscribing because it can reject (unconfigured or\n // unswitchable chain), and a failed attempt must not leave listeners\n // behind on the wallet.\n const chainId = await resolveChainIdForConnection({\n requestedChainId: parameters?.chainId,\n });\n\n attachProviderEvents();\n\n // wagmi v3 can ask connect() for per-account ERC-7846 connect\n // capabilities (Sign-In With Ethereum, spend permissions, ...), which\n // a wallet only reports through a `wallet_connect` handshake. Dynamic\n // connects the account itself, so there is nothing to report — wagmi's\n // own injected connector returns an empty map here for the same reason.\n // This says nothing about EIP-5792 execution capabilities (atomic\n // batching, paymaster service): those are answered by\n // `wallet_getCapabilities` on the provider, which external wallets pass\n // straight through while embedded wallets expose no `request` method at\n // all. Advertising Dynamic's own batching / sponsorship there is a\n // follow-up for if the need arises.\n const accounts = parameters?.withCapabilities\n ? [{ address, capabilities: {} }]\n : [address];\n\n // wagmi types `accounts` as conditional on the `withCapabilities`\n // generic, which it only infers from a literal argument — a value\n // branched at runtime satisfies neither side of the conditional, so the\n // cast is unavoidable. wagmi's own injected and mock connectors cast to\n // `never` here for exactly this reason.\n return {\n accounts: accounts as never,\n chainId,\n };\n },\n\n disconnect: async () => detachProviderEventsIfAttached(),\n\n getAccounts: async () => [address] as readonly Address[],\n\n getChainId,\n\n // Delegating to the SDK keeps custom wallet clients (e.g. smart accounts)\n // working instead of hand-rolling a `custom(provider)` transport. Dynamic\n // is the source of truth for the active network, so the requested\n // `chainId` is not used to re-scope the client here.\n getClient: async (): Promise<Client> => {\n const walletClient = await createWalletClientForWalletAccount(\n { walletAccount },\n client\n );\n\n // The SDK and wagmi can resolve different viem versions in the\n // monorepo; their structurally-identical client types are otherwise\n // nominally incompatible, so we bridge them here.\n return walletClient as unknown as Client;\n },\n\n // A required wagmi connector method: wagmi keeps the provider type opaque\n // through the `provider` generic of `CreateConnectorFn`, which this\n // connector fixes to `EvmWalletProvider`. Consumers reaching for the\n // underlying provider (`connector.getProvider()`) therefore get Dynamic's\n // typed wallet provider instead of an unknown.\n getProvider: async () => walletProvider,\n\n // wagmi requires a stable, unique connector id. The wallet account id is\n // already the SDK's canonical identifier for the account, so reuse it\n // rather than re-deriving the id contract here.\n id: `dynamic-${walletAccount.id}`,\n\n isAuthorized: async () => {\n const { addresses } = await walletProvider.getConnectedAddresses();\n return addresses.some(\n (connected) => getAddress(connected as Hex) === address\n );\n },\n\n name: DYNAMIC_CONNECTOR_NAME,\n\n onAccountsChanged: (addresses: string[]) =>\n emitConnectedAddresses({ addresses }),\n\n onChainChanged: (chainId: string) =>\n emitChainId({ chainId: Number(chainId) }),\n\n onDisconnect: emitDisconnect,\n\n switchChain: switchToChain,\n\n type: DYNAMIC_CONNECTOR_TYPE,\n };\n });\n","import {\n getDefaultClient,\n getSelectedWalletAccount,\n onEvent,\n} from '@dynamic-labs-sdk/client';\nimport { getCore } from '@dynamic-labs-sdk/client/core';\nimport { isEvmWalletAccount } from '@dynamic-labs-sdk/evm';\nimport type { Config, Connector } from '@wagmi/core';\nimport { connect, disconnect } from '@wagmi/core';\n\nimport { createDynamicWagmiConnector } from '../createDynamicWagmiConnector';\n\n/**\n * Parameters for {@link syncDynamicWagmi}.\n *\n * @example\n * ```ts\n * const params: SyncDynamicWagmiParams = { config };\n * ```\n * @see {@link syncDynamicWagmi}\n * @see {@link useSyncDynamicWagmi}\n */\nexport type SyncDynamicWagmiParams = {\n /**\n * The wagmi config to keep in sync with Dynamic's selected EVM wallet account.\n */\n config: Config;\n};\n\n/**\n * Keeps a wagmi `Config` in sync with Dynamic's selected EVM wallet account.\n *\n * This is the vanilla-JS counterpart to the `useSyncDynamicWagmi` React hook: it\n * subscribes to Dynamic's wallet events and, whenever the selected EVM account\n * changes (login, wallet switch, logout), rebuilds a Dynamic wagmi connector and\n * drives wagmi's `connect` / `disconnect` so `useAccount` and the rest of the\n * wagmi hooks/actions mirror Dynamic. Dynamic stays the source of truth; wagmi is\n * a read-only mirror.\n *\n * Unlike `createDynamicWagmiConnector` — which bridges a single account you pass\n * in and never switches on its own — this reacts to Dynamic's selection, so\n * calling `setSelectedWalletAccount` is enough to move wagmi. Call the returned\n * function to stop syncing and tear down the mirrored connection.\n *\n * Only the connection this sync created is ever disconnected, so wallets the\n * consumer connects to wagmi themselves keep working alongside Dynamic's.\n *\n * @example\n * ```ts\n * const stopSync = syncDynamicWagmi({ config });\n * // Later, wagmi follows Dynamic's selection automatically:\n * await setSelectedWalletAccount({ walletAccount: nextWalletAccount });\n * // When you're done:\n * stopSync();\n * ```\n *\n * @param params.config - The wagmi config to synchronize.\n * @param [client] - The Dynamic client instance. Only required when using\n * multiple Dynamic clients.\n * @returns A function that stops the sync, unsubscribes from Dynamic events, and\n * disconnects the mirrored wagmi connection.\n * @see {@link createDynamicWagmiConnector}\n * @see {@link useSyncDynamicWagmi}\n * @see {@link SyncDynamicWagmi}\n * @notInstrumented\n */\nexport const syncDynamicWagmi = (\n { config }: SyncDynamicWagmiParams,\n client = getDefaultClient()\n): (() => void) => {\n // The id of the wallet account currently mirrored into wagmi, so repeated\n // events for the same account don't trigger redundant reconnects.\n let syncedWalletAccountId: string | null | undefined;\n\n // The connector instance backing the mirrored connection, kept so teardown\n // can target it explicitly. wagmi supports several concurrent connections and\n // `disconnect(config)` drops whichever one is currently active — which may\n // well be a wallet the consumer connected to wagmi themselves — so the sync\n // must never disconnect without naming its own connector.\n let mirroredConnector: Connector | undefined;\n\n // The disconnect currently in flight, so an overlapping caller (a sync run\n // switching accounts and the teardown, say) waits on it instead of asking\n // wagmi to disconnect the same connector twice.\n let pendingDisconnect: Promise<void> | undefined;\n\n const disconnectMirroredConnection = async (): Promise<void> => {\n if (pendingDisconnect) {\n await pendingDisconnect;\n return;\n }\n\n if (!mirroredConnector) {\n return;\n }\n\n const connectorToDisconnect = mirroredConnector;\n pendingDisconnect = disconnect(config, {\n connector: connectorToDisconnect,\n });\n\n try {\n await pendingDisconnect;\n\n // Dropped only once wagmi confirmed the disconnect, so a failed attempt\n // keeps the reference a later switch or teardown needs to retry with.\n mirroredConnector = undefined;\n } finally {\n pendingDisconnect = undefined;\n }\n };\n\n // Guards against overlapping runs: concurrent `sync()` calls would interleave\n // their connect/disconnect steps and corrupt the mirrored-account bookkeeping.\n let isSyncing = false;\n let resyncRequested = false;\n\n // Set once the sync is stopped so an in-flight `sync()` started before\n // teardown can bail out instead of racing the teardown's disconnect and\n // re-establishing a connection that outlives the subscription.\n let isCancelled = false;\n\n const syncOnce = async (): Promise<void> => {\n const selectedWallet = getSelectedWalletAccount(client);\n\n const evmWalletAccount =\n selectedWallet && isEvmWalletAccount(selectedWallet)\n ? selectedWallet\n : null;\n\n const nextWalletAccountId = evmWalletAccount?.id ?? null;\n\n if (nextWalletAccountId === syncedWalletAccountId) {\n return;\n }\n\n try {\n // Replace any previously mirrored connection first — wagmi's `connect`\n // adds to its connection registry without removing others, so without\n // this a switched-away wallet lingers and can reappear after logout.\n await disconnectMirroredConnection();\n\n if (!evmWalletAccount) {\n syncedWalletAccountId = nextWalletAccountId;\n return;\n }\n\n // The sync was stopped while this run was awaiting; teardown has already\n // disconnected, so skip connecting to avoid leaking a connection that\n // outlives the subscription.\n if (isCancelled) {\n return;\n }\n\n // Registering the connector up front (the same call `connect` makes for\n // a connector factory) yields the instance wagmi will store, which is\n // what later disconnects have to name.\n const connector = config._internal.connectors.setup(\n createDynamicWagmiConnector({ walletAccount: evmWalletAccount }, client)\n );\n\n await connect(config, { connector });\n\n mirroredConnector = connector;\n syncedWalletAccountId = nextWalletAccountId;\n } catch (error) {\n // Left `undefined` — \"nothing mirrored yet\" — rather than the account\n // this run failed on or the one it failed to leave: both compare equal to\n // a value a later event can legitimately report, which would make the\n // equality guard swallow the retry (a failed logout disconnect would keep\n // wagmi on the logged-out wallet forever).\n syncedWalletAccountId = undefined;\n getCore(client).logger.error(\n 'Failed to sync Dynamic wallet account with wagmi',\n error\n );\n }\n };\n\n const sync = async (): Promise<void> => {\n // Serialize runs: if one is in flight, flag a re-run so the latest selected\n // account is picked up once it finishes, rather than racing it.\n if (isSyncing) {\n resyncRequested = true;\n return;\n }\n isSyncing = true;\n\n try {\n // Draining the queued re-runs in a loop — rather than kicking off a\n // fire-and-forget follow-up run — keeps them inside this promise, so\n // awaiting `sync()` guarantees wagmi caught up with Dynamic's latest\n // selection.\n do {\n resyncRequested = false;\n await syncOnce();\n } while (resyncRequested);\n } finally {\n isSyncing = false;\n }\n };\n\n void sync();\n\n const unsubscribeFromWalletAccounts = onEvent(\n { event: 'walletAccountsChanged', listener: () => void sync() },\n client\n );\n\n const unsubscribeFromUser = onEvent(\n { event: 'userChanged', listener: () => void sync() },\n client\n );\n\n return () => {\n isCancelled = true;\n\n unsubscribeFromWalletAccounts();\n unsubscribeFromUser();\n\n // Tear down the mirrored connection so a stopped sync doesn't leave wagmi\n // connected to an account it's no longer tracking. wagmi rejects when the\n // connection is already gone (e.g. the wallet disconnected itself), which is\n // nothing to act on during teardown, so log instead of leaving an unhandled\n // rejection behind.\n void disconnectMirroredConnection().catch((error: unknown) => {\n getCore(client).logger.error(\n 'Failed to disconnect Dynamic wallet account from wagmi',\n error\n );\n });\n };\n};\n"],"mappings":"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"}