@rango-dev/wallets-react 0.34.1-next.2 → 0.35.1-next.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.
- package/CHANGELOG.md +4 -0
- package/dist/helpers/index.js +1 -1
- package/dist/helpers/index.js.map +1 -1
- package/dist/hub/types.d.ts +2 -2
- package/dist/hub/types.d.ts.map +1 -1
- package/dist/hub/useHubAdapter.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +3 -3
- package/dist/legacy/types.d.ts +3 -2
- package/dist/legacy/types.d.ts.map +1 -1
- package/dist/wallets-react.build.json +1 -1
- package/package.json +3 -3
- package/src/hub/types.ts +2 -2
- package/src/hub/useHubAdapter.ts +14 -10
- package/src/hub/utils.ts +1 -1
- package/src/legacy/types.ts +7 -2
package/CHANGELOG.md
CHANGED
package/dist/helpers/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var h=Object.defineProperty;var o=(
|
|
1
|
+
var h=Object.defineProperty;var o=(u,e)=>h(u,"name",{value:e,configurable:!0});import{LegacyEvents as $e}from"@rango-dev/wallets-core/legacy";import"@rango-dev/wallets-core/utils";import{pickVersion as E}from"@rango-dev/wallets-core/utils";import{convertEvmBlockchainMetaToEvmChainInfo as Qe}from"@rango-dev/wallets-shared";import{isEvmBlockchain as Ke}from"rango-types";var s="last-connected-wallets",a="hub-v1-last-connected-wallets";import{createContext as v}from"react";var c="Context hasn't been initialized yet.",y={async connect(){throw new Error(c)},async disconnect(){throw new Error(c)},async disconnectAll(){throw new Error(c)},async suggestAndConnect(){throw new Error(c)},state(){throw new Error(c)},canSwitchNetworkTo(){throw new Error(c)},providers(){throw new Error(c)},getWalletInfo(){throw new Error(c)},getSigners(){throw new Error(c)}},f=v(y);import{useEffect as we,useReducer as he}from"react";import{Persistor as l}from"@rango-dev/wallets-core/legacy";var i=class{static{o(this,"LastConnectedWalletsFromStorage")}#e;constructor(e){this.#e=e}addWallet(e,t){if(this.#e===a)return this.#t(e,t);if(this.#e===s)return this.#a(e);throw new Error("Not implemented")}removeWallets(e){if(this.#e===a)return this.#r(e);if(this.#e===s)return this.#c(e);throw new Error("Not implemented")}list(){if(this.#e===a)return this.#n();if(this.#e===s)return this.#o();throw new Error("Not implemented")}removeNamespacesFromWallet(e,t){if(this.#e===a)return this.#s(e,t);throw new Error("Not implemented")}#o(){let t=new l().getItem(s)||[],r={};return t.forEach(n=>{r[n]=[]}),r}#n(){return new l().getItem(a)||{}}#t(e,t){let r=new l,n=r.getItem(this.#e)||{},p=t;if(n[e]){let d=n[e];p=d.concat(t.filter(m=>!d.some(w=>w.namespace===m.namespace)))}r.setItem(this.#e,{...n,[e]:p})}#a(e){let t=new l,r=t.getItem(this.#e)||[];t.setItem(s,r.concat(e))}#r(e){let t=new l,r=t.getItem(this.#e)||{};if(!e){t.setItem(this.#e,{});return}e.forEach(n=>{r[n]&&delete r[n]}),t.setItem(this.#e,r)}#s(e,t){let d=(new l().getItem(this.#e)||{})[e]?.filter(m=>!t.includes(m.namespace));this.#r([e]),d?.length>0&&this.#t(e,d)}#c(e){let t=new l,r=t.getItem(this.#e)||[];if(!e){t.setItem(this.#e,[]);return}t.setItem(s,r.filter(n=>!e.includes(n)))}};import{Persistor as F}from"@rango-dev/wallets-core/legacy";import{LegacyWallet as U}from"@rango-dev/wallets-core/legacy";import{useContext as q,useRef as V}from"react";import{useEffect as Z,useRef as ee}from"react";import{legacyFormatAddressWithNetwork as Te}from"@rango-dev/wallets-core/legacy";import{CAIP_BITCOIN_CHAIN_ID as be}from"@rango-dev/wallets-core/namespaces/utxo";import{CAIP as Re}from"@rango-dev/wallets-core/utils";import{Err as Fe,Ok as Be}from"ts-results";var Ze=new i(a);function g(u){let e="0.0.0",t=[];return u.forEach(r=>{let n=E(r,e);t.push(n[1])}),t}o(g,"getAllLegacyProviders");import{utils as Ht}from"@rango-dev/wallets-core/namespaces/evm";import"@rango-dev/wallets-shared";import{useEffect as Ft,useRef as Bt,useState as Ot}from"react";import{Ok as Yt,Result as jt}from"ts-results";import{legacyIsEvmNamespace as at}from"@rango-dev/wallets-core/legacy";import{Result as ct}from"ts-results";var pt=new i(a);import{createStore as ht,Hub as vt}from"@rango-dev/wallets-core";import{useRef as Ct}from"react";export{g as getAllLegacyProviders};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/hub/utils.ts", "../../src/hub/constants.ts", "../../src/legacy/context.ts", "../../src/legacy/useLegacyProviders.ts", "../../src/hub/lastConnectedWallets.ts", "../../src/legacy/helpers.ts", "../../src/legacy/hooks.ts", "../../src/legacy/useAutoConnect.ts", "../../src/hub/helpers.ts", "../../src/hub/useHubAdapter.ts", "../../src/hub/autoConnect.ts", "../../src/hub/useHubRefs.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AllProxiedNamespaces } from './types.js';\nimport type { Hub, Provider } from '@rango-dev/wallets-core';\nimport type {\n LegacyNamespaceInputForConnect,\n LegacyProviderInterface,\n LegacyEventHandler as WalletEventHandler,\n} from '@rango-dev/wallets-core/legacy';\nimport type { Event } from '@rango-dev/wallets-core/store';\n\nimport { LegacyEvents as Events } from '@rango-dev/wallets-core/legacy';\nimport { type VersionedProviders } from '@rango-dev/wallets-core/utils';\nimport { pickVersion } from '@rango-dev/wallets-core/utils';\nimport {\n type AddEthereumChainParameter,\n convertEvmBlockchainMetaToEvmChainInfo,\n} from '@rango-dev/wallets-shared';\nimport { type BlockchainMeta, isEvmBlockchain } from 'rango-types';\n\nimport {\n type ConnectResult,\n HUB_LAST_CONNECTED_WALLETS,\n type ProviderProps,\n} from '../legacy/mod.js';\n\nimport {\n fromAccountIdToLegacyAddressFormat,\n isConnectResultEvm,\n isConnectResultSolana,\n} from './helpers.js';\nimport { LastConnectedWalletsFromStorage } from './lastConnectedWallets.js';\n\n/* Gets a list of hub and legacy providers and returns a tuple which separates them. */\nexport function separateLegacyAndHubProviders(\n providers: VersionedProviders[]\n): [LegacyProviderInterface[], Provider[]] {\n const LEGACY_VERSION = '0.0.0';\n const HUB_VERSION = '1.0.0';\n\n const legacyProviders: LegacyProviderInterface[] = [];\n const hubProviders: Provider[] = [];\n\n providers.forEach((provider) => {\n try {\n const target = pickVersion(provider, HUB_VERSION);\n hubProviders.push(target[1]);\n } catch {\n const target = pickVersion(provider, LEGACY_VERSION);\n legacyProviders.push(target[1]);\n }\n });\n\n return [legacyProviders, hubProviders];\n}\n\nexport function findProviderByType(\n providers: Provider[],\n type: string\n): Provider | undefined {\n return providers.find((provider) => provider.id === type);\n}\n\n/**\n * We will call this function on hub's `subscribe`.\n * it will check states and will emit legacy events for backward compatibility.\n */\n\nconst lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n HUB_LAST_CONNECTED_WALLETS\n);\n\nexport function getSupportedChainsFromProvider(\n provider: Provider,\n allBlockChains: ProviderProps['allBlockChains']\n) {\n const namespacesProperty = provider\n .info()\n ?.properties?.find((property) => property.name === 'namespaces');\n\n const supportedChains =\n namespacesProperty?.value.data.flatMap((namespace) =>\n namespace.getSupportedChains(allBlockChains || [])\n ) || [];\n\n return supportedChains;\n}\n\nexport function mapHubEventsToLegacy(\n hub: Hub,\n event: Event,\n onUpdateState: WalletEventHandler,\n allBlockChains: ProviderProps['allBlockChains']\n): void {\n const provider = hub.get(event.provider);\n if (!provider) {\n throw new Error(\n \"Currently all the events have assigned to a provider. The event doesn't include one.\",\n {\n cause: event,\n }\n );\n }\n\n // @ts-expect-error for those events that doesn't have namespace, it will be undefinded\n const namespaceId: string | undefined = event.namespace;\n\n const namespace = namespaceId\n ? provider.findByNamespace(namespaceId)\n : undefined;\n let accounts: string[] | null = null;\n let network: string | null = null;\n\n if (namespace) {\n const [getNamespaceState] = namespace.state();\n accounts = getNamespaceState().accounts;\n network = getNamespaceState().network;\n }\n\n const [getProviderState] = provider.state();\n const coreState = {\n connected: getProviderState().connected,\n connecting: getProviderState().connecting,\n installed: getProviderState().installed,\n accounts,\n network,\n reachable: true,\n };\n\n const eventInfo = {\n supportedBlockchains: getSupportedChainsFromProvider(\n provider,\n allBlockChains\n ),\n isContractWallet: false,\n isHub: true,\n namespace: namespaceId,\n };\n\n switch (event.type) {\n case 'provider_detected':\n onUpdateState(\n event.provider,\n Events.INSTALLED,\n true,\n coreState,\n eventInfo\n );\n break;\n case 'provider_connecting':\n onUpdateState(\n event.provider,\n Events.CONNECTING,\n event.value,\n coreState,\n eventInfo\n );\n break;\n case 'provider_connected':\n onUpdateState(\n event.provider,\n Events.CONNECTED,\n true,\n coreState,\n eventInfo\n );\n break;\n case 'provider_disconnected':\n onUpdateState(\n event.provider,\n Events.PROVIDER_DISCONNECTED,\n event.provider,\n coreState,\n eventInfo\n );\n onUpdateState(\n event.provider,\n Events.CONNECTED,\n false,\n coreState,\n eventInfo\n );\n onUpdateState(\n event.provider,\n Events.ACCOUNTS,\n null,\n coreState,\n eventInfo\n );\n break;\n case 'namespace_disconnected':\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n event.provider,\n [event.namespace]\n );\n\n onUpdateState(\n event.provider,\n Events.NAMESPACE_DISCONNECTED,\n event.namespace,\n coreState,\n {\n ...eventInfo,\n namespace: event.namespace,\n }\n );\n // onUpdateState(event.provider, Events.ACCOUNTS, null, coreState, eventInfo);\n break;\n case 'namespace_connected':\n case 'namespace_account_switched':\n {\n if (event.type === 'namespace_account_switched') {\n onUpdateState(\n event.provider,\n Events.NAMESPACE_DISCONNECTED,\n event.namespace,\n coreState,\n eventInfo\n );\n }\n\n const formattedAddresses = event.accounts.map(\n fromAccountIdToLegacyAddressFormat\n );\n onUpdateState(\n event.provider,\n Events.ACCOUNTS,\n formattedAddresses,\n coreState,\n {\n ...eventInfo,\n namespace: event.namespace,\n }\n );\n }\n break;\n case 'namespace_network_switched':\n onUpdateState(event.provider, Events.NETWORK, event.network, coreState, {\n ...eventInfo,\n namespace: event.namespace,\n });\n break;\n }\n}\n\nexport function getAllLegacyProviders(\n allProviders: VersionedProviders[]\n): LegacyProviderInterface[] {\n const LEGACY_VERSION = '0.0.0';\n\n const legacyProviders: LegacyProviderInterface[] = [];\n\n allProviders.forEach((provider) => {\n const target = pickVersion(provider, LEGACY_VERSION);\n legacyProviders.push(target[1]);\n });\n\n return legacyProviders;\n}\n\nexport function getLegacyProvider(\n allProviders: VersionedProviders[],\n type: string\n): LegacyProviderInterface {\n const legacyProviders: LegacyProviderInterface[] =\n getAllLegacyProviders(allProviders);\n\n const provider = legacyProviders.find((legacyProvider) => {\n return legacyProvider.config.type === type;\n });\n\n if (!provider) {\n console.warn(\n `You have a provider that doesn't have legacy provider. It causes some problems since we need some legacy functionality. Provider Id: ${type}`\n );\n throw new Error(\n `You need to have legacy implementation to use some methods. Provider Id: ${type}`\n );\n }\n\n return provider;\n}\n\n/**\n * In legacy mode, for those who have switch network functionality (like evm), we are using an enum for network names\n * this enum only has meaning for us, and when we are going to connect an instance (e.g. window.ethereum) we should pass chain id.\n */\nexport function convertNamespaceNetworkToEvmChainId(\n namespace: LegacyNamespaceInputForConnect,\n meta: BlockchainMeta[]\n) {\n if (!namespace.network) {\n return undefined;\n }\n\n const evmBlockchainsList = meta.filter(isEvmBlockchain);\n const evmChains = convertEvmBlockchainMetaToEvmChainInfo(evmBlockchainsList);\n\n return evmChains[namespace.network];\n}\n\n/**\n * We are passing an string for chain id (e.g. ETH, POLYGON), but wallet's instances (e.g. window.ethereum) needs chainId (e.g. 0x1).\n * This function will help us to map these strings to proper hex ids.\n *\n * If you need same functionality for other blockchain types (e.g. Cosmos), You can make a separate function and add it here.\n */\nexport function tryConvertNamespaceNetworkToChainInfo(\n namespace: LegacyNamespaceInputForConnect,\n meta: BlockchainMeta[]\n): string | AddEthereumChainParameter | undefined {\n // `undefined` means it's not evm or we couldn't find it in meta.\n const evmChain = convertNamespaceNetworkToEvmChainId(namespace, meta);\n const network = evmChain || namespace.network;\n\n return network;\n}\n\nexport function transformHubResultToLegacyResult(\n res: Awaited<ReturnType<AllProxiedNamespaces['connect']>>\n): ConnectResult {\n if (isConnectResultEvm(res)) {\n return {\n accounts: res.accounts,\n network: res.network,\n provider: undefined,\n };\n } else if (isConnectResultSolana(res)) {\n return {\n accounts: res,\n network: null,\n provider: undefined,\n };\n }\n\n return {\n accounts: [res],\n network: null,\n provider: undefined,\n };\n}\n\n/**\n * Synchronizes providers in the hub with the configuration providers.\n * - Registers and initializes any configuration providers not yet in the hub\n * - Removes providers from the hub that aren't in the configuration\n */\nexport function synchronizeHubWithConfigProviders(\n hub: Hub,\n configurationProviders: Provider[]\n) {\n const registeredProviders = hub.getAll();\n\n // Register and initialize providers that exist in config but not in hub\n const providersToRegister = configurationProviders.filter(\n (configProvider) => !registeredProviders.get(configProvider.id)\n );\n\n providersToRegister.forEach((providerToRegister) => {\n hub.add(providerToRegister.id, providerToRegister);\n providerToRegister.init();\n });\n\n // Remove providers that exist in hub but not in config\n registeredProviders.forEach((registeredProvider) => {\n const isProviderInConfig = configurationProviders.some(\n (configProvider) => configProvider.id === registeredProvider.id\n );\n\n if (!isProviderInConfig) {\n hub.remove(registeredProvider.id);\n }\n });\n}\n", "export const LEGACY_LAST_CONNECTED_WALLETS = 'last-connected-wallets';\nexport const HUB_LAST_CONNECTED_WALLETS = 'hub-v1-last-connected-wallets';\n", "import type { ProviderContext } from './types.js';\n\nimport { createContext } from 'react';\n\nconst defaultErrorMessage = \"Context hasn't been initialized yet.\";\nconst defaultContext: ProviderContext = {\n async connect() {\n throw new Error(defaultErrorMessage);\n },\n async disconnect() {\n throw new Error(defaultErrorMessage);\n },\n async disconnectAll() {\n throw new Error(defaultErrorMessage);\n },\n async suggestAndConnect() {\n throw new Error(defaultErrorMessage);\n },\n state() {\n throw new Error(defaultErrorMessage);\n },\n canSwitchNetworkTo() {\n throw new Error(defaultErrorMessage);\n },\n providers() {\n throw new Error(defaultErrorMessage);\n },\n getWalletInfo() {\n throw new Error(defaultErrorMessage);\n },\n getSigners() {\n throw new Error(defaultErrorMessage);\n },\n};\n\nexport const WalletContext = createContext<ProviderContext>(defaultContext);\n", "import type { ProviderContext, ProviderProps } from './types.js';\nimport type { LegacyProviderInterface } from '@rango-dev/wallets-core/legacy';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { useEffect, useReducer } from 'react';\n\nimport { autoConnect } from './autoConnect.js';\nimport {\n availableWallets,\n checkWalletProviders,\n clearPersistance,\n connectedWallets,\n defaultWalletState,\n makeEventHandler,\n stateReducer,\n tryPersistWallet,\n tryRemoveWalletFromPersistance,\n} from './helpers.js';\nimport { useInitializers } from './hooks.js';\nimport { useAutoConnect } from './useAutoConnect.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ProviderType = any;\n\nexport type LegacyProviderProps = Omit<ProviderProps, 'providers'> & {\n providers: LegacyProviderInterface[];\n};\n\nexport function useLegacyProviders(\n props: LegacyProviderProps\n): ProviderContext {\n const [providersState, dispatch] = useReducer(stateReducer, {});\n\n // Get (or add) wallet instance (`provider`s will be wrapped in a `Wallet`)\n const getWalletInstance = useInitializers(\n makeEventHandler(dispatch, props.onUpdateState)\n );\n\n // Getting providers from props and put all of them in a `Map` with an appropriate interface.\n const listOfProviders = props.providers;\n const wallets = checkWalletProviders(listOfProviders);\n\n useAutoConnect({\n allBlockChains: props.allBlockChains,\n autoConnect: props.autoConnect,\n autoConnectHandler: async () => autoConnect(wallets, getWalletInstance),\n });\n\n // Final API we put in context and it will be available to use for users.\n const api: ProviderContext = {\n async connect(type, namespaces) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n // Legacy providers doesn't implemented multiple namespaces, so it will always be one value.\n let network = undefined;\n if (namespaces && namespaces.length > 0) {\n /*\n * This may not be safe in cases there are two `network` for namespaces, the first one will be picked always.\n * But since legacy provider only accepts one value, it shouldn't be happened when we are using legacy mode.\n */\n network = namespaces.find((ns) => !!ns.network)?.network;\n }\n\n const walletInstance = getWalletInstance(wallet);\n const result = await walletInstance.connect(network, namespaces);\n if (props.autoConnect) {\n void tryPersistWallet({\n type,\n walletActions: wallet.actions,\n getState: api.state,\n });\n }\n\n return [result];\n },\n async disconnect(type) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n const walletInstance = getWalletInstance(wallet);\n await walletInstance.disconnect();\n if (props.autoConnect) {\n tryRemoveWalletFromPersistance({ type, walletActions: wallet.actions });\n }\n },\n async disconnectAll() {\n const disconnect_promises: Promise<void>[] = [];\n\n /*\n * When a wallet is initializing, a record will be added to `providersState`\n * So we use them to know what wallet has been initialized then we need to\n * filter connected wallets only.\n */\n connectedWallets(providersState).forEach((type) => {\n const wallet = wallets.get(type);\n\n if (wallet) {\n const walletInstance = getWalletInstance(wallet);\n disconnect_promises.push(walletInstance.disconnect());\n }\n });\n\n if (props.autoConnect) {\n clearPersistance();\n }\n return await Promise.allSettled(disconnect_promises);\n },\n\n async suggestAndConnect(type, network) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n const walletInstance = getWalletInstance(wallet);\n const result = await walletInstance.suggestAndConnect(network);\n\n return result;\n },\n\n state(type) {\n return providersState[type] || defaultWalletState;\n },\n canSwitchNetworkTo(type, network) {\n const wallet = wallets.get(type);\n if (!wallet) {\n return false;\n }\n\n const walletInstance = getWalletInstance(wallet);\n return walletInstance.canSwitchNetworkTo\n ? walletInstance.canSwitchNetworkTo(network, walletInstance.provider)\n : false;\n },\n providers() {\n const providers: { [type in WalletType]?: ProviderType } = {};\n availableWallets(providersState).forEach((type) => {\n const wallet = wallets.get(type);\n if (wallet) {\n const walletInstance = getWalletInstance(wallet);\n providers[type] = walletInstance.provider;\n }\n });\n\n return providers;\n },\n getWalletInfo(type) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n /*\n * Get wallet info could be used in render methods to show wallets data\n * So, addWalletRef method shouldn't be called in this method\n */\n\n return wallet.actions.getWalletInfo(props.allBlockChains || []);\n },\n async getSigners(type) {\n const wallet = wallets.get(type);\n\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n const walletInstance = getWalletInstance(wallet);\n const provider = walletInstance.provider;\n const result = walletInstance.getSigners(provider);\n\n return result;\n },\n };\n\n // Initialize instances\n useEffect(() => {\n wallets.forEach((wallet) => {\n const walletInstance = getWalletInstance(wallet);\n const runOnInit = () => {\n if (walletInstance.onInit) {\n walletInstance.onInit();\n }\n };\n\n const initWhenPageIsReady = (event: Event) => {\n if (\n event.target &&\n (event.target as Document).readyState === 'complete'\n ) {\n runOnInit();\n\n document.removeEventListener('readystatechange', initWhenPageIsReady);\n }\n };\n\n // Try to run, maybe it's ready.\n runOnInit();\n\n /*\n * Try again when the page has been completely loaded.\n * Some of wallets, take some time to be fully injected and loaded.\n */\n document.addEventListener('readystatechange', initWhenPageIsReady);\n });\n }, []);\n\n // Setting supported blockchains on instances\n useEffect(() => {\n const allBlockChains = props.allBlockChains;\n if (allBlockChains) {\n wallets.forEach((wallet) => {\n const walletInstance = getWalletInstance(wallet);\n const walletInfo = walletInstance.getWalletInfo(\n props.allBlockChains || []\n );\n walletInstance.setInfo({\n supportedBlockchains: walletInfo.supportedChains,\n isContractWallet: !!walletInfo.isContractWallet,\n });\n });\n }\n }, [props.allBlockChains]);\n\n // Setting event handler on instances\n useEffect(() => {\n wallets.forEach((wallet) => {\n const walletInstance = getWalletInstance(wallet);\n walletInstance.setHandler(\n makeEventHandler(dispatch, props.onUpdateState)\n );\n });\n }, [props.onUpdateState]);\n\n return api;\n}\n", "import type { Namespace } from '@rango-dev/wallets-core/namespaces/common';\n\nimport { Persistor } from '@rango-dev/wallets-core/legacy';\n\nimport {\n HUB_LAST_CONNECTED_WALLETS,\n LEGACY_LAST_CONNECTED_WALLETS,\n} from './constants.js';\n\nexport interface NamespaceInput {\n namespace: Namespace;\n network: string | undefined;\n}\n\nexport interface LastConnectedWalletsStorage {\n [providerId: string]: NamespaceInput[];\n}\n\nexport type LegacyLastConnectedWalletsStorage = string[];\n\n/**\n * We are doing some certain actions on storage for `last-connected-wallets` key.\n * This class helps us to define them in one place and also it has support for both legacy and hub.\n */\nexport class LastConnectedWalletsFromStorage {\n #storageKey: string;\n\n constructor(storageKey: string) {\n this.#storageKey = storageKey;\n }\n\n addWallet(providerId: string, namespaces: NamespaceInput[]): void {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#addWalletToHub(providerId, namespaces);\n } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {\n return this.#addWalletToLegacy(providerId);\n }\n throw new Error('Not implemented');\n }\n removeWallets(providerIds?: string[]): void {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#removeWalletsFromHub(providerIds);\n } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {\n return this.#removeWalletsFromLegacy(providerIds);\n }\n throw new Error('Not implemented');\n }\n list(): LastConnectedWalletsStorage {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#listFromHub();\n } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {\n return this.#listFromLegacy();\n }\n throw new Error('Not implemented');\n }\n removeNamespacesFromWallet(providerId: string, namespaceIds: string[]) {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#removeNamespaceFromWalletHub(providerId, namespaceIds);\n }\n throw new Error('Not implemented');\n }\n\n #listFromLegacy(): LastConnectedWalletsStorage {\n const persistor = new Persistor<LegacyLastConnectedWalletsStorage>();\n const lastConnectedWallets =\n persistor.getItem(LEGACY_LAST_CONNECTED_WALLETS) || [];\n const output: LastConnectedWalletsStorage = {};\n lastConnectedWallets.forEach((provider) => {\n // Setting empty namespaces\n output[provider] = [];\n });\n return output;\n }\n #listFromHub(): LastConnectedWalletsStorage {\n const persistor = new Persistor<LastConnectedWalletsStorage>();\n const lastConnectedWallets =\n persistor.getItem(HUB_LAST_CONNECTED_WALLETS) || {};\n return lastConnectedWallets;\n }\n #addWalletToHub(providerId: string, namespaces: NamespaceInput[]): void {\n const storage = new Persistor<LastConnectedWalletsStorage>();\n const storageState = storage.getItem(this.#storageKey) || {};\n\n let toBeAddedNamespaces = namespaces;\n\n // If provider already exits in the storage, we should just add new namespaces to the previously added namespaces.\n if (!!storageState[providerId]) {\n const storedNamespaces = storageState[providerId];\n toBeAddedNamespaces = storedNamespaces.concat(\n namespaces.filter(\n (namespace) =>\n !storedNamespaces.some(\n (storedNamespace) =>\n storedNamespace.namespace === namespace.namespace\n )\n )\n );\n }\n\n storage.setItem(this.#storageKey, {\n ...storageState,\n [providerId]: toBeAddedNamespaces,\n });\n }\n #addWalletToLegacy(providerId: string): void {\n const storage = new Persistor<LegacyLastConnectedWalletsStorage>();\n const storageState = storage.getItem(this.#storageKey) || [];\n\n storage.setItem(\n LEGACY_LAST_CONNECTED_WALLETS,\n storageState.concat(providerId)\n );\n }\n #removeWalletsFromHub(providerIds?: string[]): void {\n const persistor = new Persistor<LastConnectedWalletsStorage>();\n const storageState = persistor.getItem(this.#storageKey) || {};\n\n // Remove all wallets\n if (!providerIds) {\n persistor.setItem(this.#storageKey, {});\n return;\n }\n\n // Remove some of the wallets\n providerIds.forEach((providerId) => {\n if (storageState[providerId]) {\n delete storageState[providerId];\n }\n });\n\n persistor.setItem(this.#storageKey, storageState);\n }\n #removeNamespaceFromWalletHub(\n providerId: string,\n namespaceIds: string[]\n ): void {\n const persistor = new Persistor<LastConnectedWalletsStorage>();\n const storageState = persistor.getItem(this.#storageKey) || {};\n\n const currentProviderNamespaces = storageState[providerId];\n const newProviderNamespaces = currentProviderNamespaces?.filter(\n (namespace) => !namespaceIds.includes(namespace.namespace)\n );\n\n this.#removeWalletsFromHub([providerId]);\n if (newProviderNamespaces?.length > 0) {\n this.#addWalletToHub(providerId, newProviderNamespaces);\n }\n }\n #removeWalletsFromLegacy(providerIds?: string[]): void {\n const persistor = new Persistor<LegacyLastConnectedWalletsStorage>();\n const storageState = persistor.getItem(this.#storageKey) || [];\n\n // Remove all wallets\n if (!providerIds) {\n persistor.setItem(this.#storageKey, []);\n return;\n }\n\n // Remove some of the wallets\n persistor.setItem(\n LEGACY_LAST_CONNECTED_WALLETS,\n storageState.filter((wallet) => !providerIds.includes(wallet))\n );\n }\n}\n", "import type {\n ProviderInterface,\n State,\n WalletActions,\n WalletProviders,\n} from './types.js';\nimport type {\n LegacyOptions as Options,\n LegacyEventHandler as WalletEventHandler,\n LegacyState as WalletState,\n} from '@rango-dev/wallets-core/legacy';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { Persistor } from '@rango-dev/wallets-core/legacy';\n\nimport { LEGACY_LAST_CONNECTED_WALLETS } from '../hub/constants.js';\nimport { LastConnectedWalletsFromStorage } from '../hub/lastConnectedWallets.js';\n\nexport function choose(wallets: any[], type: WalletType): any | null {\n return wallets.find((wallet) => wallet.type === type) || null;\n}\n\nexport const defaultWalletState: WalletState = {\n connected: false,\n connecting: false,\n reachable: false,\n installed: false,\n accounts: null,\n network: null,\n};\n\nexport function stateReducer(state: State, action: any) {\n if (action.type === 'new_state') {\n // TODO fix problem and remove ts-ignore\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const target_wallet = state[action.wallet];\n if (!target_wallet) {\n return {\n ...state,\n [action.wallet]: {\n ...defaultWalletState,\n [action.name]: action.value,\n },\n };\n }\n\n return {\n ...state,\n [action.wallet]: {\n ...target_wallet,\n [action.name]: action.value,\n },\n };\n }\n\n return state;\n}\n\nexport function connectedWallets(providersState: State): WalletType[] {\n return Object.entries(providersState)\n .filter(([, wallet_state]) => {\n return wallet_state?.connected;\n })\n .map(([type]) => {\n return type;\n });\n}\n\nexport function availableWallets(providersState: State): WalletType[] {\n return Object.entries(providersState).map(([type]) => {\n return type;\n });\n}\n\nexport function checkWalletProviders(\n list: ProviderInterface[]\n): WalletProviders {\n const wallets: WalletProviders = new Map();\n\n list.forEach((provider) => {\n const { config, ...actions } = provider;\n wallets.set(config.type, {\n actions,\n config,\n });\n });\n\n return wallets;\n}\n\n/* eslint-disable @typescript-eslint/ban-types */\nexport function isAsync(fn: Function) {\n return fn?.constructor?.name === 'AsyncFunction';\n}\n\nexport function needsCheckInstallation(options: Options) {\n const { checkInstallation = true } = options.config;\n return checkInstallation;\n}\n\nexport async function tryPersistWallet({\n type,\n walletActions,\n getState,\n}: {\n type: WalletType;\n walletActions: WalletActions;\n getState: (walletType: WalletType) => WalletState;\n}) {\n if (walletActions.canEagerConnect) {\n const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n LEGACY_LAST_CONNECTED_WALLETS\n );\n const lastConnectedWallets = lastConnectedWalletsFromStorage.list();\n const walletAlreadyPersisted = !!lastConnectedWallets[type];\n\n /*\n *If on the last attempt we are unable to eagerly connect to any wallet and the user connects any wallet manualy,\n *persistance will be outdated and will need to be removed.\n */\n if (walletAlreadyPersisted && !getState(type).connected) {\n clearPersistance();\n }\n\n if (!walletAlreadyPersisted) {\n lastConnectedWalletsFromStorage.addWallet(type, []);\n }\n }\n}\n\nexport function tryRemoveWalletFromPersistance({\n type,\n walletActions,\n}: {\n type: WalletType;\n walletActions: WalletActions;\n}) {\n if (walletActions.canEagerConnect) {\n const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n LEGACY_LAST_CONNECTED_WALLETS\n );\n lastConnectedWalletsFromStorage.removeWallets([type]);\n }\n}\n\nexport function clearPersistance() {\n const persistor = new Persistor<string[]>();\n const wallets = persistor.getItem(LEGACY_LAST_CONNECTED_WALLETS);\n if (wallets) {\n persistor.removeItem(LEGACY_LAST_CONNECTED_WALLETS);\n }\n}\n\n/*\n *Our event handler includes an internal state updater, and a notifier\n *for the outside listener.\n *On creating first wallet refrence, and on chaning `props.onUpdateState`\n *we are using this function.\n */\nexport function makeEventHandler(\n dispatcher: any,\n onUpdateState?: WalletEventHandler\n) {\n const handler: WalletEventHandler = (\n type,\n name,\n value,\n coreState,\n supportedChains\n ) => {\n const action = { type: 'new_state', wallet: type, name, value };\n // Update state\n dispatcher(action);\n\n // Giving the event to the outside listener\n if (onUpdateState) {\n onUpdateState(type, name, value, coreState, supportedChains);\n }\n };\n\n return handler;\n}\n", "import type { ProviderContext, WalletActions, WalletConfig } from './types.js';\nimport type { LegacyEventHandler as WalletEventHandler } from '@rango-dev/wallets-core/legacy';\n\nimport { LegacyWallet as Wallet } from '@rango-dev/wallets-core/legacy';\nimport { useContext, useRef } from 'react';\n\nimport { WalletContext } from './context.js';\n\nexport type GetWalletInstance = (wallet: {\n actions: WalletActions;\n config: WalletConfig;\n}) => Wallet;\n\nexport function useInitializers(\n onChangeState: WalletEventHandler\n): GetWalletInstance {\n const availableWallets = useRef<{\n [key: string]: Wallet | undefined;\n }>({});\n\n /*\n * If `wallet` hasn't been added to `availableWallets`,\n * Get a instance of `Wallet` and save the refrence in `availableWallets`.\n * Otherwise, return the already created instance.\n */\n function updater(wallet: {\n actions: WalletActions;\n config: WalletConfig;\n }): Wallet {\n const type = wallet.config.type;\n // We only update, if there is no instance available.\n if (typeof availableWallets.current[type] === 'undefined') {\n availableWallets.current[type] = new Wallet(\n {\n config: wallet.config,\n handler: onChangeState,\n },\n wallet.actions\n );\n }\n\n return availableWallets.current[type]!;\n }\n\n return updater;\n}\n\nexport function useWallets(): ProviderContext {\n const context = useContext(WalletContext);\n if (!context) {\n throw Error('useWallet can only be used within the Provider component');\n }\n return context;\n}\n", "import type { ProviderProps } from './types.js';\n\nimport { useEffect, useRef } from 'react';\n\nimport { shouldTryAutoConnect } from './utils.js';\n\nexport function useAutoConnect(\n props: Pick<ProviderProps, 'allBlockChains' | 'autoConnect'> & {\n /**\n * A function to run autoConnect on instances\n */\n autoConnectHandler: () => void;\n }\n) {\n const autoConnectInitiated = useRef(false);\n\n useEffect(() => {\n if (shouldTryAutoConnect(props) && !autoConnectInitiated.current) {\n autoConnectInitiated.current = true;\n props.autoConnectHandler();\n }\n }, [props.autoConnect, props.allBlockChains]);\n}\n", "import type { AllProxiedNamespaces } from './types.js';\nimport type {\n Accounts,\n AccountsWithActiveChain,\n} from '@rango-dev/wallets-core/namespaces/common';\nimport type { Result } from 'ts-results';\n\nimport { legacyFormatAddressWithNetwork as formatAddressWithNetwork } from '@rango-dev/wallets-core/legacy';\nimport { CAIP_BITCOIN_CHAIN_ID } from '@rango-dev/wallets-core/namespaces/utxo';\nimport { CAIP } from '@rango-dev/wallets-core/utils';\nimport { Err, Ok } from 'ts-results';\n\nexport function mapCaipNamespaceToLegacyNetworkName(\n chainId: CAIP.ChainIdParams | string\n): string {\n if (typeof chainId === 'string') {\n return chainId;\n }\n const useNamespaceAsNetworkFor = ['solana'];\n\n if (useNamespaceAsNetworkFor.includes(chainId.namespace.toLowerCase())) {\n return chainId.namespace.toUpperCase();\n }\n\n if (chainId.namespace.toLowerCase() === 'eip155') {\n return 'ETH';\n } else if (chainId.reference === CAIP_BITCOIN_CHAIN_ID) {\n return 'BTC';\n }\n\n if (chainId.namespace === 'sui') {\n return chainId.reference.toUpperCase();\n }\n\n return chainId.reference;\n}\n\n/**\n * CAIP's accountId has a format like this: eip155:1:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb\n * Legacy format is something like this: ETH:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb\n * This function will try to convert this two format.\n *\n * @see https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md\n */\nexport function fromAccountIdToLegacyAddressFormat(account: string): string {\n const { chainId, address } = CAIP.AccountId.parse(account);\n const network = mapCaipNamespaceToLegacyNetworkName(chainId);\n return formatAddressWithNetwork(address, network);\n}\n\n/**\n * Getting a list of (lazy) promises and run them one after another.\n */\n\nexport async function runSequentiallyWithoutFailure<R>(\n promises: Array<() => Promise<R>>\n): Promise<Result<R, unknown>[]> {\n return promises.reduce(async (prevPromise, task) => {\n const previousResults = await prevPromise;\n try {\n const taskResult = await task();\n return [...previousResults, new Ok(taskResult)];\n } catch (error) {\n return [...previousResults, new Err(error)];\n }\n }, Promise.resolve<Result<R, unknown>[]>([]));\n}\n\nexport function isConnectResultEvm(\n result: Awaited<ReturnType<AllProxiedNamespaces['connect']>>\n): result is AccountsWithActiveChain {\n return typeof result === 'object' && !Array.isArray(result);\n}\n\nexport function isConnectResultSolana(\n result: Awaited<ReturnType<AllProxiedNamespaces['connect']>>\n): result is Accounts {\n return Array.isArray(result);\n}\n\ntype QueueItem<T> = {\n task: () => Promise<T>;\n resolve: (value: Result<T, unknown>) => void;\n key: string;\n};\n/**\n * Creates a queue manager that ensures sequential execution of tasks by key.\n * When multiple tasks with the same key are queued, they are executed one at a time\n * in the order they were added. This prevents race conditions and ensures\n * predictable task execution order.\n *\n */\nexport function createQueue(options?: {\n onError?: (\n error: unknown,\n actions: {\n removeCurrentKeyFromQueue: () => void;\n }\n ) => void;\n}) {\n const processingKeys = new Set<string>();\n let queue: QueueItem<unknown>[] = [];\n\n const removeKeyFromQueue = (\n key: string,\n result: Result<unknown, unknown>\n ) => {\n queue = queue.filter((q) => {\n if (q.key !== key) {\n return true;\n }\n q.resolve(result);\n return false;\n });\n };\n\n const processQueue = async () => {\n const currentItem = queue.find((item) => !processingKeys.has(item.key));\n if (!currentItem) {\n return;\n }\n\n const { task, resolve, key } = currentItem;\n processingKeys.add(key);\n\n try {\n const result = await task();\n resolve(new Ok(result));\n } catch (error) {\n if (options?.onError) {\n options.onError(error, {\n removeCurrentKeyFromQueue: () =>\n removeKeyFromQueue(key, new Err(error)),\n });\n }\n\n resolve(new Err(error));\n } finally {\n const indexOfCurrentItem = queue.findIndex((item) => item.key === key);\n if (indexOfCurrentItem >= 0) {\n queue.splice(indexOfCurrentItem, 1);\n }\n processingKeys.delete(key);\n void processQueue();\n }\n };\n\n const queueTask = async <T>(\n task: () => Promise<T>,\n key: string\n ): Promise<Result<T, unknown>> =>\n new Promise((resolve) => {\n queue.push({\n task,\n resolve: resolve as (value: Result<unknown, unknown>) => void,\n key,\n });\n void processQueue();\n });\n\n return queueTask;\n}\n", "import type { AllProxiedNamespaces, ExtensionLink } from './types.js';\nimport type { ProviderContext, Providers } from '../index.js';\nimport type { Provider } from '@rango-dev/wallets-core';\nimport type { LegacyNamespaceInputForConnect } from '@rango-dev/wallets-core/legacy';\nimport type { VersionedProviders } from '@rango-dev/wallets-core/utils';\n\nimport { utils } from '@rango-dev/wallets-core/namespaces/evm';\nimport { type WalletInfo } from '@rango-dev/wallets-shared';\nimport { useEffect, useRef, useState } from 'react';\nimport { Ok, Result } from 'ts-results';\n\nimport {\n type ConnectResult,\n HUB_LAST_CONNECTED_WALLETS,\n type ProviderProps,\n} from '../legacy/mod.js';\nimport { useAutoConnect } from '../legacy/useAutoConnect.js';\n\nimport { autoConnect } from './autoConnect.js';\nimport { createQueue, fromAccountIdToLegacyAddressFormat } from './helpers.js';\nimport { LastConnectedWalletsFromStorage } from './lastConnectedWallets.js';\nimport { useHubRefs } from './useHubRefs.js';\nimport {\n getLegacyProvider,\n getSupportedChainsFromProvider,\n mapHubEventsToLegacy,\n transformHubResultToLegacyResult,\n tryConvertNamespaceNetworkToChainInfo,\n} from './utils.js';\n\nexport type UseAdapterParams = Omit<ProviderProps, 'providers'> & {\n providers: Provider[];\n /** This is only will be used to access some parts of the legacy provider that doesn't exists in Hub. */\n allVersionedProviders: VersionedProviders[];\n};\n\nexport function useHubAdapter(params: UseAdapterParams): ProviderContext {\n const { getStore, getHub } = useHubRefs(params.providers);\n const [, rerender] = useState(0);\n // useEffect will run `subscribe` once, so we need a reference and mutate the value if it's changes.\n const dataRef = useRef({\n onUpdateState: params.onUpdateState,\n allVersionedProviders: params.allVersionedProviders,\n allBlockChains: params.allBlockChains,\n });\n\n const queueTask = createQueue({\n onError: (error, actions) => {\n if (utils.isUserRejectionError(error)) {\n actions.removeCurrentKeyFromQueue();\n }\n },\n });\n\n useEffect(() => {\n dataRef.current = {\n onUpdateState: params.onUpdateState,\n allVersionedProviders: params.allVersionedProviders,\n allBlockChains: params.allBlockChains,\n };\n }, [params]);\n\n // Initialize instances\n useEffect(() => {\n const runOnInit = () => {\n getHub().init();\n\n rerender((currentRender) => currentRender + 1);\n };\n\n // Then will call init whenever page is ready.\n const initHubWhenPageIsReady = (event: Event) => {\n // Then will call init whenever page is ready.\n if (\n event.target &&\n (event.target as Document).readyState === 'complete'\n ) {\n runOnInit();\n document.removeEventListener(\n 'readystatechange',\n initHubWhenPageIsReady\n );\n }\n };\n\n // Try to run, maybe it's ready.\n runOnInit();\n\n /*\n * Try again when the page has been completely loaded.\n * Some of wallets, take some time to be fully injected and loaded.\n */\n document.addEventListener('readystatechange', initHubWhenPageIsReady);\n\n getStore()\n .subscribe((event) => {\n if (dataRef.current.onUpdateState) {\n try {\n mapHubEventsToLegacy(\n getHub(),\n event,\n dataRef.current.onUpdateState,\n dataRef.current.allBlockChains\n );\n } catch (e) {\n console.error(e);\n }\n }\n rerender((currentRender) => currentRender + 1);\n })\n .flushEvents();\n }, []);\n\n useAutoConnect({\n autoConnect: params.autoConnect,\n allBlockChains: params.allBlockChains,\n autoConnectHandler: () => {\n void autoConnect({\n allBlockChains: params.allBlockChains,\n getHub,\n wallets: params.configs?.wallets,\n });\n },\n });\n\n const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n HUB_LAST_CONNECTED_WALLETS\n );\n\n const api: ProviderContext = {\n canSwitchNetworkTo(type, network, namespace) {\n const provider = getHub().get(type);\n\n if (!provider) {\n throw new Error(\n `You should add ${type} to provider first then call 'canSwitchNetworkTo'.`\n );\n }\n\n if (!namespace) {\n throw new Error(\n 'Passing namespace to `canSwitchNetworkTo` is required.'\n );\n }\n\n const proxiedNamespace = provider.findByNamespace(namespace.namespace);\n if (!proxiedNamespace) {\n throw new Error(\n `We couldn't find any matched namespace on your request provider. (requested namespace: ${namespace.namespace})`\n );\n }\n if (!('canSwitchNetwork' in proxiedNamespace)) {\n return false;\n }\n const namespacesProperty = provider\n .info()\n ?.properties?.find((property) => property.name === 'namespaces');\n\n if (!dataRef.current.allBlockChains) {\n throw new Error(`Blockchains are not available`);\n }\n const providerSupportedChainsOfNamespace = namespacesProperty?.value.data\n .find(\n (providerNamespace) => providerNamespace.value === namespace.namespace\n )\n ?.getSupportedChains(dataRef.current.allBlockChains);\n\n if (!providerSupportedChainsOfNamespace) {\n throw new Error(\n `NamespaceMeta is not defined for requested namespace: ${namespace.namespace}`\n );\n }\n\n return proxiedNamespace.canSwitchNetwork({\n network,\n supportedChains: providerSupportedChainsOfNamespace,\n });\n },\n async connect(type, namespaces) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(\n `You should add ${type} to provider first then call 'connect'.`\n );\n }\n\n if (!namespaces) {\n throw new Error('Passing namespace to `connect` is required.');\n }\n\n // Check `namespace` and look into hub to see how it can match given namespace to hub namespace.\n const targetNamespaces: [\n LegacyNamespaceInputForConnect,\n AllProxiedNamespaces\n ][] = [];\n namespaces.forEach((namespace) => {\n const targetNamespace = namespace.namespace;\n\n const result = wallet.findByNamespace(targetNamespace);\n if (!result) {\n throw new Error(\n `We couldn't find any provider matched with your request namespace. (requested namespace: ${namespace.namespace})`\n );\n }\n\n targetNamespaces.push([namespace, result]);\n });\n\n // Try to run `connect` on matched namespaces\n const connectResultFromTargetNamespaces = targetNamespaces.map(\n async ([namespaceInput, namespace]) => {\n const network = tryConvertNamespaceNetworkToChainInfo(\n namespaceInput,\n params.allBlockChains || []\n );\n\n /*\n * `connect` can have different interfaces (e.g. Solana -> .connect(), EVM -> .connect(\"0x1\") ),\n * our assumption here is all the `connect` hasn't chain or if they have, they will accept it in first argument.\n * By this assumption, always passing a chain should be problematic since it will be ignored if the namespace's `connect` hasn't chain.\n */\n const connectNamespaceProcess = async () =>\n namespace\n .connect(network)\n .then<ConnectResult>(transformHubResultToLegacyResult)\n .then((connectResult) => {\n return {\n response: connectResult,\n input: {\n namespace: namespaceInput.namespace,\n network: namespaceInput.network,\n supportsEagerConnect: 'canEagerConnect' in namespace,\n },\n };\n });\n return queueTask(connectNamespaceProcess, type);\n }\n );\n\n /*\n * We need to connect to namespace one after another, sending multiple requests at the same time may be failed.\n * e.g. when wallet popup opens and asking for the password from the user, it should be resolved first, then other request will be resolved.\n */\n const connectResultWithLegacyFormat = await Promise.all(\n connectResultFromTargetNamespaces\n );\n\n // Keeping only namespaces that connected successfully and support eager connect, then we'll store them on storage for auto connect functionality.\n const successfullyConnectedSupportingEagerConnectNamespaces =\n connectResultWithLegacyFormat\n .filter(<T, E>(result: Result<T, E>): result is Ok<T> => result.ok)\n .filter((result) => result.val.input.supportsEagerConnect)\n .map((result) => ({\n namespace: result.val.input.namespace,\n network: result.val.input.network,\n }));\n\n if (successfullyConnectedSupportingEagerConnectNamespaces.length > 0) {\n lastConnectedWalletsFromStorage.addWallet(\n type,\n successfullyConnectedSupportingEagerConnectNamespaces\n );\n }\n\n // Getting rid of `input` from Result\n const connectResults = connectResultWithLegacyFormat.map((result) =>\n result.andThen((okResult) => new Ok(okResult.response))\n );\n\n const allResult = Result.all(...connectResults);\n if (allResult.err) {\n throw allResult.val;\n }\n\n return allResult.unwrap();\n },\n async disconnect(type, namespaces) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(\n `You should add ${type} to provider first then call 'disconnect'.`\n );\n }\n\n wallet.getAll().forEach((namespace) => {\n const namespaceShouldBeDisconnected =\n !namespaces || namespaces.includes(namespace.namespaceId);\n const namespaceIsConnected = namespace.state()[0]().connected;\n if (namespaceShouldBeDisconnected && namespaceIsConnected) {\n return namespace.disconnect();\n }\n });\n\n if (params.autoConnect) {\n if (namespaces) {\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n type,\n namespaces\n );\n } else {\n lastConnectedWalletsFromStorage.removeWallets([type]);\n }\n }\n },\n async disconnectAll() {\n const disconnectPromises: Promise<void>[] = Array.from(\n getHub().getAll().values()\n ).map(async (provider) => this.disconnect(provider.id));\n\n return await Promise.allSettled(disconnectPromises);\n },\n async getSigners(type) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n const info = wallet.info();\n if (!info) {\n throw new Error('Your provider should have required `info`.');\n }\n\n const providerProperties = info.properties;\n\n const signerProperty = providerProperties?.find(\n (property) => property.name === 'signers'\n );\n if (!signerProperty) {\n throw new Error('Your provider should contain signers property.');\n }\n\n return signerProperty.value.getSigners();\n },\n getWalletInfo(type) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n const info = wallet.info();\n if (!info) {\n throw new Error('Your provider should have required `info`.');\n }\n\n const installLink: Exclude<WalletInfo['installLink'], string> = {\n DEFAULT: '',\n };\n\n // `extensions` in legacy format was uppercase and also `DEFAULT` was used instead of `homepage`\n Object.keys(info.extensions).forEach((k) => {\n const key = k as ExtensionLink;\n\n if (key === 'homepage') {\n installLink.DEFAULT = info.extensions[key] || '';\n }\n\n const allowedKeys: ExtensionLink[] = [\n 'firefox',\n 'chrome',\n 'brave',\n 'edge',\n ];\n if (allowedKeys.includes(key)) {\n const upperCasedKey = key.toUpperCase() as keyof Exclude<\n WalletInfo['installLink'],\n string\n >;\n installLink[upperCasedKey] = info.extensions[key] || '';\n }\n });\n\n const providerProperties = info.properties;\n\n const namespacesProperty = providerProperties?.find(\n (property) => property.name === 'namespaces'\n );\n const derivationPathProperty = providerProperties?.find(\n (property) => property.name === 'derivationPath'\n );\n const detailsProperty = providerProperties?.find(\n (property) => property.name === 'details'\n );\n\n return {\n name: info.name,\n img: info.icon,\n installLink: installLink,\n // We don't have this values anymore, fill them with some values that communicate this.\n color: 'red',\n supportedChains: getSupportedChainsFromProvider(\n wallet,\n dataRef.current.allBlockChains\n ),\n isContractWallet: detailsProperty?.value?.isContractWallet,\n mobileWallet: detailsProperty?.value?.mobileWallet,\n // if set to false here, it will not show the wallet in mobile in anyways. to be compatible with old behavior, undefined is more appropirate.\n showOnMobile: detailsProperty?.value?.showOnMobile,\n needsNamespace: namespacesProperty?.value,\n needsDerivationPath: derivationPathProperty?.value,\n\n isHub: true,\n properties: wallet.info()?.properties,\n };\n },\n providers() {\n const output: Providers = {};\n\n Array.from(getHub().getAll().keys()).forEach((id) => {\n try {\n const provider = getLegacyProvider(params.allVersionedProviders, id);\n output[id] = provider.getInstance();\n } catch (e) {\n console.warn(e);\n }\n });\n\n return output;\n },\n state(type) {\n const hubState = getHub().state();\n const wallet = getHub().get(type);\n const walletState = hubState[type];\n\n if (!walletState || !wallet) {\n throw new Error(\n `It seems your requested provider doesn't exist in hub. Provider Id: ${type}`\n );\n }\n\n const accounts = walletState.namespaces\n .filter((namespace) => namespace.connected)\n .flatMap((namespace) =>\n namespace.accounts?.map(fromAccountIdToLegacyAddressFormat)\n )\n .filter((account): account is string => !!account);\n\n const namespacesState = new Map(\n Array.from(wallet.getAll(), ([_, value]) => [\n value.namespaceId,\n value.state()[0](),\n ])\n );\n\n const coreState = {\n connected: walletState.connected,\n connecting: walletState.connecting,\n installed: walletState.installed,\n reachable: true,\n accounts: accounts,\n network: null,\n namespaces: namespacesState,\n };\n return coreState;\n },\n suggestAndConnect(_type, _network): never {\n throw new Error('`suggestAndConnect` is not implemented');\n },\n };\n\n return api;\n}\n", "import type { AllProxiedNamespaces } from './types.js';\nimport type { UseAdapterParams } from './useHubAdapter.js';\nimport type { Hub, Provider } from '@rango-dev/wallets-core';\nimport type {\n LegacyNamespaceInputForConnect,\n LegacyProviderInterface,\n} from '@rango-dev/wallets-core/legacy';\nimport type { Namespace } from '@rango-dev/wallets-core/namespaces/common';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { legacyIsEvmNamespace } from '@rango-dev/wallets-core/legacy';\nimport { Result } from 'ts-results';\n\nimport { HUB_LAST_CONNECTED_WALLETS } from '../legacy/mod.js';\n\nimport { runSequentiallyWithoutFailure } from './helpers.js';\nimport { LastConnectedWalletsFromStorage } from './lastConnectedWallets.js';\nimport { convertNamespaceNetworkToEvmChainId } from './utils.js';\n\n// Getting connected wallets from storage\nconst lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n HUB_LAST_CONNECTED_WALLETS\n);\n\n/**\n * Run `.connect` action on some selected namespaces (passed as param) for a provider.\n */\nasync function eagerConnect(\n type: string,\n namespacesInput: LegacyNamespaceInputForConnect[] | undefined,\n params: {\n getHub: () => Hub;\n allBlockChains: UseAdapterParams['allBlockChains'];\n }\n) {\n const { getHub, allBlockChains } = params;\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(\n `You should add ${type} to provider first then call 'connect'.`\n );\n }\n\n if (!namespacesInput) {\n throw new Error('Passing namespace to `connect` is required. ');\n }\n\n const targetNamespaces: [\n LegacyNamespaceInputForConnect,\n AllProxiedNamespaces\n ][] = [];\n namespacesInput.forEach((namespaceInput) => {\n const targetNamespace: Namespace = namespaceInput.namespace;\n\n const result = wallet.findByNamespace(targetNamespace);\n\n if (!result) {\n throw new Error(\n `We couldn't find any provider matched with your request namespace. (requested namespace: ${namespaceInput.namespace})`\n );\n }\n\n targetNamespaces.push([namespaceInput, result]);\n });\n\n const connectNamespacesPromises = targetNamespaces.map(\n ([info, namespace]) => {\n const evmChain = legacyIsEvmNamespace(info)\n ? convertNamespaceNetworkToEvmChainId(info, allBlockChains || [])\n : undefined;\n const chain = evmChain || info.network;\n\n return async () =>\n await namespace.connect(chain).catch((e) => {\n /*\n * Since we check for connect failures using `instanceof Error`\n * this check is added here to make sure the thrown error always is an instance of `Error`\n */\n if (e instanceof Error) {\n throw e;\n }\n throw new Error(e);\n });\n }\n );\n\n /**\n * Sometimes calling methods on a instance in parallel, would cause an error in wallet.\n * We are running a method at a time to make sure we are covering this.\n * e.g. when we are trying to eagerConnect evm and solana on phantom at the same time, the last namespace throw an error.\n */\n const connectNamespacesResult = await runSequentiallyWithoutFailure(\n connectNamespacesPromises\n );\n\n const failedNamespaces: LegacyNamespaceInputForConnect[] = targetNamespaces\n .filter((_, index) => connectNamespacesResult[index].err)\n .map((targetNamespace) => targetNamespace[0]);\n\n if (failedNamespaces.length > 0) {\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n type,\n failedNamespaces.map((namespace) => namespace.namespace)\n );\n }\n\n const atLeastOneNamespaceConnectedSuccessfully = connectNamespacesResult.some(\n (result) => result.ok\n );\n if (!atLeastOneNamespaceConnectedSuccessfully) {\n throw new Error(`No namespace connected for ${type}`);\n }\n return Result.all(\n ...connectNamespacesResult.filter((result) => result.ok)\n ).unwrap();\n}\n\n/**\n * Run `.canEagerConnect` action on some selected namespaces of a wallet.\n */\nasync function tryRunCanEagerConnect(\n namespaces: LegacyNamespaceInputForConnect[],\n wallet: Provider\n): Promise<{\n successNamespaces: LegacyNamespaceInputForConnect[];\n failedNamespaces: LegacyNamespaceInputForConnect[];\n}> {\n const foundNamespaces: LegacyNamespaceInputForConnect[] = [];\n const successNamespaces: LegacyNamespaceInputForConnect[] = [];\n const failedNamespaces: LegacyNamespaceInputForConnect[] = [];\n const canEagerConnectPromises: (() => Promise<boolean>)[] = [];\n\n // 1. Try find namespace instances and create canEagerConnect promises\n namespaces.forEach((namespace) => {\n const namespaceInstance = wallet.findByNamespace(namespace.namespace);\n if (namespaceInstance) {\n foundNamespaces.push(namespace);\n canEagerConnectPromises.push(\n async () => await namespaceInstance.canEagerConnect()\n );\n } else {\n failedNamespaces.push(namespace);\n }\n });\n\n // 2. Run canEagerConnect sequentially on namespaces\n const canEagerConnectResults = await runSequentiallyWithoutFailure(\n canEagerConnectPromises\n );\n\n // 3. Separate success and failed namespaces based on canEagerConnect result\n foundNamespaces.forEach((namespace, index) => {\n if (canEagerConnectResults[index].ok && canEagerConnectResults[index].val) {\n successNamespaces.push(namespace);\n } else {\n failedNamespaces.push(namespace);\n }\n });\n\n return { successNamespaces, failedNamespaces };\n}\n\n/*\n * Get last connected wallets and last connected namespaces for each of them from storage\n * Then run `.connect` on each namespace if `.canEagerConnect` returns true.\n */\nexport async function autoConnect(deps: {\n getHub: () => Hub;\n allBlockChains: UseAdapterParams['allBlockChains'];\n wallets?: (WalletType | LegacyProviderInterface)[];\n}): Promise<void> {\n const { getHub, allBlockChains, wallets } = deps;\n const lastConnectedWallets = lastConnectedWalletsFromStorage.list();\n const walletIds = Object.keys(lastConnectedWallets);\n\n const walletsToRemoveFromPersistence: string[] = [];\n\n if (walletIds.length) {\n const eagerConnectQueue: Promise<unknown>[] = [];\n\n // Run `.connect` if `.canEagerConnect` returns `true`.\n walletIds.forEach(async (providerName) => {\n if (wallets && !wallets.includes(providerName)) {\n console.warn(\n 'Trying to run auto connect for a wallet which is not included in config. Desired wallet:',\n providerName\n );\n walletsToRemoveFromPersistence.push(providerName);\n return;\n }\n\n const wallet = getHub().get(providerName);\n\n const lastConnectedNamespaces: LegacyNamespaceInputForConnect[] =\n lastConnectedWallets[providerName].map((namespace) => ({\n namespace: namespace.namespace,\n network: namespace.network,\n }));\n\n if (!lastConnectedNamespaces.length || !wallet) {\n walletsToRemoveFromPersistence.push(providerName);\n return;\n }\n\n const { successNamespaces, failedNamespaces } =\n await tryRunCanEagerConnect(lastConnectedNamespaces, wallet);\n\n if (!successNamespaces.length) {\n walletsToRemoveFromPersistence.push(providerName);\n return;\n } else if (failedNamespaces.length) {\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n wallet.id,\n failedNamespaces.map((namespace) => namespace.namespace)\n );\n }\n eagerConnectQueue.push(\n eagerConnect(providerName, successNamespaces, {\n allBlockChains,\n getHub,\n }).catch((error) => console.warn(error))\n );\n });\n\n lastConnectedWalletsFromStorage.removeWallets(\n walletsToRemoveFromPersistence\n );\n\n await Promise.all(eagerConnectQueue);\n }\n}\n", "import type { Provider, Store } from '@rango-dev/wallets-core';\n\nimport { createStore, Hub } from '@rango-dev/wallets-core';\nimport { useRef } from 'react';\n\nimport { synchronizeHubWithConfigProviders } from './utils.js';\n\nexport function useHubRefs(providers: Provider[]) {\n const store = useRef<Store | null>(null);\n\n const hub = useRef<Hub | null>(null);\n\n function createHub() {\n const createdHub = new Hub({\n store: getStore(),\n });\n /*\n * First add providers to hub\n * This helps to `getWalletInfo` be usable, before initialize.\n */\n providers.forEach((provider) => {\n createdHub.add(provider.id, provider);\n });\n hub.current = createdHub;\n return createdHub;\n }\n\n // https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents\n function getStore() {\n if (store.current !== null) {\n return store.current;\n }\n const createdStore = createStore();\n store.current = createdStore;\n return createdStore;\n }\n\n function getHub(): Hub {\n const hubProviders = hub.current?.getAll();\n\n if (!hub.current || !hubProviders) {\n return createHub();\n }\n\n synchronizeHubWithConfigProviders(hub.current, providers);\n return hub.current;\n }\n\n return { getStore, getHub };\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { AllProxiedNamespaces } from './types.js';\nimport type { Hub, Provider } from '@rango-dev/wallets-core';\nimport type {\n LegacyNamespaceInputForConnect,\n LegacyProviderInterface,\n LegacyEventHandler as WalletEventHandler,\n} from '@rango-dev/wallets-core/legacy';\nimport type { Event } from '@rango-dev/wallets-core/store';\n\nimport { LegacyEvents as Events } from '@rango-dev/wallets-core/legacy';\nimport { type VersionedProviders } from '@rango-dev/wallets-core/utils';\nimport { pickVersion } from '@rango-dev/wallets-core/utils';\nimport {\n type AddEthereumChainParameter,\n convertEvmBlockchainMetaToEvmChainInfo,\n} from '@rango-dev/wallets-shared';\nimport { type BlockchainMeta, isEvmBlockchain } from 'rango-types';\n\nimport {\n type ConnectResult,\n HUB_LAST_CONNECTED_WALLETS,\n type ProviderProps,\n} from '../legacy/mod.js';\n\nimport {\n fromAccountIdToLegacyAddressFormat,\n isConnectResultEvm,\n isConnectResultSolana,\n} from './helpers.js';\nimport { LastConnectedWalletsFromStorage } from './lastConnectedWallets.js';\n\n/* Gets a list of hub and legacy providers and returns a tuple which separates them. */\nexport function separateLegacyAndHubProviders(\n providers: VersionedProviders[]\n): [LegacyProviderInterface[], Provider[]] {\n const LEGACY_VERSION = '0.0.0';\n const HUB_VERSION = '1.0.0';\n\n const legacyProviders: LegacyProviderInterface[] = [];\n const hubProviders: Provider[] = [];\n\n providers.forEach((provider) => {\n try {\n const target = pickVersion(provider, HUB_VERSION);\n hubProviders.push(target[1]);\n } catch {\n const target = pickVersion(provider, LEGACY_VERSION);\n legacyProviders.push(target[1]);\n }\n });\n\n return [legacyProviders, hubProviders];\n}\n\nexport function findProviderByType(\n providers: Provider[],\n type: string\n): Provider | undefined {\n return providers.find((provider) => provider.id === type);\n}\n\n/**\n * We will call this function on hub's `subscribe`.\n * it will check states and will emit legacy events for backward compatibility.\n */\n\nconst lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n HUB_LAST_CONNECTED_WALLETS\n);\n\nexport function getSupportedChainsFromProvider(\n provider: Provider,\n allBlockChains: ProviderProps['allBlockChains']\n) {\n const namespacesProperty = provider\n .info()\n ?.metadata.properties?.find((property) => property.name === 'namespaces');\n\n const supportedChains =\n namespacesProperty?.value.data.flatMap((namespace) =>\n namespace.getSupportedChains(allBlockChains || [])\n ) || [];\n\n return supportedChains;\n}\n\nexport function mapHubEventsToLegacy(\n hub: Hub,\n event: Event,\n onUpdateState: WalletEventHandler,\n allBlockChains: ProviderProps['allBlockChains']\n): void {\n const provider = hub.get(event.provider);\n if (!provider) {\n throw new Error(\n \"Currently all the events have assigned to a provider. The event doesn't include one.\",\n {\n cause: event,\n }\n );\n }\n\n // @ts-expect-error for those events that doesn't have namespace, it will be undefinded\n const namespaceId: string | undefined = event.namespace;\n\n const namespace = namespaceId\n ? provider.findByNamespace(namespaceId)\n : undefined;\n let accounts: string[] | null = null;\n let network: string | null = null;\n\n if (namespace) {\n const [getNamespaceState] = namespace.state();\n accounts = getNamespaceState().accounts;\n network = getNamespaceState().network;\n }\n\n const [getProviderState] = provider.state();\n const coreState = {\n connected: getProviderState().connected,\n connecting: getProviderState().connecting,\n installed: getProviderState().installed,\n accounts,\n network,\n reachable: true,\n };\n\n const eventInfo = {\n supportedBlockchains: getSupportedChainsFromProvider(\n provider,\n allBlockChains\n ),\n isContractWallet: false,\n isHub: true,\n namespace: namespaceId,\n };\n\n switch (event.type) {\n case 'provider_detected':\n onUpdateState(\n event.provider,\n Events.INSTALLED,\n true,\n coreState,\n eventInfo\n );\n break;\n case 'provider_connecting':\n onUpdateState(\n event.provider,\n Events.CONNECTING,\n event.value,\n coreState,\n eventInfo\n );\n break;\n case 'provider_connected':\n onUpdateState(\n event.provider,\n Events.CONNECTED,\n true,\n coreState,\n eventInfo\n );\n break;\n case 'provider_disconnected':\n onUpdateState(\n event.provider,\n Events.PROVIDER_DISCONNECTED,\n event.provider,\n coreState,\n eventInfo\n );\n onUpdateState(\n event.provider,\n Events.CONNECTED,\n false,\n coreState,\n eventInfo\n );\n onUpdateState(\n event.provider,\n Events.ACCOUNTS,\n null,\n coreState,\n eventInfo\n );\n break;\n case 'namespace_disconnected':\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n event.provider,\n [event.namespace]\n );\n\n onUpdateState(\n event.provider,\n Events.NAMESPACE_DISCONNECTED,\n event.namespace,\n coreState,\n {\n ...eventInfo,\n namespace: event.namespace,\n }\n );\n // onUpdateState(event.provider, Events.ACCOUNTS, null, coreState, eventInfo);\n break;\n case 'namespace_connected':\n case 'namespace_account_switched':\n {\n if (event.type === 'namespace_account_switched') {\n onUpdateState(\n event.provider,\n Events.NAMESPACE_DISCONNECTED,\n event.namespace,\n coreState,\n eventInfo\n );\n }\n\n const formattedAddresses = event.accounts.map(\n fromAccountIdToLegacyAddressFormat\n );\n onUpdateState(\n event.provider,\n Events.ACCOUNTS,\n formattedAddresses,\n coreState,\n {\n ...eventInfo,\n namespace: event.namespace,\n }\n );\n }\n break;\n case 'namespace_network_switched':\n onUpdateState(event.provider, Events.NETWORK, event.network, coreState, {\n ...eventInfo,\n namespace: event.namespace,\n });\n break;\n }\n}\n\nexport function getAllLegacyProviders(\n allProviders: VersionedProviders[]\n): LegacyProviderInterface[] {\n const LEGACY_VERSION = '0.0.0';\n\n const legacyProviders: LegacyProviderInterface[] = [];\n\n allProviders.forEach((provider) => {\n const target = pickVersion(provider, LEGACY_VERSION);\n legacyProviders.push(target[1]);\n });\n\n return legacyProviders;\n}\n\nexport function getLegacyProvider(\n allProviders: VersionedProviders[],\n type: string\n): LegacyProviderInterface {\n const legacyProviders: LegacyProviderInterface[] =\n getAllLegacyProviders(allProviders);\n\n const provider = legacyProviders.find((legacyProvider) => {\n return legacyProvider.config.type === type;\n });\n\n if (!provider) {\n console.warn(\n `You have a provider that doesn't have legacy provider. It causes some problems since we need some legacy functionality. Provider Id: ${type}`\n );\n throw new Error(\n `You need to have legacy implementation to use some methods. Provider Id: ${type}`\n );\n }\n\n return provider;\n}\n\n/**\n * In legacy mode, for those who have switch network functionality (like evm), we are using an enum for network names\n * this enum only has meaning for us, and when we are going to connect an instance (e.g. window.ethereum) we should pass chain id.\n */\nexport function convertNamespaceNetworkToEvmChainId(\n namespace: LegacyNamespaceInputForConnect,\n meta: BlockchainMeta[]\n) {\n if (!namespace.network) {\n return undefined;\n }\n\n const evmBlockchainsList = meta.filter(isEvmBlockchain);\n const evmChains = convertEvmBlockchainMetaToEvmChainInfo(evmBlockchainsList);\n\n return evmChains[namespace.network];\n}\n\n/**\n * We are passing an string for chain id (e.g. ETH, POLYGON), but wallet's instances (e.g. window.ethereum) needs chainId (e.g. 0x1).\n * This function will help us to map these strings to proper hex ids.\n *\n * If you need same functionality for other blockchain types (e.g. Cosmos), You can make a separate function and add it here.\n */\nexport function tryConvertNamespaceNetworkToChainInfo(\n namespace: LegacyNamespaceInputForConnect,\n meta: BlockchainMeta[]\n): string | AddEthereumChainParameter | undefined {\n // `undefined` means it's not evm or we couldn't find it in meta.\n const evmChain = convertNamespaceNetworkToEvmChainId(namespace, meta);\n const network = evmChain || namespace.network;\n\n return network;\n}\n\nexport function transformHubResultToLegacyResult(\n res: Awaited<ReturnType<AllProxiedNamespaces['connect']>>\n): ConnectResult {\n if (isConnectResultEvm(res)) {\n return {\n accounts: res.accounts,\n network: res.network,\n provider: undefined,\n };\n } else if (isConnectResultSolana(res)) {\n return {\n accounts: res,\n network: null,\n provider: undefined,\n };\n }\n\n return {\n accounts: [res],\n network: null,\n provider: undefined,\n };\n}\n\n/**\n * Synchronizes providers in the hub with the configuration providers.\n * - Registers and initializes any configuration providers not yet in the hub\n * - Removes providers from the hub that aren't in the configuration\n */\nexport function synchronizeHubWithConfigProviders(\n hub: Hub,\n configurationProviders: Provider[]\n) {\n const registeredProviders = hub.getAll();\n\n // Register and initialize providers that exist in config but not in hub\n const providersToRegister = configurationProviders.filter(\n (configProvider) => !registeredProviders.get(configProvider.id)\n );\n\n providersToRegister.forEach((providerToRegister) => {\n hub.add(providerToRegister.id, providerToRegister);\n providerToRegister.init();\n });\n\n // Remove providers that exist in hub but not in config\n registeredProviders.forEach((registeredProvider) => {\n const isProviderInConfig = configurationProviders.some(\n (configProvider) => configProvider.id === registeredProvider.id\n );\n\n if (!isProviderInConfig) {\n hub.remove(registeredProvider.id);\n }\n });\n}\n", "export const LEGACY_LAST_CONNECTED_WALLETS = 'last-connected-wallets';\nexport const HUB_LAST_CONNECTED_WALLETS = 'hub-v1-last-connected-wallets';\n", "import type { ProviderContext } from './types.js';\n\nimport { createContext } from 'react';\n\nconst defaultErrorMessage = \"Context hasn't been initialized yet.\";\nconst defaultContext: ProviderContext = {\n async connect() {\n throw new Error(defaultErrorMessage);\n },\n async disconnect() {\n throw new Error(defaultErrorMessage);\n },\n async disconnectAll() {\n throw new Error(defaultErrorMessage);\n },\n async suggestAndConnect() {\n throw new Error(defaultErrorMessage);\n },\n state() {\n throw new Error(defaultErrorMessage);\n },\n canSwitchNetworkTo() {\n throw new Error(defaultErrorMessage);\n },\n providers() {\n throw new Error(defaultErrorMessage);\n },\n getWalletInfo() {\n throw new Error(defaultErrorMessage);\n },\n getSigners() {\n throw new Error(defaultErrorMessage);\n },\n};\n\nexport const WalletContext = createContext<ProviderContext>(defaultContext);\n", "import type { ProviderContext, ProviderProps } from './types.js';\nimport type { LegacyProviderInterface } from '@rango-dev/wallets-core/legacy';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { useEffect, useReducer } from 'react';\n\nimport { autoConnect } from './autoConnect.js';\nimport {\n availableWallets,\n checkWalletProviders,\n clearPersistance,\n connectedWallets,\n defaultWalletState,\n makeEventHandler,\n stateReducer,\n tryPersistWallet,\n tryRemoveWalletFromPersistance,\n} from './helpers.js';\nimport { useInitializers } from './hooks.js';\nimport { useAutoConnect } from './useAutoConnect.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ProviderType = any;\n\nexport type LegacyProviderProps = Omit<ProviderProps, 'providers'> & {\n providers: LegacyProviderInterface[];\n};\n\nexport function useLegacyProviders(\n props: LegacyProviderProps\n): ProviderContext {\n const [providersState, dispatch] = useReducer(stateReducer, {});\n\n // Get (or add) wallet instance (`provider`s will be wrapped in a `Wallet`)\n const getWalletInstance = useInitializers(\n makeEventHandler(dispatch, props.onUpdateState)\n );\n\n // Getting providers from props and put all of them in a `Map` with an appropriate interface.\n const listOfProviders = props.providers;\n const wallets = checkWalletProviders(listOfProviders);\n\n useAutoConnect({\n allBlockChains: props.allBlockChains,\n autoConnect: props.autoConnect,\n autoConnectHandler: async () => autoConnect(wallets, getWalletInstance),\n });\n\n // Final API we put in context and it will be available to use for users.\n const api: ProviderContext = {\n async connect(type, namespaces) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n // Legacy providers doesn't implemented multiple namespaces, so it will always be one value.\n let network = undefined;\n if (namespaces && namespaces.length > 0) {\n /*\n * This may not be safe in cases there are two `network` for namespaces, the first one will be picked always.\n * But since legacy provider only accepts one value, it shouldn't be happened when we are using legacy mode.\n */\n network = namespaces.find((ns) => !!ns.network)?.network;\n }\n\n const walletInstance = getWalletInstance(wallet);\n const result = await walletInstance.connect(network, namespaces);\n if (props.autoConnect) {\n void tryPersistWallet({\n type,\n walletActions: wallet.actions,\n getState: api.state,\n });\n }\n\n return [result];\n },\n async disconnect(type) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n const walletInstance = getWalletInstance(wallet);\n await walletInstance.disconnect();\n if (props.autoConnect) {\n tryRemoveWalletFromPersistance({ type, walletActions: wallet.actions });\n }\n },\n async disconnectAll() {\n const disconnect_promises: Promise<void>[] = [];\n\n /*\n * When a wallet is initializing, a record will be added to `providersState`\n * So we use them to know what wallet has been initialized then we need to\n * filter connected wallets only.\n */\n connectedWallets(providersState).forEach((type) => {\n const wallet = wallets.get(type);\n\n if (wallet) {\n const walletInstance = getWalletInstance(wallet);\n disconnect_promises.push(walletInstance.disconnect());\n }\n });\n\n if (props.autoConnect) {\n clearPersistance();\n }\n return await Promise.allSettled(disconnect_promises);\n },\n\n async suggestAndConnect(type, network) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n const walletInstance = getWalletInstance(wallet);\n const result = await walletInstance.suggestAndConnect(network);\n\n return result;\n },\n\n state(type) {\n return providersState[type] || defaultWalletState;\n },\n canSwitchNetworkTo(type, network) {\n const wallet = wallets.get(type);\n if (!wallet) {\n return false;\n }\n\n const walletInstance = getWalletInstance(wallet);\n return walletInstance.canSwitchNetworkTo\n ? walletInstance.canSwitchNetworkTo(network, walletInstance.provider)\n : false;\n },\n providers() {\n const providers: { [type in WalletType]?: ProviderType } = {};\n availableWallets(providersState).forEach((type) => {\n const wallet = wallets.get(type);\n if (wallet) {\n const walletInstance = getWalletInstance(wallet);\n providers[type] = walletInstance.provider;\n }\n });\n\n return providers;\n },\n getWalletInfo(type) {\n const wallet = wallets.get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n /*\n * Get wallet info could be used in render methods to show wallets data\n * So, addWalletRef method shouldn't be called in this method\n */\n\n return wallet.actions.getWalletInfo(props.allBlockChains || []);\n },\n async getSigners(type) {\n const wallet = wallets.get(type);\n\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n const walletInstance = getWalletInstance(wallet);\n const provider = walletInstance.provider;\n const result = walletInstance.getSigners(provider);\n\n return result;\n },\n };\n\n // Initialize instances\n useEffect(() => {\n wallets.forEach((wallet) => {\n const walletInstance = getWalletInstance(wallet);\n const runOnInit = () => {\n if (walletInstance.onInit) {\n walletInstance.onInit();\n }\n };\n\n const initWhenPageIsReady = (event: Event) => {\n if (\n event.target &&\n (event.target as Document).readyState === 'complete'\n ) {\n runOnInit();\n\n document.removeEventListener('readystatechange', initWhenPageIsReady);\n }\n };\n\n // Try to run, maybe it's ready.\n runOnInit();\n\n /*\n * Try again when the page has been completely loaded.\n * Some of wallets, take some time to be fully injected and loaded.\n */\n document.addEventListener('readystatechange', initWhenPageIsReady);\n });\n }, []);\n\n // Setting supported blockchains on instances\n useEffect(() => {\n const allBlockChains = props.allBlockChains;\n if (allBlockChains) {\n wallets.forEach((wallet) => {\n const walletInstance = getWalletInstance(wallet);\n const walletInfo = walletInstance.getWalletInfo(\n props.allBlockChains || []\n );\n walletInstance.setInfo({\n supportedBlockchains: walletInfo.supportedChains,\n isContractWallet: !!walletInfo.isContractWallet,\n });\n });\n }\n }, [props.allBlockChains]);\n\n // Setting event handler on instances\n useEffect(() => {\n wallets.forEach((wallet) => {\n const walletInstance = getWalletInstance(wallet);\n walletInstance.setHandler(\n makeEventHandler(dispatch, props.onUpdateState)\n );\n });\n }, [props.onUpdateState]);\n\n return api;\n}\n", "import type { Namespace } from '@rango-dev/wallets-core/namespaces/common';\n\nimport { Persistor } from '@rango-dev/wallets-core/legacy';\n\nimport {\n HUB_LAST_CONNECTED_WALLETS,\n LEGACY_LAST_CONNECTED_WALLETS,\n} from './constants.js';\n\nexport interface NamespaceInput {\n namespace: Namespace;\n network: string | undefined;\n}\n\nexport interface LastConnectedWalletsStorage {\n [providerId: string]: NamespaceInput[];\n}\n\nexport type LegacyLastConnectedWalletsStorage = string[];\n\n/**\n * We are doing some certain actions on storage for `last-connected-wallets` key.\n * This class helps us to define them in one place and also it has support for both legacy and hub.\n */\nexport class LastConnectedWalletsFromStorage {\n #storageKey: string;\n\n constructor(storageKey: string) {\n this.#storageKey = storageKey;\n }\n\n addWallet(providerId: string, namespaces: NamespaceInput[]): void {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#addWalletToHub(providerId, namespaces);\n } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {\n return this.#addWalletToLegacy(providerId);\n }\n throw new Error('Not implemented');\n }\n removeWallets(providerIds?: string[]): void {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#removeWalletsFromHub(providerIds);\n } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {\n return this.#removeWalletsFromLegacy(providerIds);\n }\n throw new Error('Not implemented');\n }\n list(): LastConnectedWalletsStorage {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#listFromHub();\n } else if (this.#storageKey === LEGACY_LAST_CONNECTED_WALLETS) {\n return this.#listFromLegacy();\n }\n throw new Error('Not implemented');\n }\n removeNamespacesFromWallet(providerId: string, namespaceIds: string[]) {\n if (this.#storageKey === HUB_LAST_CONNECTED_WALLETS) {\n return this.#removeNamespaceFromWalletHub(providerId, namespaceIds);\n }\n throw new Error('Not implemented');\n }\n\n #listFromLegacy(): LastConnectedWalletsStorage {\n const persistor = new Persistor<LegacyLastConnectedWalletsStorage>();\n const lastConnectedWallets =\n persistor.getItem(LEGACY_LAST_CONNECTED_WALLETS) || [];\n const output: LastConnectedWalletsStorage = {};\n lastConnectedWallets.forEach((provider) => {\n // Setting empty namespaces\n output[provider] = [];\n });\n return output;\n }\n #listFromHub(): LastConnectedWalletsStorage {\n const persistor = new Persistor<LastConnectedWalletsStorage>();\n const lastConnectedWallets =\n persistor.getItem(HUB_LAST_CONNECTED_WALLETS) || {};\n return lastConnectedWallets;\n }\n #addWalletToHub(providerId: string, namespaces: NamespaceInput[]): void {\n const storage = new Persistor<LastConnectedWalletsStorage>();\n const storageState = storage.getItem(this.#storageKey) || {};\n\n let toBeAddedNamespaces = namespaces;\n\n // If provider already exits in the storage, we should just add new namespaces to the previously added namespaces.\n if (!!storageState[providerId]) {\n const storedNamespaces = storageState[providerId];\n toBeAddedNamespaces = storedNamespaces.concat(\n namespaces.filter(\n (namespace) =>\n !storedNamespaces.some(\n (storedNamespace) =>\n storedNamespace.namespace === namespace.namespace\n )\n )\n );\n }\n\n storage.setItem(this.#storageKey, {\n ...storageState,\n [providerId]: toBeAddedNamespaces,\n });\n }\n #addWalletToLegacy(providerId: string): void {\n const storage = new Persistor<LegacyLastConnectedWalletsStorage>();\n const storageState = storage.getItem(this.#storageKey) || [];\n\n storage.setItem(\n LEGACY_LAST_CONNECTED_WALLETS,\n storageState.concat(providerId)\n );\n }\n #removeWalletsFromHub(providerIds?: string[]): void {\n const persistor = new Persistor<LastConnectedWalletsStorage>();\n const storageState = persistor.getItem(this.#storageKey) || {};\n\n // Remove all wallets\n if (!providerIds) {\n persistor.setItem(this.#storageKey, {});\n return;\n }\n\n // Remove some of the wallets\n providerIds.forEach((providerId) => {\n if (storageState[providerId]) {\n delete storageState[providerId];\n }\n });\n\n persistor.setItem(this.#storageKey, storageState);\n }\n #removeNamespaceFromWalletHub(\n providerId: string,\n namespaceIds: string[]\n ): void {\n const persistor = new Persistor<LastConnectedWalletsStorage>();\n const storageState = persistor.getItem(this.#storageKey) || {};\n\n const currentProviderNamespaces = storageState[providerId];\n const newProviderNamespaces = currentProviderNamespaces?.filter(\n (namespace) => !namespaceIds.includes(namespace.namespace)\n );\n\n this.#removeWalletsFromHub([providerId]);\n if (newProviderNamespaces?.length > 0) {\n this.#addWalletToHub(providerId, newProviderNamespaces);\n }\n }\n #removeWalletsFromLegacy(providerIds?: string[]): void {\n const persistor = new Persistor<LegacyLastConnectedWalletsStorage>();\n const storageState = persistor.getItem(this.#storageKey) || [];\n\n // Remove all wallets\n if (!providerIds) {\n persistor.setItem(this.#storageKey, []);\n return;\n }\n\n // Remove some of the wallets\n persistor.setItem(\n LEGACY_LAST_CONNECTED_WALLETS,\n storageState.filter((wallet) => !providerIds.includes(wallet))\n );\n }\n}\n", "import type {\n ProviderInterface,\n State,\n WalletActions,\n WalletProviders,\n} from './types.js';\nimport type {\n LegacyOptions as Options,\n LegacyEventHandler as WalletEventHandler,\n LegacyState as WalletState,\n} from '@rango-dev/wallets-core/legacy';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { Persistor } from '@rango-dev/wallets-core/legacy';\n\nimport { LEGACY_LAST_CONNECTED_WALLETS } from '../hub/constants.js';\nimport { LastConnectedWalletsFromStorage } from '../hub/lastConnectedWallets.js';\n\nexport function choose(wallets: any[], type: WalletType): any | null {\n return wallets.find((wallet) => wallet.type === type) || null;\n}\n\nexport const defaultWalletState: WalletState = {\n connected: false,\n connecting: false,\n reachable: false,\n installed: false,\n accounts: null,\n network: null,\n};\n\nexport function stateReducer(state: State, action: any) {\n if (action.type === 'new_state') {\n // TODO fix problem and remove ts-ignore\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n const target_wallet = state[action.wallet];\n if (!target_wallet) {\n return {\n ...state,\n [action.wallet]: {\n ...defaultWalletState,\n [action.name]: action.value,\n },\n };\n }\n\n return {\n ...state,\n [action.wallet]: {\n ...target_wallet,\n [action.name]: action.value,\n },\n };\n }\n\n return state;\n}\n\nexport function connectedWallets(providersState: State): WalletType[] {\n return Object.entries(providersState)\n .filter(([, wallet_state]) => {\n return wallet_state?.connected;\n })\n .map(([type]) => {\n return type;\n });\n}\n\nexport function availableWallets(providersState: State): WalletType[] {\n return Object.entries(providersState).map(([type]) => {\n return type;\n });\n}\n\nexport function checkWalletProviders(\n list: ProviderInterface[]\n): WalletProviders {\n const wallets: WalletProviders = new Map();\n\n list.forEach((provider) => {\n const { config, ...actions } = provider;\n wallets.set(config.type, {\n actions,\n config,\n });\n });\n\n return wallets;\n}\n\n/* eslint-disable @typescript-eslint/ban-types */\nexport function isAsync(fn: Function) {\n return fn?.constructor?.name === 'AsyncFunction';\n}\n\nexport function needsCheckInstallation(options: Options) {\n const { checkInstallation = true } = options.config;\n return checkInstallation;\n}\n\nexport async function tryPersistWallet({\n type,\n walletActions,\n getState,\n}: {\n type: WalletType;\n walletActions: WalletActions;\n getState: (walletType: WalletType) => WalletState;\n}) {\n if (walletActions.canEagerConnect) {\n const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n LEGACY_LAST_CONNECTED_WALLETS\n );\n const lastConnectedWallets = lastConnectedWalletsFromStorage.list();\n const walletAlreadyPersisted = !!lastConnectedWallets[type];\n\n /*\n *If on the last attempt we are unable to eagerly connect to any wallet and the user connects any wallet manualy,\n *persistance will be outdated and will need to be removed.\n */\n if (walletAlreadyPersisted && !getState(type).connected) {\n clearPersistance();\n }\n\n if (!walletAlreadyPersisted) {\n lastConnectedWalletsFromStorage.addWallet(type, []);\n }\n }\n}\n\nexport function tryRemoveWalletFromPersistance({\n type,\n walletActions,\n}: {\n type: WalletType;\n walletActions: WalletActions;\n}) {\n if (walletActions.canEagerConnect) {\n const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n LEGACY_LAST_CONNECTED_WALLETS\n );\n lastConnectedWalletsFromStorage.removeWallets([type]);\n }\n}\n\nexport function clearPersistance() {\n const persistor = new Persistor<string[]>();\n const wallets = persistor.getItem(LEGACY_LAST_CONNECTED_WALLETS);\n if (wallets) {\n persistor.removeItem(LEGACY_LAST_CONNECTED_WALLETS);\n }\n}\n\n/*\n *Our event handler includes an internal state updater, and a notifier\n *for the outside listener.\n *On creating first wallet refrence, and on chaning `props.onUpdateState`\n *we are using this function.\n */\nexport function makeEventHandler(\n dispatcher: any,\n onUpdateState?: WalletEventHandler\n) {\n const handler: WalletEventHandler = (\n type,\n name,\n value,\n coreState,\n supportedChains\n ) => {\n const action = { type: 'new_state', wallet: type, name, value };\n // Update state\n dispatcher(action);\n\n // Giving the event to the outside listener\n if (onUpdateState) {\n onUpdateState(type, name, value, coreState, supportedChains);\n }\n };\n\n return handler;\n}\n", "import type { ProviderContext, WalletActions, WalletConfig } from './types.js';\nimport type { LegacyEventHandler as WalletEventHandler } from '@rango-dev/wallets-core/legacy';\n\nimport { LegacyWallet as Wallet } from '@rango-dev/wallets-core/legacy';\nimport { useContext, useRef } from 'react';\n\nimport { WalletContext } from './context.js';\n\nexport type GetWalletInstance = (wallet: {\n actions: WalletActions;\n config: WalletConfig;\n}) => Wallet;\n\nexport function useInitializers(\n onChangeState: WalletEventHandler\n): GetWalletInstance {\n const availableWallets = useRef<{\n [key: string]: Wallet | undefined;\n }>({});\n\n /*\n * If `wallet` hasn't been added to `availableWallets`,\n * Get a instance of `Wallet` and save the refrence in `availableWallets`.\n * Otherwise, return the already created instance.\n */\n function updater(wallet: {\n actions: WalletActions;\n config: WalletConfig;\n }): Wallet {\n const type = wallet.config.type;\n // We only update, if there is no instance available.\n if (typeof availableWallets.current[type] === 'undefined') {\n availableWallets.current[type] = new Wallet(\n {\n config: wallet.config,\n handler: onChangeState,\n },\n wallet.actions\n );\n }\n\n return availableWallets.current[type]!;\n }\n\n return updater;\n}\n\nexport function useWallets(): ProviderContext {\n const context = useContext(WalletContext);\n if (!context) {\n throw Error('useWallet can only be used within the Provider component');\n }\n return context;\n}\n", "import type { ProviderProps } from './types.js';\n\nimport { useEffect, useRef } from 'react';\n\nimport { shouldTryAutoConnect } from './utils.js';\n\nexport function useAutoConnect(\n props: Pick<ProviderProps, 'allBlockChains' | 'autoConnect'> & {\n /**\n * A function to run autoConnect on instances\n */\n autoConnectHandler: () => void;\n }\n) {\n const autoConnectInitiated = useRef(false);\n\n useEffect(() => {\n if (shouldTryAutoConnect(props) && !autoConnectInitiated.current) {\n autoConnectInitiated.current = true;\n props.autoConnectHandler();\n }\n }, [props.autoConnect, props.allBlockChains]);\n}\n", "import type { AllProxiedNamespaces } from './types.js';\nimport type {\n Accounts,\n AccountsWithActiveChain,\n} from '@rango-dev/wallets-core/namespaces/common';\nimport type { Result } from 'ts-results';\n\nimport { legacyFormatAddressWithNetwork as formatAddressWithNetwork } from '@rango-dev/wallets-core/legacy';\nimport { CAIP_BITCOIN_CHAIN_ID } from '@rango-dev/wallets-core/namespaces/utxo';\nimport { CAIP } from '@rango-dev/wallets-core/utils';\nimport { Err, Ok } from 'ts-results';\n\nexport function mapCaipNamespaceToLegacyNetworkName(\n chainId: CAIP.ChainIdParams | string\n): string {\n if (typeof chainId === 'string') {\n return chainId;\n }\n const useNamespaceAsNetworkFor = ['solana'];\n\n if (useNamespaceAsNetworkFor.includes(chainId.namespace.toLowerCase())) {\n return chainId.namespace.toUpperCase();\n }\n\n if (chainId.namespace.toLowerCase() === 'eip155') {\n return 'ETH';\n } else if (chainId.reference === CAIP_BITCOIN_CHAIN_ID) {\n return 'BTC';\n }\n\n if (chainId.namespace === 'sui') {\n return chainId.reference.toUpperCase();\n }\n\n return chainId.reference;\n}\n\n/**\n * CAIP's accountId has a format like this: eip155:1:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb\n * Legacy format is something like this: ETH:0xab16a96D359eC26a11e2C2b3d8f8B8942d5Bfcdb\n * This function will try to convert this two format.\n *\n * @see https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md\n */\nexport function fromAccountIdToLegacyAddressFormat(account: string): string {\n const { chainId, address } = CAIP.AccountId.parse(account);\n const network = mapCaipNamespaceToLegacyNetworkName(chainId);\n return formatAddressWithNetwork(address, network);\n}\n\n/**\n * Getting a list of (lazy) promises and run them one after another.\n */\n\nexport async function runSequentiallyWithoutFailure<R>(\n promises: Array<() => Promise<R>>\n): Promise<Result<R, unknown>[]> {\n return promises.reduce(async (prevPromise, task) => {\n const previousResults = await prevPromise;\n try {\n const taskResult = await task();\n return [...previousResults, new Ok(taskResult)];\n } catch (error) {\n return [...previousResults, new Err(error)];\n }\n }, Promise.resolve<Result<R, unknown>[]>([]));\n}\n\nexport function isConnectResultEvm(\n result: Awaited<ReturnType<AllProxiedNamespaces['connect']>>\n): result is AccountsWithActiveChain {\n return typeof result === 'object' && !Array.isArray(result);\n}\n\nexport function isConnectResultSolana(\n result: Awaited<ReturnType<AllProxiedNamespaces['connect']>>\n): result is Accounts {\n return Array.isArray(result);\n}\n\ntype QueueItem<T> = {\n task: () => Promise<T>;\n resolve: (value: Result<T, unknown>) => void;\n key: string;\n};\n/**\n * Creates a queue manager that ensures sequential execution of tasks by key.\n * When multiple tasks with the same key are queued, they are executed one at a time\n * in the order they were added. This prevents race conditions and ensures\n * predictable task execution order.\n *\n */\nexport function createQueue(options?: {\n onError?: (\n error: unknown,\n actions: {\n removeCurrentKeyFromQueue: () => void;\n }\n ) => void;\n}) {\n const processingKeys = new Set<string>();\n let queue: QueueItem<unknown>[] = [];\n\n const removeKeyFromQueue = (\n key: string,\n result: Result<unknown, unknown>\n ) => {\n queue = queue.filter((q) => {\n if (q.key !== key) {\n return true;\n }\n q.resolve(result);\n return false;\n });\n };\n\n const processQueue = async () => {\n const currentItem = queue.find((item) => !processingKeys.has(item.key));\n if (!currentItem) {\n return;\n }\n\n const { task, resolve, key } = currentItem;\n processingKeys.add(key);\n\n try {\n const result = await task();\n resolve(new Ok(result));\n } catch (error) {\n if (options?.onError) {\n options.onError(error, {\n removeCurrentKeyFromQueue: () =>\n removeKeyFromQueue(key, new Err(error)),\n });\n }\n\n resolve(new Err(error));\n } finally {\n const indexOfCurrentItem = queue.findIndex((item) => item.key === key);\n if (indexOfCurrentItem >= 0) {\n queue.splice(indexOfCurrentItem, 1);\n }\n processingKeys.delete(key);\n void processQueue();\n }\n };\n\n const queueTask = async <T>(\n task: () => Promise<T>,\n key: string\n ): Promise<Result<T, unknown>> =>\n new Promise((resolve) => {\n queue.push({\n task,\n resolve: resolve as (value: Result<unknown, unknown>) => void,\n key,\n });\n void processQueue();\n });\n\n return queueTask;\n}\n", "import type { AllProxiedNamespaces, ExtensionLink } from './types.js';\nimport type { ProviderContext, Providers } from '../index.js';\nimport type { Provider } from '@rango-dev/wallets-core';\nimport type { LegacyNamespaceInputForConnect } from '@rango-dev/wallets-core/legacy';\nimport type { VersionedProviders } from '@rango-dev/wallets-core/utils';\n\nimport { utils } from '@rango-dev/wallets-core/namespaces/evm';\nimport { type WalletInfo } from '@rango-dev/wallets-shared';\nimport { useEffect, useRef, useState } from 'react';\nimport { Ok, Result } from 'ts-results';\n\nimport {\n type ConnectResult,\n HUB_LAST_CONNECTED_WALLETS,\n type ProviderProps,\n} from '../legacy/mod.js';\nimport { useAutoConnect } from '../legacy/useAutoConnect.js';\n\nimport { autoConnect } from './autoConnect.js';\nimport { createQueue, fromAccountIdToLegacyAddressFormat } from './helpers.js';\nimport { LastConnectedWalletsFromStorage } from './lastConnectedWallets.js';\nimport { useHubRefs } from './useHubRefs.js';\nimport {\n getLegacyProvider,\n getSupportedChainsFromProvider,\n mapHubEventsToLegacy,\n transformHubResultToLegacyResult,\n tryConvertNamespaceNetworkToChainInfo,\n} from './utils.js';\n\nexport type UseAdapterParams = Omit<ProviderProps, 'providers'> & {\n providers: Provider[];\n /** This is only will be used to access some parts of the legacy provider that doesn't exists in Hub. */\n allVersionedProviders: VersionedProviders[];\n};\n\nexport function useHubAdapter(params: UseAdapterParams): ProviderContext {\n const { getStore, getHub } = useHubRefs(params.providers);\n const [, rerender] = useState(0);\n // useEffect will run `subscribe` once, so we need a reference and mutate the value if it's changes.\n const dataRef = useRef({\n onUpdateState: params.onUpdateState,\n allVersionedProviders: params.allVersionedProviders,\n allBlockChains: params.allBlockChains,\n });\n\n const queueTask = createQueue({\n onError: (error, actions) => {\n if (utils.isUserRejectionError(error)) {\n actions.removeCurrentKeyFromQueue();\n }\n },\n });\n\n useEffect(() => {\n dataRef.current = {\n onUpdateState: params.onUpdateState,\n allVersionedProviders: params.allVersionedProviders,\n allBlockChains: params.allBlockChains,\n };\n }, [params]);\n\n // Initialize instances\n useEffect(() => {\n const runOnInit = () => {\n getHub().init();\n\n rerender((currentRender) => currentRender + 1);\n };\n\n // Then will call init whenever page is ready.\n const initHubWhenPageIsReady = (event: Event) => {\n // Then will call init whenever page is ready.\n if (\n event.target &&\n (event.target as Document).readyState === 'complete'\n ) {\n runOnInit();\n document.removeEventListener(\n 'readystatechange',\n initHubWhenPageIsReady\n );\n }\n };\n\n // Try to run, maybe it's ready.\n runOnInit();\n\n /*\n * Try again when the page has been completely loaded.\n * Some of wallets, take some time to be fully injected and loaded.\n */\n document.addEventListener('readystatechange', initHubWhenPageIsReady);\n\n getStore()\n .subscribe((event) => {\n if (dataRef.current.onUpdateState) {\n try {\n mapHubEventsToLegacy(\n getHub(),\n event,\n dataRef.current.onUpdateState,\n dataRef.current.allBlockChains\n );\n } catch (e) {\n console.error(e);\n }\n }\n rerender((currentRender) => currentRender + 1);\n })\n .flushEvents();\n }, []);\n\n useAutoConnect({\n autoConnect: params.autoConnect,\n allBlockChains: params.allBlockChains,\n autoConnectHandler: () => {\n void autoConnect({\n allBlockChains: params.allBlockChains,\n getHub,\n wallets: params.configs?.wallets,\n });\n },\n });\n\n const lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n HUB_LAST_CONNECTED_WALLETS\n );\n\n const api: ProviderContext = {\n canSwitchNetworkTo(type, network, namespace) {\n const provider = getHub().get(type);\n\n if (!provider) {\n throw new Error(\n `You should add ${type} to provider first then call 'canSwitchNetworkTo'.`\n );\n }\n\n if (!namespace) {\n throw new Error(\n 'Passing namespace to `canSwitchNetworkTo` is required.'\n );\n }\n\n const proxiedNamespace = provider.findByNamespace(namespace.namespace);\n if (!proxiedNamespace) {\n throw new Error(\n `We couldn't find any matched namespace on your request provider. (requested namespace: ${namespace.namespace})`\n );\n }\n if (!('canSwitchNetwork' in proxiedNamespace)) {\n return false;\n }\n const namespacesProperty = provider\n .info()\n ?.metadata?.properties?.find(\n (property) => property.name === 'namespaces'\n );\n\n if (!dataRef.current.allBlockChains) {\n throw new Error(`Blockchains are not available`);\n }\n const providerSupportedChainsOfNamespace = namespacesProperty?.value.data\n .find(\n (providerNamespace) => providerNamespace.value === namespace.namespace\n )\n ?.getSupportedChains(dataRef.current.allBlockChains);\n\n if (!providerSupportedChainsOfNamespace) {\n throw new Error(\n `NamespaceMeta is not defined for requested namespace: ${namespace.namespace}`\n );\n }\n\n return proxiedNamespace.canSwitchNetwork({\n network,\n supportedChains: providerSupportedChainsOfNamespace,\n });\n },\n async connect(type, namespaces) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(\n `You should add ${type} to provider first then call 'connect'.`\n );\n }\n\n if (!namespaces) {\n throw new Error('Passing namespace to `connect` is required.');\n }\n\n // Check `namespace` and look into hub to see how it can match given namespace to hub namespace.\n const targetNamespaces: [\n LegacyNamespaceInputForConnect,\n AllProxiedNamespaces\n ][] = [];\n namespaces.forEach((namespace) => {\n const targetNamespace = namespace.namespace;\n\n const result = wallet.findByNamespace(targetNamespace);\n if (!result) {\n throw new Error(\n `We couldn't find any provider matched with your request namespace. (requested namespace: ${namespace.namespace})`\n );\n }\n\n targetNamespaces.push([namespace, result]);\n });\n\n // Try to run `connect` on matched namespaces\n const connectResultFromTargetNamespaces = targetNamespaces.map(\n async ([namespaceInput, namespace]) => {\n const network = tryConvertNamespaceNetworkToChainInfo(\n namespaceInput,\n params.allBlockChains || []\n );\n\n /*\n * `connect` can have different interfaces (e.g. Solana -> .connect(), EVM -> .connect(\"0x1\") ),\n * our assumption here is all the `connect` hasn't chain or if they have, they will accept it in first argument.\n * By this assumption, always passing a chain should be problematic since it will be ignored if the namespace's `connect` hasn't chain.\n */\n const connectNamespaceProcess = async () =>\n namespace\n .connect(network)\n .then<ConnectResult>(transformHubResultToLegacyResult)\n .then((connectResult) => {\n return {\n response: connectResult,\n input: {\n namespace: namespaceInput.namespace,\n network: namespaceInput.network,\n supportsEagerConnect: 'canEagerConnect' in namespace,\n },\n };\n });\n return queueTask(connectNamespaceProcess, type);\n }\n );\n\n /*\n * We need to connect to namespace one after another, sending multiple requests at the same time may be failed.\n * e.g. when wallet popup opens and asking for the password from the user, it should be resolved first, then other request will be resolved.\n */\n const connectResultWithLegacyFormat = await Promise.all(\n connectResultFromTargetNamespaces\n );\n\n // Keeping only namespaces that connected successfully and support eager connect, then we'll store them on storage for auto connect functionality.\n const successfullyConnectedSupportingEagerConnectNamespaces =\n connectResultWithLegacyFormat\n .filter(<T, E>(result: Result<T, E>): result is Ok<T> => result.ok)\n .filter((result) => result.val.input.supportsEagerConnect)\n .map((result) => ({\n namespace: result.val.input.namespace,\n network: result.val.input.network,\n }));\n\n if (successfullyConnectedSupportingEagerConnectNamespaces.length > 0) {\n lastConnectedWalletsFromStorage.addWallet(\n type,\n successfullyConnectedSupportingEagerConnectNamespaces\n );\n }\n\n // Getting rid of `input` from Result\n const connectResults = connectResultWithLegacyFormat.map((result) =>\n result.andThen((okResult) => new Ok(okResult.response))\n );\n\n const allResult = Result.all(...connectResults);\n if (allResult.err) {\n throw allResult.val;\n }\n\n return allResult.unwrap();\n },\n async disconnect(type, namespaces) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(\n `You should add ${type} to provider first then call 'disconnect'.`\n );\n }\n\n wallet.getAll().forEach((namespace) => {\n const namespaceShouldBeDisconnected =\n !namespaces || namespaces.includes(namespace.namespaceId);\n const namespaceIsConnected = namespace.state()[0]().connected;\n if (namespaceShouldBeDisconnected && namespaceIsConnected) {\n return namespace.disconnect();\n }\n });\n\n if (params.autoConnect) {\n if (namespaces) {\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n type,\n namespaces\n );\n } else {\n lastConnectedWalletsFromStorage.removeWallets([type]);\n }\n }\n },\n async disconnectAll() {\n const disconnectPromises: Promise<void>[] = Array.from(\n getHub().getAll().values()\n ).map(async (provider) => this.disconnect(provider.id));\n\n return await Promise.allSettled(disconnectPromises);\n },\n async getSigners(type) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n const info = wallet.info();\n if (!info) {\n throw new Error('Your provider should have required `info`.');\n }\n\n const providerProperties = info.metadata.properties;\n\n const signerProperty = providerProperties?.find(\n (property) => property.name === 'signers'\n );\n if (!signerProperty) {\n throw new Error('Your provider should contain signers property.');\n }\n\n return signerProperty.value.getSigners();\n },\n getWalletInfo(type) {\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(`You should add ${type} to provider first.`);\n }\n\n const info = wallet.info();\n if (!info) {\n throw new Error('Your provider should have required `info`.');\n }\n\n const installLink: Exclude<WalletInfo['installLink'], string> = {\n DEFAULT: '',\n };\n\n const { metadata, deepLink } = info;\n const { extensions } = metadata;\n // `extensions` in legacy format was uppercase and also `DEFAULT` was used instead of `homepage`\n Object.keys(extensions).forEach((k) => {\n const key = k as ExtensionLink;\n\n if (key === 'homepage') {\n installLink.DEFAULT = extensions[key] || '';\n }\n\n const allowedKeys: ExtensionLink[] = [\n 'firefox',\n 'chrome',\n 'brave',\n 'edge',\n ];\n if (allowedKeys.includes(key)) {\n const upperCasedKey = key.toUpperCase() as keyof Exclude<\n WalletInfo['installLink'],\n string\n >;\n installLink[upperCasedKey] = extensions[key] || '';\n }\n });\n\n const providerProperties = metadata.properties;\n\n const namespacesProperty = providerProperties?.find(\n (property) => property.name === 'namespaces'\n );\n const derivationPathProperty = providerProperties?.find(\n (property) => property.name === 'derivationPath'\n );\n const detailsProperty = providerProperties?.find(\n (property) => property.name === 'details'\n );\n\n return {\n name: metadata.name,\n img: metadata.icon,\n installLink: installLink,\n // We don't have this values anymore, fill them with some values that communicate this.\n color: 'red',\n supportedChains: getSupportedChainsFromProvider(\n wallet,\n dataRef.current.allBlockChains\n ),\n isContractWallet: detailsProperty?.value?.isContractWallet,\n mobileWallet: detailsProperty?.value?.mobileWallet,\n // if set to false here, it will not show the wallet in mobile in anyways. to be compatible with old behavior, undefined is more appropirate.\n showOnMobile: detailsProperty?.value?.showOnMobile,\n needsNamespace: namespacesProperty?.value,\n needsDerivationPath: derivationPathProperty?.value,\n generateDeepLink: deepLink,\n isHub: true,\n properties: metadata.properties,\n };\n },\n providers() {\n const output: Providers = {};\n\n Array.from(getHub().getAll().keys()).forEach((id) => {\n try {\n const provider = getLegacyProvider(params.allVersionedProviders, id);\n output[id] = provider.getInstance();\n } catch (e) {\n console.warn(e);\n }\n });\n\n return output;\n },\n state(type) {\n const hubState = getHub().state();\n const wallet = getHub().get(type);\n const walletState = hubState[type];\n\n if (!walletState || !wallet) {\n throw new Error(\n `It seems your requested provider doesn't exist in hub. Provider Id: ${type}`\n );\n }\n\n const accounts = walletState.namespaces\n .filter((namespace) => namespace.connected)\n .flatMap((namespace) =>\n namespace.accounts?.map(fromAccountIdToLegacyAddressFormat)\n )\n .filter((account): account is string => !!account);\n\n const namespacesState = new Map(\n Array.from(wallet.getAll(), ([_, value]) => [\n value.namespaceId,\n value.state()[0](),\n ])\n );\n\n const coreState = {\n connected: walletState.connected,\n connecting: walletState.connecting,\n installed: walletState.installed,\n reachable: true,\n accounts: accounts,\n network: null,\n namespaces: namespacesState,\n };\n return coreState;\n },\n suggestAndConnect(_type, _network): never {\n throw new Error('`suggestAndConnect` is not implemented');\n },\n };\n\n return api;\n}\n", "import type { AllProxiedNamespaces } from './types.js';\nimport type { UseAdapterParams } from './useHubAdapter.js';\nimport type { Hub, Provider } from '@rango-dev/wallets-core';\nimport type {\n LegacyNamespaceInputForConnect,\n LegacyProviderInterface,\n} from '@rango-dev/wallets-core/legacy';\nimport type { Namespace } from '@rango-dev/wallets-core/namespaces/common';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { legacyIsEvmNamespace } from '@rango-dev/wallets-core/legacy';\nimport { Result } from 'ts-results';\n\nimport { HUB_LAST_CONNECTED_WALLETS } from '../legacy/mod.js';\n\nimport { runSequentiallyWithoutFailure } from './helpers.js';\nimport { LastConnectedWalletsFromStorage } from './lastConnectedWallets.js';\nimport { convertNamespaceNetworkToEvmChainId } from './utils.js';\n\n// Getting connected wallets from storage\nconst lastConnectedWalletsFromStorage = new LastConnectedWalletsFromStorage(\n HUB_LAST_CONNECTED_WALLETS\n);\n\n/**\n * Run `.connect` action on some selected namespaces (passed as param) for a provider.\n */\nasync function eagerConnect(\n type: string,\n namespacesInput: LegacyNamespaceInputForConnect[] | undefined,\n params: {\n getHub: () => Hub;\n allBlockChains: UseAdapterParams['allBlockChains'];\n }\n) {\n const { getHub, allBlockChains } = params;\n const wallet = getHub().get(type);\n if (!wallet) {\n throw new Error(\n `You should add ${type} to provider first then call 'connect'.`\n );\n }\n\n if (!namespacesInput) {\n throw new Error('Passing namespace to `connect` is required. ');\n }\n\n const targetNamespaces: [\n LegacyNamespaceInputForConnect,\n AllProxiedNamespaces\n ][] = [];\n namespacesInput.forEach((namespaceInput) => {\n const targetNamespace: Namespace = namespaceInput.namespace;\n\n const result = wallet.findByNamespace(targetNamespace);\n\n if (!result) {\n throw new Error(\n `We couldn't find any provider matched with your request namespace. (requested namespace: ${namespaceInput.namespace})`\n );\n }\n\n targetNamespaces.push([namespaceInput, result]);\n });\n\n const connectNamespacesPromises = targetNamespaces.map(\n ([info, namespace]) => {\n const evmChain = legacyIsEvmNamespace(info)\n ? convertNamespaceNetworkToEvmChainId(info, allBlockChains || [])\n : undefined;\n const chain = evmChain || info.network;\n\n return async () =>\n await namespace.connect(chain).catch((e) => {\n /*\n * Since we check for connect failures using `instanceof Error`\n * this check is added here to make sure the thrown error always is an instance of `Error`\n */\n if (e instanceof Error) {\n throw e;\n }\n throw new Error(e);\n });\n }\n );\n\n /**\n * Sometimes calling methods on a instance in parallel, would cause an error in wallet.\n * We are running a method at a time to make sure we are covering this.\n * e.g. when we are trying to eagerConnect evm and solana on phantom at the same time, the last namespace throw an error.\n */\n const connectNamespacesResult = await runSequentiallyWithoutFailure(\n connectNamespacesPromises\n );\n\n const failedNamespaces: LegacyNamespaceInputForConnect[] = targetNamespaces\n .filter((_, index) => connectNamespacesResult[index].err)\n .map((targetNamespace) => targetNamespace[0]);\n\n if (failedNamespaces.length > 0) {\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n type,\n failedNamespaces.map((namespace) => namespace.namespace)\n );\n }\n\n const atLeastOneNamespaceConnectedSuccessfully = connectNamespacesResult.some(\n (result) => result.ok\n );\n if (!atLeastOneNamespaceConnectedSuccessfully) {\n throw new Error(`No namespace connected for ${type}`);\n }\n return Result.all(\n ...connectNamespacesResult.filter((result) => result.ok)\n ).unwrap();\n}\n\n/**\n * Run `.canEagerConnect` action on some selected namespaces of a wallet.\n */\nasync function tryRunCanEagerConnect(\n namespaces: LegacyNamespaceInputForConnect[],\n wallet: Provider\n): Promise<{\n successNamespaces: LegacyNamespaceInputForConnect[];\n failedNamespaces: LegacyNamespaceInputForConnect[];\n}> {\n const foundNamespaces: LegacyNamespaceInputForConnect[] = [];\n const successNamespaces: LegacyNamespaceInputForConnect[] = [];\n const failedNamespaces: LegacyNamespaceInputForConnect[] = [];\n const canEagerConnectPromises: (() => Promise<boolean>)[] = [];\n\n // 1. Try find namespace instances and create canEagerConnect promises\n namespaces.forEach((namespace) => {\n const namespaceInstance = wallet.findByNamespace(namespace.namespace);\n if (namespaceInstance) {\n foundNamespaces.push(namespace);\n canEagerConnectPromises.push(\n async () => await namespaceInstance.canEagerConnect()\n );\n } else {\n failedNamespaces.push(namespace);\n }\n });\n\n // 2. Run canEagerConnect sequentially on namespaces\n const canEagerConnectResults = await runSequentiallyWithoutFailure(\n canEagerConnectPromises\n );\n\n // 3. Separate success and failed namespaces based on canEagerConnect result\n foundNamespaces.forEach((namespace, index) => {\n if (canEagerConnectResults[index].ok && canEagerConnectResults[index].val) {\n successNamespaces.push(namespace);\n } else {\n failedNamespaces.push(namespace);\n }\n });\n\n return { successNamespaces, failedNamespaces };\n}\n\n/*\n * Get last connected wallets and last connected namespaces for each of them from storage\n * Then run `.connect` on each namespace if `.canEagerConnect` returns true.\n */\nexport async function autoConnect(deps: {\n getHub: () => Hub;\n allBlockChains: UseAdapterParams['allBlockChains'];\n wallets?: (WalletType | LegacyProviderInterface)[];\n}): Promise<void> {\n const { getHub, allBlockChains, wallets } = deps;\n const lastConnectedWallets = lastConnectedWalletsFromStorage.list();\n const walletIds = Object.keys(lastConnectedWallets);\n\n const walletsToRemoveFromPersistence: string[] = [];\n\n if (walletIds.length) {\n const eagerConnectQueue: Promise<unknown>[] = [];\n\n // Run `.connect` if `.canEagerConnect` returns `true`.\n walletIds.forEach(async (providerName) => {\n if (wallets && !wallets.includes(providerName)) {\n console.warn(\n 'Trying to run auto connect for a wallet which is not included in config. Desired wallet:',\n providerName\n );\n walletsToRemoveFromPersistence.push(providerName);\n return;\n }\n\n const wallet = getHub().get(providerName);\n\n const lastConnectedNamespaces: LegacyNamespaceInputForConnect[] =\n lastConnectedWallets[providerName].map((namespace) => ({\n namespace: namespace.namespace,\n network: namespace.network,\n }));\n\n if (!lastConnectedNamespaces.length || !wallet) {\n walletsToRemoveFromPersistence.push(providerName);\n return;\n }\n\n const { successNamespaces, failedNamespaces } =\n await tryRunCanEagerConnect(lastConnectedNamespaces, wallet);\n\n if (!successNamespaces.length) {\n walletsToRemoveFromPersistence.push(providerName);\n return;\n } else if (failedNamespaces.length) {\n lastConnectedWalletsFromStorage.removeNamespacesFromWallet(\n wallet.id,\n failedNamespaces.map((namespace) => namespace.namespace)\n );\n }\n eagerConnectQueue.push(\n eagerConnect(providerName, successNamespaces, {\n allBlockChains,\n getHub,\n }).catch((error) => console.warn(error))\n );\n });\n\n lastConnectedWalletsFromStorage.removeWallets(\n walletsToRemoveFromPersistence\n );\n\n await Promise.all(eagerConnectQueue);\n }\n}\n", "import type { Provider, Store } from '@rango-dev/wallets-core';\n\nimport { createStore, Hub } from '@rango-dev/wallets-core';\nimport { useRef } from 'react';\n\nimport { synchronizeHubWithConfigProviders } from './utils.js';\n\nexport function useHubRefs(providers: Provider[]) {\n const store = useRef<Store | null>(null);\n\n const hub = useRef<Hub | null>(null);\n\n function createHub() {\n const createdHub = new Hub({\n store: getStore(),\n });\n /*\n * First add providers to hub\n * This helps to `getWalletInfo` be usable, before initialize.\n */\n providers.forEach((provider) => {\n createdHub.add(provider.id, provider);\n });\n hub.current = createdHub;\n return createdHub;\n }\n\n // https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents\n function getStore() {\n if (store.current !== null) {\n return store.current;\n }\n const createdStore = createStore();\n store.current = createdStore;\n return createdStore;\n }\n\n function getHub(): Hub {\n const hubProviders = hub.current?.getAll();\n\n if (!hub.current || !hubProviders) {\n return createHub();\n }\n\n synchronizeHubWithConfigProviders(hub.current, providers);\n return hub.current;\n }\n\n return { getStore, getHub };\n}\n"],
|
|
5
5
|
"mappings": "+EASA,OAAS,gBAAgBA,OAAc,iCACvC,MAAwC,gCACxC,OAAS,eAAAC,MAAmB,gCAC5B,OAEE,0CAAAC,OACK,4BACP,OAA8B,mBAAAC,OAAuB,cChB9C,IAAMC,EAAgC,yBAChCC,EAA6B,gCCC1C,OAAS,iBAAAC,MAAqB,QAE9B,IAAMC,EAAsB,uCACtBC,EAAkC,CACtC,MAAM,SAAU,CACd,MAAM,IAAI,MAAMD,CAAmB,CACrC,EACA,MAAM,YAAa,CACjB,MAAM,IAAI,MAAMA,CAAmB,CACrC,EACA,MAAM,eAAgB,CACpB,MAAM,IAAI,MAAMA,CAAmB,CACrC,EACA,MAAM,mBAAoB,CACxB,MAAM,IAAI,MAAMA,CAAmB,CACrC,EACA,OAAQ,CACN,MAAM,IAAI,MAAMA,CAAmB,CACrC,EACA,oBAAqB,CACnB,MAAM,IAAI,MAAMA,CAAmB,CACrC,EACA,WAAY,CACV,MAAM,IAAI,MAAMA,CAAmB,CACrC,EACA,eAAgB,CACd,MAAM,IAAI,MAAMA,CAAmB,CACrC,EACA,YAAa,CACX,MAAM,IAAI,MAAMA,CAAmB,CACrC,CACF,EAEaE,EAAgBH,EAA+BE,CAAc,EC/B1E,OAAS,aAAAE,GAAW,cAAAC,OAAkB,QCFtC,OAAS,aAAAC,MAAiB,iCAsBnB,IAAMC,EAAN,KAAsC,CAxB7C,MAwB6C,CAAAC,EAAA,wCAC3CC,GAEA,YAAYC,EAAoB,CAC9B,KAAKD,GAAcC,CACrB,CAEA,UAAUC,EAAoBC,EAAoC,CAChE,GAAI,KAAKH,KAAgBI,EACvB,OAAO,KAAKC,GAAgBH,EAAYC,CAAU,EAC7C,GAAI,KAAKH,KAAgBM,EAC9B,OAAO,KAAKC,GAAmBL,CAAU,EAE3C,MAAM,IAAI,MAAM,iBAAiB,CACnC,CACA,cAAcM,EAA8B,CAC1C,GAAI,KAAKR,KAAgBI,EACvB,OAAO,KAAKK,GAAsBD,CAAW,EACxC,GAAI,KAAKR,KAAgBM,EAC9B,OAAO,KAAKI,GAAyBF,CAAW,EAElD,MAAM,IAAI,MAAM,iBAAiB,CACnC,CACA,MAAoC,CAClC,GAAI,KAAKR,KAAgBI,EACvB,OAAO,KAAKO,GAAa,EACpB,GAAI,KAAKX,KAAgBM,EAC9B,OAAO,KAAKM,GAAgB,EAE9B,MAAM,IAAI,MAAM,iBAAiB,CACnC,CACA,2BAA2BV,EAAoBW,EAAwB,CACrE,GAAI,KAAKb,KAAgBI,EACvB,OAAO,KAAKU,GAA8BZ,EAAYW,CAAY,EAEpE,MAAM,IAAI,MAAM,iBAAiB,CACnC,CAEAD,IAA+C,CAE7C,IAAMG,EADY,IAAIC,EAA6C,EAEvD,QAAQV,CAA6B,GAAK,CAAC,EACjDW,EAAsC,CAAC,EAC7C,OAAAF,EAAqB,QAASG,GAAa,CAEzCD,EAAOC,CAAQ,EAAI,CAAC,CACtB,CAAC,EACMD,CACT,CACAN,IAA4C,CAI1C,OAHkB,IAAIK,EAAuC,EAEjD,QAAQZ,CAA0B,GAAK,CAAC,CAEtD,CACAC,GAAgBH,EAAoBC,EAAoC,CACtE,IAAMgB,EAAU,IAAIH,EACdI,EAAeD,EAAQ,QAAQ,KAAKnB,EAAW,GAAK,CAAC,EAEvDqB,EAAsBlB,EAG1B,GAAMiB,EAAalB,CAAU,EAAG,CAC9B,IAAMoB,EAAmBF,EAAalB,CAAU,EAChDmB,EAAsBC,EAAiB,OACrCnB,EAAW,OACRoB,GACC,CAACD,EAAiB,KACfE,GACCA,EAAgB,YAAcD,EAAU,SAC5C,CACJ,CACF,CACF,CAEAJ,EAAQ,QAAQ,KAAKnB,GAAa,CAChC,GAAGoB,EACH,CAAClB,CAAU,EAAGmB,CAChB,CAAC,CACH,CACAd,GAAmBL,EAA0B,CAC3C,IAAMiB,EAAU,IAAIH,EACdI,EAAeD,EAAQ,QAAQ,KAAKnB,EAAW,GAAK,CAAC,EAE3DmB,EAAQ,QACNb,EACAc,EAAa,OAAOlB,CAAU,CAChC,CACF,CACAO,GAAsBD,EAA8B,CAClD,IAAMiB,EAAY,IAAIT,EAChBI,EAAeK,EAAU,QAAQ,KAAKzB,EAAW,GAAK,CAAC,EAG7D,GAAI,CAACQ,EAAa,CAChBiB,EAAU,QAAQ,KAAKzB,GAAa,CAAC,CAAC,EACtC,MACF,CAGAQ,EAAY,QAASN,GAAe,CAC9BkB,EAAalB,CAAU,GACzB,OAAOkB,EAAalB,CAAU,CAElC,CAAC,EAEDuB,EAAU,QAAQ,KAAKzB,GAAaoB,CAAY,CAClD,CACAN,GACEZ,EACAW,EACM,CAKN,IAAMa,GAJY,IAAIV,EAAuC,EAC9B,QAAQ,KAAKhB,EAAW,GAAK,CAAC,GAEdE,CAAU,GACA,OACtDqB,GAAc,CAACV,EAAa,SAASU,EAAU,SAAS,CAC3D,EAEA,KAAKd,GAAsB,CAACP,CAAU,CAAC,EACnCwB,GAAuB,OAAS,GAClC,KAAKrB,GAAgBH,EAAYwB,CAAqB,CAE1D,CACAhB,GAAyBF,EAA8B,CACrD,IAAMiB,EAAY,IAAIT,EAChBI,EAAeK,EAAU,QAAQ,KAAKzB,EAAW,GAAK,CAAC,EAG7D,GAAI,CAACQ,EAAa,CAChBiB,EAAU,QAAQ,KAAKzB,GAAa,CAAC,CAAC,EACtC,MACF,CAGAyB,EAAU,QACRnB,EACAc,EAAa,OAAQO,GAAW,CAACnB,EAAY,SAASmB,CAAM,CAAC,CAC/D,CACF,CACF,ECxJA,OAAS,aAAAC,MAAiB,iCCV1B,OAAS,gBAAgBC,MAAc,iCACvC,OAAS,cAAAC,EAAY,UAAAC,MAAc,QCFnC,OAAS,aAAAC,EAAW,UAAAC,OAAc,QCKlC,OAAS,kCAAkCC,OAAgC,iCAC3E,OAAS,yBAAAC,OAA6B,0CACtC,OAAS,QAAAC,OAAY,gCACrB,OAAS,OAAAC,GAAK,MAAAC,OAAU,aRwDxB,IAAMC,GAAkC,IAAIC,EAC1CC,CACF,EA+KO,SAASC,EACdC,EAC2B,CAC3B,IAAMC,EAAiB,QAEjBC,EAA6C,CAAC,EAEpD,OAAAF,EAAa,QAASG,GAAa,CACjC,IAAMC,EAASC,EAAYF,EAAUF,CAAc,EACnDC,EAAgB,KAAKE,EAAO,CAAC,CAAC,CAChC,CAAC,EAEMF,CACT,CAbgBI,EAAAP,EAAA,yBS7OhB,OAAS,SAAAQ,OAAa,yCACtB,MAAgC,4BAChC,OAAS,aAAAC,GAAW,UAAAC,GAAQ,YAAAC,OAAgB,QAC5C,OAAS,MAAAC,GAAI,UAAAC,OAAc,aCC3B,OAAS,wBAAAC,OAA4B,iCACrC,OAAS,UAAAC,OAAc,aASvB,IAAMC,GAAkC,IAAIC,EAC1CC,CACF,ECpBA,OAAS,eAAAC,GAAa,OAAAC,OAAW,0BACjC,OAAS,UAAAC,OAAc",
|
|
6
6
|
"names": ["Events", "pickVersion", "convertEvmBlockchainMetaToEvmChainInfo", "isEvmBlockchain", "LEGACY_LAST_CONNECTED_WALLETS", "HUB_LAST_CONNECTED_WALLETS", "createContext", "defaultErrorMessage", "defaultContext", "WalletContext", "useEffect", "useReducer", "Persistor", "LastConnectedWalletsFromStorage", "__name", "#storageKey", "storageKey", "providerId", "namespaces", "HUB_LAST_CONNECTED_WALLETS", "#addWalletToHub", "LEGACY_LAST_CONNECTED_WALLETS", "#addWalletToLegacy", "providerIds", "#removeWalletsFromHub", "#removeWalletsFromLegacy", "#listFromHub", "#listFromLegacy", "namespaceIds", "#removeNamespaceFromWalletHub", "lastConnectedWallets", "Persistor", "output", "provider", "storage", "storageState", "toBeAddedNamespaces", "storedNamespaces", "namespace", "storedNamespace", "persistor", "newProviderNamespaces", "wallet", "Persistor", "Wallet", "useContext", "useRef", "useEffect", "useRef", "formatAddressWithNetwork", "CAIP_BITCOIN_CHAIN_ID", "CAIP", "Err", "Ok", "lastConnectedWalletsFromStorage", "LastConnectedWalletsFromStorage", "HUB_LAST_CONNECTED_WALLETS", "getAllLegacyProviders", "allProviders", "LEGACY_VERSION", "legacyProviders", "provider", "target", "pickVersion", "__name", "utils", "useEffect", "useRef", "useState", "Ok", "Result", "legacyIsEvmNamespace", "Result", "lastConnectedWalletsFromStorage", "LastConnectedWalletsFromStorage", "HUB_LAST_CONNECTED_WALLETS", "createStore", "Hub", "useRef"]
|
|
7
7
|
}
|
package/dist/hub/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CommonNamespaces, FindProxiedNamespace,
|
|
1
|
+
import type { CommonNamespaces, FindProxiedNamespace, ProviderMetadata } from '@rango-dev/wallets-core';
|
|
2
2
|
export type AllProxiedNamespaces = FindProxiedNamespace<keyof CommonNamespaces, CommonNamespaces>;
|
|
3
|
-
export type ExtensionLink = keyof
|
|
3
|
+
export type ExtensionLink = keyof ProviderMetadata['extensions'];
|
|
4
4
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/hub/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hub/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hub/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,CACrD,MAAM,gBAAgB,EACtB,gBAAgB,CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,YAAY,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHubAdapter.d.ts","sourceRoot":"","sources":["../../src/hub/useHubAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAa,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAOxE,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAe1B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,GAAG;IAChE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,wGAAwG;IACxG,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;CAC7C,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"useHubAdapter.d.ts","sourceRoot":"","sources":["../../src/hub/useHubAdapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAa,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAOxE,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,kBAAkB,CAAC;AAe1B,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,GAAG;IAChE,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,wGAAwG;IACxG,qBAAqB,EAAE,kBAAkB,EAAE,CAAC;CAC7C,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,eAAe,CA4avE"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var ge=Object.defineProperty;var i=(t,e)=>ge(t,"name",{value:e,configurable:!0});import{Persistor as ye}from"@rango-dev/wallets-core/legacy";var v="last-connected-wallets",h="hub-v1-last-connected-wallets";import{Persistor as I}from"@rango-dev/wallets-core/legacy";var C=class{static{i(this,"LastConnectedWalletsFromStorage")}#e;constructor(e){this.#e=e}addWallet(e,o){if(this.#e===h)return this.#t(e,o);if(this.#e===v)return this.#a(e);throw new Error("Not implemented")}removeWallets(e){if(this.#e===h)return this.#r(e);if(this.#e===v)return this.#c(e);throw new Error("Not implemented")}list(){if(this.#e===h)return this.#n();if(this.#e===v)return this.#o();throw new Error("Not implemented")}removeNamespacesFromWallet(e,o){if(this.#e===h)return this.#s(e,o);throw new Error("Not implemented")}#o(){let o=new I().getItem(v)||[],c={};return o.forEach(s=>{c[s]=[]}),c}#n(){return new I().getItem(h)||{}}#t(e,o){let c=new I,s=c.getItem(this.#e)||{},u=o;if(s[e]){let p=s[e];u=p.concat(o.filter(l=>!p.some(r=>r.namespace===l.namespace)))}c.setItem(this.#e,{...s,[e]:u})}#a(e){let o=new I,c=o.getItem(this.#e)||[];o.setItem(v,c.concat(e))}#r(e){let o=new I,c=o.getItem(this.#e)||{};if(!e){o.setItem(this.#e,{});return}e.forEach(s=>{c[s]&&delete c[s]}),o.setItem(this.#e,c)}#s(e,o){let p=(new I().getItem(this.#e)||{})[e]?.filter(l=>!o.includes(l.namespace));this.#r([e]),p?.length>0&&this.#t(e,p)}#c(e){let o=new I,c=o.getItem(this.#e)||[];if(!e){o.setItem(this.#e,[]);return}o.setItem(v,c.filter(s=>!e.includes(s)))}};function ot(t,e){return t.find(o=>o.type===e)||null}i(ot,"choose");var b={connected:!1,connecting:!1,reachable:!1,installed:!1,accounts:null,network:null};function V(t,e){if(e.type==="new_state"){let o=t[e.wallet];return o?{...t,[e.wallet]:{...o,[e.name]:e.value}}:{...t,[e.wallet]:{...b,[e.name]:e.value}}}return t}i(V,"stateReducer");function $(t){return Object.entries(t).filter(([,e])=>e?.connected).map(([e])=>e)}i($,"connectedWallets");function q(t){return Object.entries(t).map(([e])=>e)}i(q,"availableWallets");function G(t){let e=new Map;return t.forEach(o=>{let{config:c,...s}=o;e.set(c.type,{actions:s,config:c})}),e}i(G,"checkWalletProviders");function nt(t){return t?.constructor?.name==="AsyncFunction"}i(nt,"isAsync");function at(t){let{checkInstallation:e=!0}=t.config;return e}i(at,"needsCheckInstallation");async function Q({type:t,walletActions:e,getState:o}){if(e.canEagerConnect){let c=new C(v),u=!!c.list()[t];u&&!o(t).connected&&B(),u||c.addWallet(t,[])}}i(Q,"tryPersistWallet");function K({type:t,walletActions:e}){e.canEagerConnect&&new C(v).removeWallets([t])}i(K,"tryRemoveWalletFromPersistance");function B(){let t=new ye;t.getItem(v)&&t.removeItem(v)}i(B,"clearPersistance");function R(t,e){return i((c,s,u,p,l)=>{t({type:"new_state",wallet:c,name:s,value:u}),e&&e(c,s,u,p,l)},"handler")}i(R,"makeEventHandler");import Ve from"react";import{createContext as ve}from"react";var E="Context hasn't been initialized yet.",we={async connect(){throw new Error(E)},async disconnect(){throw new Error(E)},async disconnectAll(){throw new Error(E)},async suggestAndConnect(){throw new Error(E)},state(){throw new Error(E)},canSwitchNetworkTo(){throw new Error(E)},providers(){throw new Error(E)},getWalletInfo(){throw new Error(E)},getSigners(){throw new Error(E)}},L=ve(we);import{LegacyEvents as W}from"@rango-dev/wallets-core/legacy";import"@rango-dev/wallets-core/utils";import{pickVersion as D}from"@rango-dev/wallets-core/utils";import{convertEvmBlockchainMetaToEvmChainInfo as Ae}from"@rango-dev/wallets-shared";import{isEvmBlockchain as xe}from"rango-types";import{useEffect as F,useReducer as Ne}from"react";async function z(t,e){let o=new C(v),c=o.list(),s=Object.keys(c);if(s.length){let u=[];s.forEach(r=>{let a=t.get(r);if(a){let n=e(a);u.push({walletType:r,eagerConnect:n.eagerConnect.bind(n)})}});let p=await Promise.allSettled(u.map(async({eagerConnect:r})=>r())),l=[];p.forEach((r,a)=>{let{status:n}=r;n==="rejected"&&l.push(u[a].walletType)}),l.length&&o.removeWallets(l)}}i(z,"autoConnect");import{LegacyWallet as he}from"@rango-dev/wallets-core/legacy";import{useContext as Ce,useRef as Pe}from"react";function J(t){let e=Pe({});function o(c){let s=c.config.type;return typeof e.current[s]>"u"&&(e.current[s]=new he({config:c.config,handler:t},c.actions)),e.current[s]}return i(o,"updater"),o}i(J,"useInitializers");function We(){let t=Ce(L);if(!t)throw Error("useWallet can only be used within the Provider component");return t}i(We,"useWallets");import{useEffect as Ee,useRef as ke}from"react";function X(t){return!!t.allBlockChains?.length&&!!t.autoConnect}i(X,"shouldTryAutoConnect");function T(t){let e=ke(!1);Ee(()=>{X(t)&&!e.current&&(e.current=!0,t.autoConnectHandler())},[t.autoConnect,t.allBlockChains])}i(T,"useAutoConnect");function H(t){let[e,o]=Ne(V,{}),c=J(R(o,t.onUpdateState)),s=t.providers,u=G(s);T({allBlockChains:t.allBlockChains,autoConnect:t.autoConnect,autoConnectHandler:async()=>z(u,c)});let p={async connect(l,r){let a=u.get(l);if(!a)throw new Error(`You should add ${l} to provider first.`);let n;r&&r.length>0&&(n=r.find(f=>!!f.network)?.network);let m=await c(a).connect(n,r);return t.autoConnect&&Q({type:l,walletActions:a.actions,getState:p.state}),[m]},async disconnect(l){let r=u.get(l);if(!r)throw new Error(`You should add ${l} to provider first.`);await c(r).disconnect(),t.autoConnect&&K({type:l,walletActions:r.actions})},async disconnectAll(){let l=[];return $(e).forEach(r=>{let a=u.get(r);if(a){let n=c(a);l.push(n.disconnect())}}),t.autoConnect&&B(),await Promise.allSettled(l)},async suggestAndConnect(l,r){let a=u.get(l);if(!a)throw new Error(`You should add ${l} to provider first.`);return await c(a).suggestAndConnect(r)},state(l){return e[l]||b},canSwitchNetworkTo(l,r){let a=u.get(l);if(!a)return!1;let n=c(a);return n.canSwitchNetworkTo?n.canSwitchNetworkTo(r,n.provider):!1},providers(){let l={};return q(e).forEach(r=>{let a=u.get(r);if(a){let n=c(a);l[r]=n.provider}}),l},getWalletInfo(l){let r=u.get(l);if(!r)throw new Error(`You should add ${l} to provider first.`);return r.actions.getWalletInfo(t.allBlockChains||[])},async getSigners(l){let r=u.get(l);if(!r)throw new Error(`You should add ${l} to provider first.`);let a=c(r),n=a.provider;return a.getSigners(n)}};return F(()=>{u.forEach(l=>{let r=c(l),a=i(()=>{r.onInit&&r.onInit()},"runOnInit"),n=i(d=>{d.target&&d.target.readyState==="complete"&&(a(),document.removeEventListener("readystatechange",n))},"initWhenPageIsReady");a(),document.addEventListener("readystatechange",n)})},[]),F(()=>{t.allBlockChains&&u.forEach(r=>{let a=c(r),n=a.getWalletInfo(t.allBlockChains||[]);a.setInfo({supportedBlockchains:n.supportedChains,isContractWallet:!!n.isContractWallet})})},[t.allBlockChains]),F(()=>{u.forEach(l=>{c(l).setHandler(R(o,t.onUpdateState))})},[t.onUpdateState]),p}i(H,"useLegacyProviders");import{legacyFormatAddressWithNetwork as Ie}from"@rango-dev/wallets-core/legacy";import{CAIP_BITCOIN_CHAIN_ID as Se}from"@rango-dev/wallets-core/namespaces/utxo";import{CAIP as Le}from"@rango-dev/wallets-core/utils";import{Err as _,Ok as Z}from"ts-results";function Te(t){return typeof t=="string"?t:["solana"].includes(t.namespace.toLowerCase())?t.namespace.toUpperCase():t.namespace.toLowerCase()==="eip155"?"ETH":t.reference===Se?"BTC":t.namespace==="sui"?t.reference.toUpperCase():t.reference}i(Te,"mapCaipNamespaceToLegacyNetworkName");function A(t){let{chainId:e,address:o}=Le.AccountId.parse(t),c=Te(e);return Ie(o,c)}i(A,"fromAccountIdToLegacyAddressFormat");async function O(t){return t.reduce(async(e,o)=>{let c=await e;try{let s=await o();return[...c,new Z(s)]}catch(s){return[...c,new _(s)]}},Promise.resolve([]))}i(O,"runSequentiallyWithoutFailure");function ee(t){return typeof t=="object"&&!Array.isArray(t)}i(ee,"isConnectResultEvm");function te(t){return Array.isArray(t)}i(te,"isConnectResultSolana");function re(t){let e=new Set,o=[],c=i((p,l)=>{o=o.filter(r=>r.key!==p?!0:(r.resolve(l),!1))},"removeKeyFromQueue"),s=i(async()=>{let p=o.find(n=>!e.has(n.key));if(!p)return;let{task:l,resolve:r,key:a}=p;e.add(a);try{let n=await l();r(new Z(n))}catch(n){t?.onError&&t.onError(n,{removeCurrentKeyFromQueue:()=>c(a,new _(n))}),r(new _(n))}finally{let n=o.findIndex(d=>d.key===a);n>=0&&o.splice(n,1),e.delete(a),s()}},"processQueue");return i(async(p,l)=>new Promise(r=>{o.push({task:p,resolve:r,key:l}),s()}),"queueTask")}i(re,"createQueue");function M(t){let e="0.0.0",o="1.0.0",c=[],s=[];return t.forEach(u=>{try{let p=D(u,o);s.push(p[1])}catch{let p=D(u,e);c.push(p[1])}}),[c,s]}i(M,"separateLegacyAndHubProviders");function k(t,e){return t.find(o=>o.id===e)}i(k,"findProviderByType");var be=new C(h);function j(t,e){return t.info()?.properties?.find(s=>s.name==="namespaces")?.value.data.flatMap(s=>s.getSupportedChains(e||[]))||[]}i(j,"getSupportedChainsFromProvider");function oe(t,e,o,c){let s=t.get(e.provider);if(!s)throw new Error("Currently all the events have assigned to a provider. The event doesn't include one.",{cause:e});let u=e.namespace,p=u?s.findByNamespace(u):void 0,l=null,r=null;if(p){let[m]=p.state();l=m().accounts,r=m().network}let[a]=s.state(),n={connected:a().connected,connecting:a().connecting,installed:a().installed,accounts:l,network:r,reachable:!0},d={supportedBlockchains:j(s,c),isContractWallet:!1,isHub:!0,namespace:u};switch(e.type){case"provider_detected":o(e.provider,W.INSTALLED,!0,n,d);break;case"provider_connecting":o(e.provider,W.CONNECTING,e.value,n,d);break;case"provider_connected":o(e.provider,W.CONNECTED,!0,n,d);break;case"provider_disconnected":o(e.provider,W.PROVIDER_DISCONNECTED,e.provider,n,d),o(e.provider,W.CONNECTED,!1,n,d),o(e.provider,W.ACCOUNTS,null,n,d);break;case"namespace_disconnected":be.removeNamespacesFromWallet(e.provider,[e.namespace]),o(e.provider,W.NAMESPACE_DISCONNECTED,e.namespace,n,{...d,namespace:e.namespace});break;case"namespace_connected":case"namespace_account_switched":{e.type==="namespace_account_switched"&&o(e.provider,W.NAMESPACE_DISCONNECTED,e.namespace,n,d);let m=e.accounts.map(A);o(e.provider,W.ACCOUNTS,m,n,{...d,namespace:e.namespace})}break;case"namespace_network_switched":o(e.provider,W.NETWORK,e.network,n,{...d,namespace:e.namespace});break}}i(oe,"mapHubEventsToLegacy");function ne(t){let e="0.0.0",o=[];return t.forEach(c=>{let s=D(c,e);o.push(s[1])}),o}i(ne,"getAllLegacyProviders");function ae(t,e){let c=ne(t).find(s=>s.config.type===e);if(!c)throw console.warn(`You have a provider that doesn't have legacy provider. It causes some problems since we need some legacy functionality. Provider Id: ${e}`),new Error(`You need to have legacy implementation to use some methods. Provider Id: ${e}`);return c}i(ae,"getLegacyProvider");function Y(t,e){if(!t.network)return;let o=e.filter(xe);return Ae(o)[t.network]}i(Y,"convertNamespaceNetworkToEvmChainId");function se(t,e){return Y(t,e)||t.network}i(se,"tryConvertNamespaceNetworkToChainInfo");function ce(t){return ee(t)?{accounts:t.accounts,network:t.network,provider:void 0}:te(t)?{accounts:t,network:null,provider:void 0}:{accounts:[t],network:null,provider:void 0}}i(ce,"transformHubResultToLegacyResult");function ie(t,e){let o=t.getAll();e.filter(s=>!o.get(s.id)).forEach(s=>{t.add(s.id,s),s.init()}),o.forEach(s=>{e.some(p=>p.id===s.id)||t.remove(s.id)})}i(ie,"synchronizeHubWithConfigProviders");import{utils as De}from"@rango-dev/wallets-core/namespaces/evm";import"@rango-dev/wallets-shared";import{useEffect as ue,useRef as Me,useState as je}from"react";import{Ok as Ye,Result as Ue}from"ts-results";import{legacyIsEvmNamespace as Be}from"@rango-dev/wallets-core/legacy";import{Result as Re}from"ts-results";var x=new C(h);async function Fe(t,e,o){let{getHub:c,allBlockChains:s}=o,u=c().get(t);if(!u)throw new Error(`You should add ${t} to provider first then call 'connect'.`);if(!e)throw new Error("Passing namespace to `connect` is required. ");let p=[];e.forEach(d=>{let m=d.namespace,f=u.findByNamespace(m);if(!f)throw new Error(`We couldn't find any provider matched with your request namespace. (requested namespace: ${d.namespace})`);p.push([d,f])});let l=p.map(([d,m])=>{let P=(Be(d)?Y(d,s||[]):void 0)||d.network;return async()=>await m.connect(P).catch(y=>{throw y instanceof Error?y:new Error(y)})}),r=await O(l),a=p.filter((d,m)=>r[m].err).map(d=>d[0]);if(a.length>0&&x.removeNamespacesFromWallet(t,a.map(d=>d.namespace)),!r.some(d=>d.ok))throw new Error(`No namespace connected for ${t}`);return Re.all(...r.filter(d=>d.ok)).unwrap()}i(Fe,"eagerConnect");async function He(t,e){let o=[],c=[],s=[],u=[];t.forEach(l=>{let r=e.findByNamespace(l.namespace);r?(o.push(l),u.push(async()=>await r.canEagerConnect())):s.push(l)});let p=await O(u);return o.forEach((l,r)=>{p[r].ok&&p[r].val?c.push(l):s.push(l)}),{successNamespaces:c,failedNamespaces:s}}i(He,"tryRunCanEagerConnect");async function le(t){let{getHub:e,allBlockChains:o,wallets:c}=t,s=x.list(),u=Object.keys(s),p=[];if(u.length){let l=[];u.forEach(async r=>{if(c&&!c.includes(r)){console.warn("Trying to run auto connect for a wallet which is not included in config. Desired wallet:",r),p.push(r);return}let a=e().get(r),n=s[r].map(f=>({namespace:f.namespace,network:f.network}));if(!n.length||!a){p.push(r);return}let{successNamespaces:d,failedNamespaces:m}=await He(n,a);if(d.length)m.length&&x.removeNamespacesFromWallet(a.id,m.map(f=>f.namespace));else{p.push(r);return}l.push(Fe(r,d,{allBlockChains:o,getHub:e}).catch(f=>console.warn(f)))}),x.removeWallets(p),await Promise.all(l)}}i(le,"autoConnect");import{createStore as _e,Hub as Oe}from"@rango-dev/wallets-core";import{useRef as de}from"react";function pe(t){let e=de(null),o=de(null);function c(){let p=new Oe({store:s()});return t.forEach(l=>{p.add(l.id,l)}),o.current=p,p}i(c,"createHub");function s(){if(e.current!==null)return e.current;let p=_e();return e.current=p,p}i(s,"getStore");function u(){let p=o.current?.getAll();return!o.current||!p?c():(ie(o.current,t),o.current)}return i(u,"getHub"),{getStore:s,getHub:u}}i(pe,"useHubRefs");function U(t){let{getStore:e,getHub:o}=pe(t.providers),[,c]=je(0),s=Me({onUpdateState:t.onUpdateState,allVersionedProviders:t.allVersionedProviders,allBlockChains:t.allBlockChains}),u=re({onError:(r,a)=>{De.isUserRejectionError(r)&&a.removeCurrentKeyFromQueue()}});ue(()=>{s.current={onUpdateState:t.onUpdateState,allVersionedProviders:t.allVersionedProviders,allBlockChains:t.allBlockChains}},[t]),ue(()=>{let r=i(()=>{o().init(),c(n=>n+1)},"runOnInit"),a=i(n=>{n.target&&n.target.readyState==="complete"&&(r(),document.removeEventListener("readystatechange",a))},"initHubWhenPageIsReady");r(),document.addEventListener("readystatechange",a),e().subscribe(n=>{if(s.current.onUpdateState)try{oe(o(),n,s.current.onUpdateState,s.current.allBlockChains)}catch(d){console.error(d)}c(d=>d+1)}).flushEvents()},[]),T({autoConnect:t.autoConnect,allBlockChains:t.allBlockChains,autoConnectHandler:()=>{le({allBlockChains:t.allBlockChains,getHub:o,wallets:t.configs?.wallets})}});let p=new C(h);return{canSwitchNetworkTo(r,a,n){let d=o().get(r);if(!d)throw new Error(`You should add ${r} to provider first then call 'canSwitchNetworkTo'.`);if(!n)throw new Error("Passing namespace to `canSwitchNetworkTo` is required.");let m=d.findByNamespace(n.namespace);if(!m)throw new Error(`We couldn't find any matched namespace on your request provider. (requested namespace: ${n.namespace})`);if(!("canSwitchNetwork"in m))return!1;let f=d.info()?.properties?.find(y=>y.name==="namespaces");if(!s.current.allBlockChains)throw new Error("Blockchains are not available");let P=f?.value.data.find(y=>y.value===n.namespace)?.getSupportedChains(s.current.allBlockChains);if(!P)throw new Error(`NamespaceMeta is not defined for requested namespace: ${n.namespace}`);return m.canSwitchNetwork({network:a,supportedChains:P})},async connect(r,a){let n=o().get(r);if(!n)throw new Error(`You should add ${r} to provider first then call 'connect'.`);if(!a)throw new Error("Passing namespace to `connect` is required.");let d=[];a.forEach(g=>{let N=g.namespace,S=n.findByNamespace(N);if(!S)throw new Error(`We couldn't find any provider matched with your request namespace. (requested namespace: ${g.namespace})`);d.push([g,S])});let m=d.map(async([g,N])=>{let S=se(g,t.allBlockChains||[]);return u(i(async()=>N.connect(S).then(ce).then(fe=>({response:fe,input:{namespace:g.namespace,network:g.network,supportsEagerConnect:"canEagerConnect"in N}})),"connectNamespaceProcess"),r)}),f=await Promise.all(m),P=f.filter(g=>g.ok).filter(g=>g.val.input.supportsEagerConnect).map(g=>({namespace:g.val.input.namespace,network:g.val.input.network}));P.length>0&&p.addWallet(r,P);let y=f.map(g=>g.andThen(N=>new Ye(N.response))),w=Ue.all(...y);if(w.err)throw w.val;return w.unwrap()},async disconnect(r,a){let n=o().get(r);if(!n)throw new Error(`You should add ${r} to provider first then call 'disconnect'.`);n.getAll().forEach(d=>{let m=!a||a.includes(d.namespaceId),f=d.state()[0]().connected;if(m&&f)return d.disconnect()}),t.autoConnect&&(a?p.removeNamespacesFromWallet(r,a):p.removeWallets([r]))},async disconnectAll(){let r=Array.from(o().getAll().values()).map(async a=>this.disconnect(a.id));return await Promise.allSettled(r)},async getSigners(r){let a=o().get(r);if(!a)throw new Error(`You should add ${r} to provider first.`);let n=a.info();if(!n)throw new Error("Your provider should have required `info`.");let m=n.properties?.find(f=>f.name==="signers");if(!m)throw new Error("Your provider should contain signers property.");return m.value.getSigners()},getWalletInfo(r){let a=o().get(r);if(!a)throw new Error(`You should add ${r} to provider first.`);let n=a.info();if(!n)throw new Error("Your provider should have required `info`.");let d={DEFAULT:""};Object.keys(n.extensions).forEach(w=>{let g=w;if(g==="homepage"&&(d.DEFAULT=n.extensions[g]||""),["firefox","chrome","brave","edge"].includes(g)){let S=g.toUpperCase();d[S]=n.extensions[g]||""}});let m=n.properties,f=m?.find(w=>w.name==="namespaces"),P=m?.find(w=>w.name==="derivationPath"),y=m?.find(w=>w.name==="details");return{name:n.name,img:n.icon,installLink:d,color:"red",supportedChains:j(a,s.current.allBlockChains),isContractWallet:y?.value?.isContractWallet,mobileWallet:y?.value?.mobileWallet,showOnMobile:y?.value?.showOnMobile,needsNamespace:f?.value,needsDerivationPath:P?.value,isHub:!0,properties:a.info()?.properties}},providers(){let r={};return Array.from(o().getAll().keys()).forEach(a=>{try{let n=ae(t.allVersionedProviders,a);r[a]=n.getInstance()}catch(n){console.warn(n)}}),r},state(r){let a=o().state(),n=o().get(r),d=a[r];if(!d||!n)throw new Error(`It seems your requested provider doesn't exist in hub. Provider Id: ${r}`);let m=d.namespaces.filter(y=>y.connected).flatMap(y=>y.accounts?.map(A)).filter(y=>!!y),f=new Map(Array.from(n.getAll(),([y,w])=>[w.namespaceId,w.state()[0]()]));return{connected:d.connected,connecting:d.connecting,installed:d.installed,reachable:!0,accounts:m,network:null,namespaces:f}},suggestAndConnect(r,a){throw new Error("`suggestAndConnect` is not implemented")}}}i(U,"useHubAdapter");function me(t){let{providers:e,...o}=t,[c,s]=M(e),u=H({...o,providers:c}),p=U({...o,providers:s,allVersionedProviders:e});return{canSwitchNetworkTo(r,a,n){return k(s,r)?p.canSwitchNetworkTo(r,a,n):u.canSwitchNetworkTo(r,a)},async connect(r,a){return k(s,r)?await p.connect(r,a):await u.connect(r,a)},async disconnect(r,a){return k(s,r)?await p.disconnect(r,a):await u.disconnect(r)},async disconnectAll(){return await Promise.allSettled([p.disconnectAll(),u.disconnectAll()])},async getSigners(r){return k(s,r)?p.getSigners(r):u.getSigners(r)},getWalletInfo(r){return k(s,r)?p.getWalletInfo(r):u.getWalletInfo(r)},providers(){let r={};return s.length>0&&(r={...r,...p.providers()}),c.length>0&&(r={...r,...u.providers()}),r},state(r){return k(s,r)?p.state(r):u.state(r)},async suggestAndConnect(r,a){return k(s,r)?p.suggestAndConnect(r,a):await u.suggestAndConnect(r,a)}}}i(me,"useProviders");function $e(t){let e=me(t);return Ve.createElement(L.Provider,{value:e},t.children)}i($e,"Provider");var qe=$e;import{LegacyEvents as _r}from"@rango-dev/wallets-core/legacy";export{_r as Events,qe as Provider,q as availableWallets,G as checkWalletProviders,ot as choose,B as clearPersistance,$ as connectedWallets,b as defaultWalletState,nt as isAsync,R as makeEventHandler,at as needsCheckInstallation,V as stateReducer,Q as tryPersistWallet,K as tryRemoveWalletFromPersistance,We as useWallets};
|
|
1
|
+
var ve=Object.defineProperty;var i=(t,e)=>ve(t,"name",{value:e,configurable:!0});import{Persistor as we}from"@rango-dev/wallets-core/legacy";var v="last-connected-wallets",w="hub-v1-last-connected-wallets";import{Persistor as S}from"@rango-dev/wallets-core/legacy";var h=class{static{i(this,"LastConnectedWalletsFromStorage")}#e;constructor(e){this.#e=e}addWallet(e,o){if(this.#e===w)return this.#t(e,o);if(this.#e===v)return this.#a(e);throw new Error("Not implemented")}removeWallets(e){if(this.#e===w)return this.#r(e);if(this.#e===v)return this.#c(e);throw new Error("Not implemented")}list(){if(this.#e===w)return this.#n();if(this.#e===v)return this.#o();throw new Error("Not implemented")}removeNamespacesFromWallet(e,o){if(this.#e===w)return this.#s(e,o);throw new Error("Not implemented")}#o(){let o=new S().getItem(v)||[],c={};return o.forEach(a=>{c[a]=[]}),c}#n(){return new S().getItem(w)||{}}#t(e,o){let c=new S,a=c.getItem(this.#e)||{},u=o;if(a[e]){let p=a[e];u=p.concat(o.filter(l=>!p.some(r=>r.namespace===l.namespace)))}c.setItem(this.#e,{...a,[e]:u})}#a(e){let o=new S,c=o.getItem(this.#e)||[];o.setItem(v,c.concat(e))}#r(e){let o=new S,c=o.getItem(this.#e)||{};if(!e){o.setItem(this.#e,{});return}e.forEach(a=>{c[a]&&delete c[a]}),o.setItem(this.#e,c)}#s(e,o){let p=(new S().getItem(this.#e)||{})[e]?.filter(l=>!o.includes(l.namespace));this.#r([e]),p?.length>0&&this.#t(e,p)}#c(e){let o=new S,c=o.getItem(this.#e)||[];if(!e){o.setItem(this.#e,[]);return}o.setItem(v,c.filter(a=>!e.includes(a)))}};function nt(t,e){return t.find(o=>o.type===e)||null}i(nt,"choose");var B={connected:!1,connecting:!1,reachable:!1,installed:!1,accounts:null,network:null};function q(t,e){if(e.type==="new_state"){let o=t[e.wallet];return o?{...t,[e.wallet]:{...o,[e.name]:e.value}}:{...t,[e.wallet]:{...B,[e.name]:e.value}}}return t}i(q,"stateReducer");function G(t){return Object.entries(t).filter(([,e])=>e?.connected).map(([e])=>e)}i(G,"connectedWallets");function Q(t){return Object.entries(t).map(([e])=>e)}i(Q,"availableWallets");function K(t){let e=new Map;return t.forEach(o=>{let{config:c,...a}=o;e.set(c.type,{actions:a,config:c})}),e}i(K,"checkWalletProviders");function at(t){return t?.constructor?.name==="AsyncFunction"}i(at,"isAsync");function st(t){let{checkInstallation:e=!0}=t.config;return e}i(st,"needsCheckInstallation");async function z({type:t,walletActions:e,getState:o}){if(e.canEagerConnect){let c=new h(v),u=!!c.list()[t];u&&!o(t).connected&&R(),u||c.addWallet(t,[])}}i(z,"tryPersistWallet");function J({type:t,walletActions:e}){e.canEagerConnect&&new h(v).removeWallets([t])}i(J,"tryRemoveWalletFromPersistance");function R(){let t=new we;t.getItem(v)&&t.removeItem(v)}i(R,"clearPersistance");function F(t,e){return i((c,a,u,p,l)=>{t({type:"new_state",wallet:c,name:a,value:u}),e&&e(c,a,u,p,l)},"handler")}i(F,"makeEventHandler");import qe from"react";import{createContext as he}from"react";var k="Context hasn't been initialized yet.",Ce={async connect(){throw new Error(k)},async disconnect(){throw new Error(k)},async disconnectAll(){throw new Error(k)},async suggestAndConnect(){throw new Error(k)},state(){throw new Error(k)},canSwitchNetworkTo(){throw new Error(k)},providers(){throw new Error(k)},getWalletInfo(){throw new Error(k)},getSigners(){throw new Error(k)}},T=he(Ce);import{LegacyEvents as E}from"@rango-dev/wallets-core/legacy";import"@rango-dev/wallets-core/utils";import{pickVersion as M}from"@rango-dev/wallets-core/utils";import{convertEvmBlockchainMetaToEvmChainInfo as be}from"@rango-dev/wallets-shared";import{isEvmBlockchain as Be}from"rango-types";import{useEffect as H,useReducer as Se}from"react";async function X(t,e){let o=new h(v),c=o.list(),a=Object.keys(c);if(a.length){let u=[];a.forEach(r=>{let n=t.get(r);if(n){let s=e(n);u.push({walletType:r,eagerConnect:s.eagerConnect.bind(s)})}});let p=await Promise.allSettled(u.map(async({eagerConnect:r})=>r())),l=[];p.forEach((r,n)=>{let{status:s}=r;s==="rejected"&&l.push(u[n].walletType)}),l.length&&o.removeWallets(l)}}i(X,"autoConnect");import{LegacyWallet as Pe}from"@rango-dev/wallets-core/legacy";import{useContext as We,useRef as Ee}from"react";function Z(t){let e=Ee({});function o(c){let a=c.config.type;return typeof e.current[a]>"u"&&(e.current[a]=new Pe({config:c.config,handler:t},c.actions)),e.current[a]}return i(o,"updater"),o}i(Z,"useInitializers");function ke(){let t=We(T);if(!t)throw Error("useWallet can only be used within the Provider component");return t}i(ke,"useWallets");import{useEffect as Ne,useRef as Ie}from"react";function ee(t){return!!t.allBlockChains?.length&&!!t.autoConnect}i(ee,"shouldTryAutoConnect");function A(t){let e=Ie(!1);Ne(()=>{ee(t)&&!e.current&&(e.current=!0,t.autoConnectHandler())},[t.autoConnect,t.allBlockChains])}i(A,"useAutoConnect");function _(t){let[e,o]=Se(q,{}),c=Z(F(o,t.onUpdateState)),a=t.providers,u=K(a);A({allBlockChains:t.allBlockChains,autoConnect:t.autoConnect,autoConnectHandler:async()=>X(u,c)});let p={async connect(l,r){let n=u.get(l);if(!n)throw new Error(`You should add ${l} to provider first.`);let s;r&&r.length>0&&(s=r.find(f=>!!f.network)?.network);let m=await c(n).connect(s,r);return t.autoConnect&&z({type:l,walletActions:n.actions,getState:p.state}),[m]},async disconnect(l){let r=u.get(l);if(!r)throw new Error(`You should add ${l} to provider first.`);await c(r).disconnect(),t.autoConnect&&J({type:l,walletActions:r.actions})},async disconnectAll(){let l=[];return G(e).forEach(r=>{let n=u.get(r);if(n){let s=c(n);l.push(s.disconnect())}}),t.autoConnect&&R(),await Promise.allSettled(l)},async suggestAndConnect(l,r){let n=u.get(l);if(!n)throw new Error(`You should add ${l} to provider first.`);return await c(n).suggestAndConnect(r)},state(l){return e[l]||B},canSwitchNetworkTo(l,r){let n=u.get(l);if(!n)return!1;let s=c(n);return s.canSwitchNetworkTo?s.canSwitchNetworkTo(r,s.provider):!1},providers(){let l={};return Q(e).forEach(r=>{let n=u.get(r);if(n){let s=c(n);l[r]=s.provider}}),l},getWalletInfo(l){let r=u.get(l);if(!r)throw new Error(`You should add ${l} to provider first.`);return r.actions.getWalletInfo(t.allBlockChains||[])},async getSigners(l){let r=u.get(l);if(!r)throw new Error(`You should add ${l} to provider first.`);let n=c(r),s=n.provider;return n.getSigners(s)}};return H(()=>{u.forEach(l=>{let r=c(l),n=i(()=>{r.onInit&&r.onInit()},"runOnInit"),s=i(d=>{d.target&&d.target.readyState==="complete"&&(n(),document.removeEventListener("readystatechange",s))},"initWhenPageIsReady");n(),document.addEventListener("readystatechange",s)})},[]),H(()=>{t.allBlockChains&&u.forEach(r=>{let n=c(r),s=n.getWalletInfo(t.allBlockChains||[]);n.setInfo({supportedBlockchains:s.supportedChains,isContractWallet:!!s.isContractWallet})})},[t.allBlockChains]),H(()=>{u.forEach(l=>{c(l).setHandler(F(o,t.onUpdateState))})},[t.onUpdateState]),p}i(_,"useLegacyProviders");import{legacyFormatAddressWithNetwork as Le}from"@rango-dev/wallets-core/legacy";import{CAIP_BITCOIN_CHAIN_ID as Te}from"@rango-dev/wallets-core/namespaces/utxo";import{CAIP as Ae}from"@rango-dev/wallets-core/utils";import{Err as O,Ok as te}from"ts-results";function xe(t){return typeof t=="string"?t:["solana"].includes(t.namespace.toLowerCase())?t.namespace.toUpperCase():t.namespace.toLowerCase()==="eip155"?"ETH":t.reference===Te?"BTC":t.namespace==="sui"?t.reference.toUpperCase():t.reference}i(xe,"mapCaipNamespaceToLegacyNetworkName");function x(t){let{chainId:e,address:o}=Ae.AccountId.parse(t),c=xe(e);return Le(o,c)}i(x,"fromAccountIdToLegacyAddressFormat");async function D(t){return t.reduce(async(e,o)=>{let c=await e;try{let a=await o();return[...c,new te(a)]}catch(a){return[...c,new O(a)]}},Promise.resolve([]))}i(D,"runSequentiallyWithoutFailure");function re(t){return typeof t=="object"&&!Array.isArray(t)}i(re,"isConnectResultEvm");function oe(t){return Array.isArray(t)}i(oe,"isConnectResultSolana");function ne(t){let e=new Set,o=[],c=i((p,l)=>{o=o.filter(r=>r.key!==p?!0:(r.resolve(l),!1))},"removeKeyFromQueue"),a=i(async()=>{let p=o.find(s=>!e.has(s.key));if(!p)return;let{task:l,resolve:r,key:n}=p;e.add(n);try{let s=await l();r(new te(s))}catch(s){t?.onError&&t.onError(s,{removeCurrentKeyFromQueue:()=>c(n,new O(s))}),r(new O(s))}finally{let s=o.findIndex(d=>d.key===n);s>=0&&o.splice(s,1),e.delete(n),a()}},"processQueue");return i(async(p,l)=>new Promise(r=>{o.push({task:p,resolve:r,key:l}),a()}),"queueTask")}i(ne,"createQueue");function j(t){let e="0.0.0",o="1.0.0",c=[],a=[];return t.forEach(u=>{try{let p=M(u,o);a.push(p[1])}catch{let p=M(u,e);c.push(p[1])}}),[c,a]}i(j,"separateLegacyAndHubProviders");function N(t,e){return t.find(o=>o.id===e)}i(N,"findProviderByType");var Re=new h(w);function Y(t,e){return t.info()?.metadata.properties?.find(a=>a.name==="namespaces")?.value.data.flatMap(a=>a.getSupportedChains(e||[]))||[]}i(Y,"getSupportedChainsFromProvider");function ae(t,e,o,c){let a=t.get(e.provider);if(!a)throw new Error("Currently all the events have assigned to a provider. The event doesn't include one.",{cause:e});let u=e.namespace,p=u?a.findByNamespace(u):void 0,l=null,r=null;if(p){let[m]=p.state();l=m().accounts,r=m().network}let[n]=a.state(),s={connected:n().connected,connecting:n().connecting,installed:n().installed,accounts:l,network:r,reachable:!0},d={supportedBlockchains:Y(a,c),isContractWallet:!1,isHub:!0,namespace:u};switch(e.type){case"provider_detected":o(e.provider,E.INSTALLED,!0,s,d);break;case"provider_connecting":o(e.provider,E.CONNECTING,e.value,s,d);break;case"provider_connected":o(e.provider,E.CONNECTED,!0,s,d);break;case"provider_disconnected":o(e.provider,E.PROVIDER_DISCONNECTED,e.provider,s,d),o(e.provider,E.CONNECTED,!1,s,d),o(e.provider,E.ACCOUNTS,null,s,d);break;case"namespace_disconnected":Re.removeNamespacesFromWallet(e.provider,[e.namespace]),o(e.provider,E.NAMESPACE_DISCONNECTED,e.namespace,s,{...d,namespace:e.namespace});break;case"namespace_connected":case"namespace_account_switched":{e.type==="namespace_account_switched"&&o(e.provider,E.NAMESPACE_DISCONNECTED,e.namespace,s,d);let m=e.accounts.map(x);o(e.provider,E.ACCOUNTS,m,s,{...d,namespace:e.namespace})}break;case"namespace_network_switched":o(e.provider,E.NETWORK,e.network,s,{...d,namespace:e.namespace});break}}i(ae,"mapHubEventsToLegacy");function se(t){let e="0.0.0",o=[];return t.forEach(c=>{let a=M(c,e);o.push(a[1])}),o}i(se,"getAllLegacyProviders");function ce(t,e){let c=se(t).find(a=>a.config.type===e);if(!c)throw console.warn(`You have a provider that doesn't have legacy provider. It causes some problems since we need some legacy functionality. Provider Id: ${e}`),new Error(`You need to have legacy implementation to use some methods. Provider Id: ${e}`);return c}i(ce,"getLegacyProvider");function U(t,e){if(!t.network)return;let o=e.filter(Be);return be(o)[t.network]}i(U,"convertNamespaceNetworkToEvmChainId");function ie(t,e){return U(t,e)||t.network}i(ie,"tryConvertNamespaceNetworkToChainInfo");function le(t){return re(t)?{accounts:t.accounts,network:t.network,provider:void 0}:oe(t)?{accounts:t,network:null,provider:void 0}:{accounts:[t],network:null,provider:void 0}}i(le,"transformHubResultToLegacyResult");function de(t,e){let o=t.getAll();e.filter(a=>!o.get(a.id)).forEach(a=>{t.add(a.id,a),a.init()}),o.forEach(a=>{e.some(p=>p.id===a.id)||t.remove(a.id)})}i(de,"synchronizeHubWithConfigProviders");import{utils as je}from"@rango-dev/wallets-core/namespaces/evm";import"@rango-dev/wallets-shared";import{useEffect as fe,useRef as Ye,useState as Ue}from"react";import{Ok as Ve,Result as $e}from"ts-results";import{legacyIsEvmNamespace as Fe}from"@rango-dev/wallets-core/legacy";import{Result as He}from"ts-results";var b=new h(w);async function _e(t,e,o){let{getHub:c,allBlockChains:a}=o,u=c().get(t);if(!u)throw new Error(`You should add ${t} to provider first then call 'connect'.`);if(!e)throw new Error("Passing namespace to `connect` is required. ");let p=[];e.forEach(d=>{let m=d.namespace,f=u.findByNamespace(m);if(!f)throw new Error(`We couldn't find any provider matched with your request namespace. (requested namespace: ${d.namespace})`);p.push([d,f])});let l=p.map(([d,m])=>{let C=(Fe(d)?U(d,a||[]):void 0)||d.network;return async()=>await m.connect(C).catch(g=>{throw g instanceof Error?g:new Error(g)})}),r=await D(l),n=p.filter((d,m)=>r[m].err).map(d=>d[0]);if(n.length>0&&b.removeNamespacesFromWallet(t,n.map(d=>d.namespace)),!r.some(d=>d.ok))throw new Error(`No namespace connected for ${t}`);return He.all(...r.filter(d=>d.ok)).unwrap()}i(_e,"eagerConnect");async function Oe(t,e){let o=[],c=[],a=[],u=[];t.forEach(l=>{let r=e.findByNamespace(l.namespace);r?(o.push(l),u.push(async()=>await r.canEagerConnect())):a.push(l)});let p=await D(u);return o.forEach((l,r)=>{p[r].ok&&p[r].val?c.push(l):a.push(l)}),{successNamespaces:c,failedNamespaces:a}}i(Oe,"tryRunCanEagerConnect");async function pe(t){let{getHub:e,allBlockChains:o,wallets:c}=t,a=b.list(),u=Object.keys(a),p=[];if(u.length){let l=[];u.forEach(async r=>{if(c&&!c.includes(r)){console.warn("Trying to run auto connect for a wallet which is not included in config. Desired wallet:",r),p.push(r);return}let n=e().get(r),s=a[r].map(f=>({namespace:f.namespace,network:f.network}));if(!s.length||!n){p.push(r);return}let{successNamespaces:d,failedNamespaces:m}=await Oe(s,n);if(d.length)m.length&&b.removeNamespacesFromWallet(n.id,m.map(f=>f.namespace));else{p.push(r);return}l.push(_e(r,d,{allBlockChains:o,getHub:e}).catch(f=>console.warn(f)))}),b.removeWallets(p),await Promise.all(l)}}i(pe,"autoConnect");import{createStore as De,Hub as Me}from"@rango-dev/wallets-core";import{useRef as ue}from"react";function me(t){let e=ue(null),o=ue(null);function c(){let p=new Me({store:a()});return t.forEach(l=>{p.add(l.id,l)}),o.current=p,p}i(c,"createHub");function a(){if(e.current!==null)return e.current;let p=De();return e.current=p,p}i(a,"getStore");function u(){let p=o.current?.getAll();return!o.current||!p?c():(de(o.current,t),o.current)}return i(u,"getHub"),{getStore:a,getHub:u}}i(me,"useHubRefs");function V(t){let{getStore:e,getHub:o}=me(t.providers),[,c]=Ue(0),a=Ye({onUpdateState:t.onUpdateState,allVersionedProviders:t.allVersionedProviders,allBlockChains:t.allBlockChains}),u=ne({onError:(r,n)=>{je.isUserRejectionError(r)&&n.removeCurrentKeyFromQueue()}});fe(()=>{a.current={onUpdateState:t.onUpdateState,allVersionedProviders:t.allVersionedProviders,allBlockChains:t.allBlockChains}},[t]),fe(()=>{let r=i(()=>{o().init(),c(s=>s+1)},"runOnInit"),n=i(s=>{s.target&&s.target.readyState==="complete"&&(r(),document.removeEventListener("readystatechange",n))},"initHubWhenPageIsReady");r(),document.addEventListener("readystatechange",n),e().subscribe(s=>{if(a.current.onUpdateState)try{ae(o(),s,a.current.onUpdateState,a.current.allBlockChains)}catch(d){console.error(d)}c(d=>d+1)}).flushEvents()},[]),A({autoConnect:t.autoConnect,allBlockChains:t.allBlockChains,autoConnectHandler:()=>{pe({allBlockChains:t.allBlockChains,getHub:o,wallets:t.configs?.wallets})}});let p=new h(w);return{canSwitchNetworkTo(r,n,s){let d=o().get(r);if(!d)throw new Error(`You should add ${r} to provider first then call 'canSwitchNetworkTo'.`);if(!s)throw new Error("Passing namespace to `canSwitchNetworkTo` is required.");let m=d.findByNamespace(s.namespace);if(!m)throw new Error(`We couldn't find any matched namespace on your request provider. (requested namespace: ${s.namespace})`);if(!("canSwitchNetwork"in m))return!1;let f=d.info()?.metadata?.properties?.find(g=>g.name==="namespaces");if(!a.current.allBlockChains)throw new Error("Blockchains are not available");let C=f?.value.data.find(g=>g.value===s.namespace)?.getSupportedChains(a.current.allBlockChains);if(!C)throw new Error(`NamespaceMeta is not defined for requested namespace: ${s.namespace}`);return m.canSwitchNetwork({network:n,supportedChains:C})},async connect(r,n){let s=o().get(r);if(!s)throw new Error(`You should add ${r} to provider first then call 'connect'.`);if(!n)throw new Error("Passing namespace to `connect` is required.");let d=[];n.forEach(y=>{let W=y.namespace,P=s.findByNamespace(W);if(!P)throw new Error(`We couldn't find any provider matched with your request namespace. (requested namespace: ${y.namespace})`);d.push([y,P])});let m=d.map(async([y,W])=>{let P=ie(y,t.allBlockChains||[]);return u(i(async()=>W.connect(P).then(le).then($=>({response:$,input:{namespace:y.namespace,network:y.network,supportsEagerConnect:"canEagerConnect"in W}})),"connectNamespaceProcess"),r)}),f=await Promise.all(m),C=f.filter(y=>y.ok).filter(y=>y.val.input.supportsEagerConnect).map(y=>({namespace:y.val.input.namespace,network:y.val.input.network}));C.length>0&&p.addWallet(r,C);let g=f.map(y=>y.andThen(W=>new Ve(W.response))),I=$e.all(...g);if(I.err)throw I.val;return I.unwrap()},async disconnect(r,n){let s=o().get(r);if(!s)throw new Error(`You should add ${r} to provider first then call 'disconnect'.`);s.getAll().forEach(d=>{let m=!n||n.includes(d.namespaceId),f=d.state()[0]().connected;if(m&&f)return d.disconnect()}),t.autoConnect&&(n?p.removeNamespacesFromWallet(r,n):p.removeWallets([r]))},async disconnectAll(){let r=Array.from(o().getAll().values()).map(async n=>this.disconnect(n.id));return await Promise.allSettled(r)},async getSigners(r){let n=o().get(r);if(!n)throw new Error(`You should add ${r} to provider first.`);let s=n.info();if(!s)throw new Error("Your provider should have required `info`.");let m=s.metadata.properties?.find(f=>f.name==="signers");if(!m)throw new Error("Your provider should contain signers property.");return m.value.getSigners()},getWalletInfo(r){let n=o().get(r);if(!n)throw new Error(`You should add ${r} to provider first.`);let s=n.info();if(!s)throw new Error("Your provider should have required `info`.");let d={DEFAULT:""},{metadata:m,deepLink:f}=s,{extensions:C}=m;Object.keys(C).forEach(P=>{let L=P;if(L==="homepage"&&(d.DEFAULT=C[L]||""),["firefox","chrome","brave","edge"].includes(L)){let ye=L.toUpperCase();d[ye]=C[L]||""}});let g=m.properties,I=g?.find(P=>P.name==="namespaces"),y=g?.find(P=>P.name==="derivationPath"),W=g?.find(P=>P.name==="details");return{name:m.name,img:m.icon,installLink:d,color:"red",supportedChains:Y(n,a.current.allBlockChains),isContractWallet:W?.value?.isContractWallet,mobileWallet:W?.value?.mobileWallet,showOnMobile:W?.value?.showOnMobile,needsNamespace:I?.value,needsDerivationPath:y?.value,generateDeepLink:f,isHub:!0,properties:m.properties}},providers(){let r={};return Array.from(o().getAll().keys()).forEach(n=>{try{let s=ce(t.allVersionedProviders,n);r[n]=s.getInstance()}catch(s){console.warn(s)}}),r},state(r){let n=o().state(),s=o().get(r),d=n[r];if(!d||!s)throw new Error(`It seems your requested provider doesn't exist in hub. Provider Id: ${r}`);let m=d.namespaces.filter(g=>g.connected).flatMap(g=>g.accounts?.map(x)).filter(g=>!!g),f=new Map(Array.from(s.getAll(),([g,I])=>[I.namespaceId,I.state()[0]()]));return{connected:d.connected,connecting:d.connecting,installed:d.installed,reachable:!0,accounts:m,network:null,namespaces:f}},suggestAndConnect(r,n){throw new Error("`suggestAndConnect` is not implemented")}}}i(V,"useHubAdapter");function ge(t){let{providers:e,...o}=t,[c,a]=j(e),u=_({...o,providers:c}),p=V({...o,providers:a,allVersionedProviders:e});return{canSwitchNetworkTo(r,n,s){return N(a,r)?p.canSwitchNetworkTo(r,n,s):u.canSwitchNetworkTo(r,n)},async connect(r,n){return N(a,r)?await p.connect(r,n):await u.connect(r,n)},async disconnect(r,n){return N(a,r)?await p.disconnect(r,n):await u.disconnect(r)},async disconnectAll(){return await Promise.allSettled([p.disconnectAll(),u.disconnectAll()])},async getSigners(r){return N(a,r)?p.getSigners(r):u.getSigners(r)},getWalletInfo(r){return N(a,r)?p.getWalletInfo(r):u.getWalletInfo(r)},providers(){let r={};return a.length>0&&(r={...r,...p.providers()}),c.length>0&&(r={...r,...u.providers()}),r},state(r){return N(a,r)?p.state(r):u.state(r)},async suggestAndConnect(r,n){return N(a,r)?p.suggestAndConnect(r,n):await u.suggestAndConnect(r,n)}}}i(ge,"useProviders");function Ge(t){let e=ge(t);return qe.createElement(T.Provider,{value:e},t.children)}i(Ge,"Provider");var Qe=Ge;import{LegacyEvents as Or}from"@rango-dev/wallets-core/legacy";export{Or as Events,Qe as Provider,Q as availableWallets,K as checkWalletProviders,nt as choose,R as clearPersistance,G as connectedWallets,B as defaultWalletState,at as isAsync,F as makeEventHandler,st as needsCheckInstallation,q as stateReducer,z as tryPersistWallet,J as tryRemoveWalletFromPersistance,ke as useWallets};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|