@tuwaio/orbit-evm 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,15 @@
1
+ import { Chain } from 'viem/chains';
1
2
  import { Config } from '@wagmi/core';
2
3
  import { PublicClient, Hex, Address } from 'viem';
3
- import { Chain } from 'viem/chains';
4
+
5
+ /**
6
+ * Get EVM chain IDs from app chains configuration
7
+ */
8
+ declare function getEvmChains(appChains?: readonly [Chain, ...Chain[]]): number[];
9
+ /**
10
+ * Type guard to check if a chain list contains EVM chain IDs
11
+ */
12
+ declare function isEvmChainList(chains: (string | number)[]): chains is number[];
4
13
 
5
14
  /**
6
15
  * @file This file contains a utility to ensure the user's wallet is connected to the correct chain before proceeding with a transaction.
@@ -85,4 +94,4 @@ declare const getAddress: (name: string) => Promise<Address | null>;
85
94
  */
86
95
  declare const isEnsName: (nameOrAddress: string) => boolean;
87
96
 
88
- export { checkAndSwitchChain, createViemClient, getAddress, getAvatar, getName, isEnsName };
97
+ export { checkAndSwitchChain, createViemClient, getAddress, getAvatar, getEvmChains, getName, isEnsName, isEvmChainList };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,15 @@
1
+ import { Chain } from 'viem/chains';
1
2
  import { Config } from '@wagmi/core';
2
3
  import { PublicClient, Hex, Address } from 'viem';
3
- import { Chain } from 'viem/chains';
4
+
5
+ /**
6
+ * Get EVM chain IDs from app chains configuration
7
+ */
8
+ declare function getEvmChains(appChains?: readonly [Chain, ...Chain[]]): number[];
9
+ /**
10
+ * Type guard to check if a chain list contains EVM chain IDs
11
+ */
12
+ declare function isEvmChainList(chains: (string | number)[]): chains is number[];
4
13
 
5
14
  /**
6
15
  * @file This file contains a utility to ensure the user's wallet is connected to the correct chain before proceeding with a transaction.
@@ -85,4 +94,4 @@ declare const getAddress: (name: string) => Promise<Address | null>;
85
94
  */
86
95
  declare const isEnsName: (nameOrAddress: string) => boolean;
87
96
 
88
- export { checkAndSwitchChain, createViemClient, getAddress, getAvatar, getName, isEnsName };
97
+ export { checkAndSwitchChain, createViemClient, getAddress, getAvatar, getEvmChains, getName, isEnsName, isEvmChainList };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var core=require('@wagmi/core'),viem=require('viem'),chains=require('viem/chains'),ens=require('viem/ens');async function N(e,r){let{connector:n,chainId:t}=core.getConnection(r);if(n&&t!==e)try{await core.switchChain(r,{chainId:e});}catch(o){throw o.cause?.name==="UserRejectedRequestError"?new Error("User rejected the request to switch network."):(console.error("Failed to switch network:",o),new Error("An error occurred while switching the network."))}}var s=new Map;function a(e,r){let n=s.get(e);if(n)return n;let t=r.find(o=>o.id===e);if(t){let o=viem.createPublicClient({chain:t,transport:viem.http()});return s.set(e,o),o}console.warn(`createViemClient: No chain configuration found for chainId ${e}. A client could not be created.`);}var l=new Map,u=new Map,d=new Map,i=a(chains.mainnet.id,[chains.mainnet]),V=async e=>{if(!i)return null;let r=l.get(e);if(r!==void 0)return r;try{let n=await ens.getEnsName(i,{address:e});return l.set(e,n),n}catch(n){return console.error(`ENS name lookup failed for address ${e}:`,n),null}},j=async e=>{if(!i)return null;let r=ens.normalize(e),n=u.get(r);if(n!==void 0)return n;try{let t=await ens.getEnsAvatar(i,{name:r});return u.set(r,t),t}catch(t){return console.error(`ENS avatar lookup failed for name ${e}:`,t),null}},q=async e=>{if(!i)return null;let r=ens.normalize(e),n=d.get(r);if(n!==void 0)return n;try{let t=await ens.getEnsAddress(i,{name:r}),o=t?t.toLowerCase():null;return d.set(r,o),o}catch(t){return console.error(`ENS address lookup failed for name ${e}:`,t),null}},R=e=>e.includes(".")&&!viem.isAddress(e);exports.checkAndSwitchChain=N;exports.createViemClient=a;exports.getAddress=q;exports.getAvatar=j;exports.getName=V;exports.isEnsName=R;//# sourceMappingURL=index.js.map
1
+ 'use strict';var core=require('@wagmi/core'),viem=require('viem'),chains=require('viem/chains'),ens=require('viem/ens');function f(e){return e!=null&&typeof e=="number"&&e>0}function v(e){return !e||e.length===0?[]:e.map(r=>r.id).filter(f)}function A(e){return e.length>0&&e.every(r=>typeof r=="number")}async function P(e,r){let{connector:n,chainId:t}=core.getConnection(r);if(n&&t!==e)try{await core.switchChain(r,{chainId:e});}catch(o){throw o.cause?.name==="UserRejectedRequestError"?new Error("User rejected the request to switch network."):(console.error("Failed to switch network:",o),new Error("An error occurred while switching the network."))}}var s=new Map;function a(e,r){let n=s.get(e);if(n)return n;let t=r.find(o=>o.id===e);if(t){let o=viem.createPublicClient({chain:t,transport:viem.http()});return s.set(e,o),o}console.warn(`createViemClient: No chain configuration found for chainId ${e}. A client could not be created.`);}var l=new Map,u=new Map,m=new Map,i=a(chains.mainnet.id,[chains.mainnet]),R=async e=>{if(!i)return null;let r=l.get(e);if(r!==void 0)return r;try{let n=await ens.getEnsName(i,{address:e});return l.set(e,n),n}catch(n){return console.error(`ENS name lookup failed for address ${e}:`,n),null}},F=async e=>{if(!i)return null;let r=ens.normalize(e),n=u.get(r);if(n!==void 0)return n;try{let t=await ens.getEnsAvatar(i,{name:r});return u.set(r,t),t}catch(t){return console.error(`ENS avatar lookup failed for name ${e}:`,t),null}},B=async e=>{if(!i)return null;let r=ens.normalize(e),n=m.get(r);if(n!==void 0)return n;try{let t=await ens.getEnsAddress(i,{name:r}),o=t?t.toLowerCase():null;return m.set(r,o),o}catch(t){return console.error(`ENS address lookup failed for name ${e}:`,t),null}},D=e=>e.includes(".")&&!viem.isAddress(e);exports.checkAndSwitchChain=P;exports.createViemClient=a;exports.getAddress=B;exports.getAvatar=F;exports.getEvmChains=v;exports.getName=R;exports.isEnsName=D;exports.isEvmChainList=A;//# sourceMappingURL=index.js.map
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/checkAndSwitchChain.ts","../src/utils/createViemClient.ts","../src/utils/ensUtils.ts"],"names":["checkAndSwitchChain","chainId","config","connector","activeChainId","getConnection","switchChain","error","viemClientCache","createViemClient","chains","cachedClient","chain","c","newClient","createPublicClient","http","nameCache","avatarCache","addressCache","ensClient","mainnet","getName","address","cachedName","name","getEnsName","getAvatar","normalizedName","normalize","cachedAvatar","avatarUrl","getEnsAvatar","getAddress","cachedAddress","getEnsAddress","lowercasedAddress","isEnsName","nameOrAddress","isAddress"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @file This file contains a utility to ensure the user's wallet is connected to the correct chain before proceeding with a transaction.\n */\n\nimport { Config, getConnection, switchChain } from '@wagmi/core';\n\n/**\n * Checks if the user's wallet is connected to the specified chain. If not, it prompts\n * the user to switch to the correct chain.\n *\n * This function is a crucial prerequisite for any action that requires a specific network.\n *\n * @param {number} chainId - The ID of the desired blockchain network.\n * @param {Config} config - The wagmi configuration object.\n * @returns {Promise<void>} A promise that resolves when the wallet is on the correct chain.\n * It rejects if the user cancels the switch or if another error occurs.\n *\n * @throws {Error} Throws a specific error if the user rejects the chain switch or if the switch fails for other reasons.\n */\nexport async function checkAndSwitchChain(chainId: number, config: Config): Promise<void> {\n const { connector, chainId: activeChainId } = getConnection(config);\n\n // Proceed only if a wallet is connected and it is on a different chain than required.\n if (connector && activeChainId !== chainId) {\n try {\n // Pause execution and wait for the user to confirm the chain switch in their wallet.\n await switchChain(config, { chainId });\n } catch (error) {\n if ((error as any).cause?.name === 'UserRejectedRequestError') {\n throw new Error('User rejected the request to switch network.');\n }\n console.error('Failed to switch network:', error);\n throw new Error('An error occurred while switching the network.');\n }\n }\n}\n","/**\n * @file This file contains a utility function for creating a viem Public Client.\n */\n\nimport { createPublicClient, http, PublicClient } from 'viem';\nimport { Chain } from 'viem/chains';\n\nconst viemClientCache = new Map<number, PublicClient>();\n\n// -------------------\n\n/**\n * Creates or retrieves a cached viem Public Client for a specific chain.\n *\n * This client is used for read-only interactions with the blockchain, such as fetching\n * transaction receipts or reading contract state, without needing a wallet connection.\n *\n * @param {number} chainId - The ID of the chain for which to create the client.\n * @param {Chain[]} chains - An array of supported viem Chain objects.\n *\n * @returns {import('viem').PublicClient | undefined} A viem PublicClient instance if a matching chain is found, otherwise undefined.\n * It will also log a warning to the console if the chain is not configured.\n */\nexport function createViemClient(chainId: number, chains: readonly [Chain, ...Chain[]]): PublicClient | undefined {\n const cachedClient = viemClientCache.get(chainId);\n if (cachedClient) {\n return cachedClient;\n }\n\n const chain = chains.find((c) => c.id === chainId);\n\n if (chain) {\n const newClient = createPublicClient({\n chain: chain,\n transport: http(),\n });\n viemClientCache.set(chainId, newClient);\n return newClient;\n }\n\n // Log a warning for easier debugging if a chain configuration is missing.\n console.warn(`createViemClient: No chain configuration found for chainId ${chainId}. A client could not be created.`);\n\n return undefined;\n}\n","/**\n * @file This file contains utility functions for interacting with the Ethereum Name Service (ENS).\n * It provides methods for resolving names to addresses, addresses to names, and fetching avatars,\n * all specifically targeting the Ethereum Mainnet where ENS is deployed.\n */\n\nimport { Address, Hex, isAddress } from 'viem';\nimport { mainnet } from 'viem/chains';\nimport { getEnsAddress, getEnsAvatar, getEnsName, normalize } from 'viem/ens';\n\nimport { createViemClient } from './createViemClient';\n\nconst nameCache = new Map<Hex, string | null>();\nconst avatarCache = new Map<string, string | null>();\nconst addressCache = new Map<string, Address | null>();\n\n// -------------------\n\n// A single, shared viem client for all ENS lookups.\n// ENS lookups are always performed against Ethereum Mainnet, regardless of the app's connected chain.\nconst ensClient = createViemClient(mainnet.id, [mainnet]);\n\n/**\n * Fetches the primary ENS name for a given Ethereum address from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {Hex} address - The Ethereum address to look up.\n * @returns {Promise<string | null>} The ENS name if found, otherwise null.\n */\nexport const getName = async (address: Hex): Promise<string | null> => {\n if (!ensClient) return null;\n\n const cachedName = nameCache.get(address);\n if (cachedName !== undefined) {\n return cachedName;\n }\n\n try {\n const name = await getEnsName(ensClient, { address });\n nameCache.set(address, name);\n return name;\n } catch (error) {\n console.error(`ENS name lookup failed for address ${address}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the avatar URL for a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name (e.g., 'vitalik.eth').\n * @returns {Promise<string | null>} The URL of the avatar image if found, otherwise null.\n */\nexport const getAvatar = async (name: string): Promise<string | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAvatar = avatarCache.get(normalizedName);\n if (cachedAvatar !== undefined) {\n return cachedAvatar;\n }\n\n try {\n const avatarUrl = await getEnsAvatar(ensClient, { name: normalizedName });\n avatarCache.set(normalizedName, avatarUrl);\n return avatarUrl;\n } catch (error) {\n console.error(`ENS avatar lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the Ethereum address associated with a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name to resolve (e.g., 'vitalik.eth').\n * @returns {Promise<Address | null>} The associated Ethereum address (lowercase) or null if not found.\n */\nexport const getAddress = async (name: string): Promise<Address | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAddress = addressCache.get(normalizedName);\n if (cachedAddress !== undefined) {\n return cachedAddress;\n }\n\n try {\n const address = await getEnsAddress(ensClient, { name: normalizedName });\n const lowercasedAddress = address ? (address.toLowerCase() as Address) : null;\n addressCache.set(normalizedName, lowercasedAddress);\n return lowercasedAddress;\n } catch (error) {\n console.error(`ENS address lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * A heuristic to check if a string is likely an ENS name.\n *\n * This is not a foolproof validation but a quick check. A valid ENS name\n * must contain at least one dot and should not be a valid Ethereum address.\n *\n * @param {string} nameOrAddress - The string to check.\n * @returns {boolean} True if the string is likely an ENS name.\n *\n * @example\n * isEnsName('vitalik.eth') // true\n * isEnsName('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') // false\n * isEnsName('notanaddress') // false (doesn't contain a dot)\n */\nexport const isEnsName = (nameOrAddress: string): boolean => {\n return nameOrAddress.includes('.') && !isAddress(nameOrAddress);\n};\n"]}
1
+ {"version":3,"sources":["../src/utils/chainsUtils.ts","../src/utils/checkAndSwitchChain.ts","../src/utils/createViemClient.ts","../src/utils/ensUtils.ts"],"names":["isValidEvmChainId","id","getEvmChains","appChains","chain","isEvmChainList","chains","checkAndSwitchChain","chainId","config","connector","activeChainId","getConnection","switchChain","error","viemClientCache","createViemClient","cachedClient","c","newClient","createPublicClient","http","nameCache","avatarCache","addressCache","ensClient","mainnet","getName","address","cachedName","name","getEnsName","getAvatar","normalizedName","normalize","cachedAvatar","avatarUrl","getEnsAvatar","getAddress","cachedAddress","getEnsAddress","lowercasedAddress","isEnsName","nameOrAddress","isAddress"],"mappings":"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","file":"index.js","sourcesContent":["import type { Chain } from 'viem/chains';\n\n/**\n * Type guard to check if a value is a valid EVM chain ID\n */\nfunction isValidEvmChainId(id: unknown): id is number {\n return id !== undefined && id !== null && typeof id === 'number' && id > 0;\n}\n\n/**\n * Get EVM chain IDs from app chains configuration\n */\nexport function getEvmChains(appChains?: readonly [Chain, ...Chain[]]): number[] {\n if (!appChains || appChains.length === 0) {\n return [];\n }\n return appChains.map((chain) => chain.id).filter(isValidEvmChainId);\n}\n\n/**\n * Type guard to check if a chain list contains EVM chain IDs\n */\nexport function isEvmChainList(chains: (string | number)[]): chains is number[] {\n return chains.length > 0 && chains.every((chain) => typeof chain === 'number');\n}\n","/**\n * @file This file contains a utility to ensure the user's wallet is connected to the correct chain before proceeding with a transaction.\n */\n\nimport { Config, getConnection, switchChain } from '@wagmi/core';\n\n/**\n * Checks if the user's wallet is connected to the specified chain. If not, it prompts\n * the user to switch to the correct chain.\n *\n * This function is a crucial prerequisite for any action that requires a specific network.\n *\n * @param {number} chainId - The ID of the desired blockchain network.\n * @param {Config} config - The wagmi configuration object.\n * @returns {Promise<void>} A promise that resolves when the wallet is on the correct chain.\n * It rejects if the user cancels the switch or if another error occurs.\n *\n * @throws {Error} Throws a specific error if the user rejects the chain switch or if the switch fails for other reasons.\n */\nexport async function checkAndSwitchChain(chainId: number, config: Config): Promise<void> {\n const { connector, chainId: activeChainId } = getConnection(config);\n\n // Proceed only if a wallet is connected and it is on a different chain than required.\n if (connector && activeChainId !== chainId) {\n try {\n // Pause execution and wait for the user to confirm the chain switch in their wallet.\n await switchChain(config, { chainId });\n } catch (error) {\n if ((error as any).cause?.name === 'UserRejectedRequestError') {\n throw new Error('User rejected the request to switch network.');\n }\n console.error('Failed to switch network:', error);\n throw new Error('An error occurred while switching the network.');\n }\n }\n}\n","/**\n * @file This file contains a utility function for creating a viem Public Client.\n */\n\nimport { createPublicClient, http, PublicClient } from 'viem';\nimport { Chain } from 'viem/chains';\n\nconst viemClientCache = new Map<number, PublicClient>();\n\n// -------------------\n\n/**\n * Creates or retrieves a cached viem Public Client for a specific chain.\n *\n * This client is used for read-only interactions with the blockchain, such as fetching\n * transaction receipts or reading contract state, without needing a wallet connection.\n *\n * @param {number} chainId - The ID of the chain for which to create the client.\n * @param {Chain[]} chains - An array of supported viem Chain objects.\n *\n * @returns {import('viem').PublicClient | undefined} A viem PublicClient instance if a matching chain is found, otherwise undefined.\n * It will also log a warning to the console if the chain is not configured.\n */\nexport function createViemClient(chainId: number, chains: readonly [Chain, ...Chain[]]): PublicClient | undefined {\n const cachedClient = viemClientCache.get(chainId);\n if (cachedClient) {\n return cachedClient;\n }\n\n const chain = chains.find((c) => c.id === chainId);\n\n if (chain) {\n const newClient = createPublicClient({\n chain: chain,\n transport: http(),\n });\n viemClientCache.set(chainId, newClient);\n return newClient;\n }\n\n // Log a warning for easier debugging if a chain configuration is missing.\n console.warn(`createViemClient: No chain configuration found for chainId ${chainId}. A client could not be created.`);\n\n return undefined;\n}\n","/**\n * @file This file contains utility functions for interacting with the Ethereum Name Service (ENS).\n * It provides methods for resolving names to addresses, addresses to names, and fetching avatars,\n * all specifically targeting the Ethereum Mainnet where ENS is deployed.\n */\n\nimport { Address, Hex, isAddress } from 'viem';\nimport { mainnet } from 'viem/chains';\nimport { getEnsAddress, getEnsAvatar, getEnsName, normalize } from 'viem/ens';\n\nimport { createViemClient } from './createViemClient';\n\nconst nameCache = new Map<Hex, string | null>();\nconst avatarCache = new Map<string, string | null>();\nconst addressCache = new Map<string, Address | null>();\n\n// -------------------\n\n// A single, shared viem client for all ENS lookups.\n// ENS lookups are always performed against Ethereum Mainnet, regardless of the app's connected chain.\nconst ensClient = createViemClient(mainnet.id, [mainnet]);\n\n/**\n * Fetches the primary ENS name for a given Ethereum address from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {Hex} address - The Ethereum address to look up.\n * @returns {Promise<string | null>} The ENS name if found, otherwise null.\n */\nexport const getName = async (address: Hex): Promise<string | null> => {\n if (!ensClient) return null;\n\n const cachedName = nameCache.get(address);\n if (cachedName !== undefined) {\n return cachedName;\n }\n\n try {\n const name = await getEnsName(ensClient, { address });\n nameCache.set(address, name);\n return name;\n } catch (error) {\n console.error(`ENS name lookup failed for address ${address}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the avatar URL for a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name (e.g., 'vitalik.eth').\n * @returns {Promise<string | null>} The URL of the avatar image if found, otherwise null.\n */\nexport const getAvatar = async (name: string): Promise<string | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAvatar = avatarCache.get(normalizedName);\n if (cachedAvatar !== undefined) {\n return cachedAvatar;\n }\n\n try {\n const avatarUrl = await getEnsAvatar(ensClient, { name: normalizedName });\n avatarCache.set(normalizedName, avatarUrl);\n return avatarUrl;\n } catch (error) {\n console.error(`ENS avatar lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the Ethereum address associated with a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name to resolve (e.g., 'vitalik.eth').\n * @returns {Promise<Address | null>} The associated Ethereum address (lowercase) or null if not found.\n */\nexport const getAddress = async (name: string): Promise<Address | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAddress = addressCache.get(normalizedName);\n if (cachedAddress !== undefined) {\n return cachedAddress;\n }\n\n try {\n const address = await getEnsAddress(ensClient, { name: normalizedName });\n const lowercasedAddress = address ? (address.toLowerCase() as Address) : null;\n addressCache.set(normalizedName, lowercasedAddress);\n return lowercasedAddress;\n } catch (error) {\n console.error(`ENS address lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * A heuristic to check if a string is likely an ENS name.\n *\n * This is not a foolproof validation but a quick check. A valid ENS name\n * must contain at least one dot and should not be a valid Ethereum address.\n *\n * @param {string} nameOrAddress - The string to check.\n * @returns {boolean} True if the string is likely an ENS name.\n *\n * @example\n * isEnsName('vitalik.eth') // true\n * isEnsName('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') // false\n * isEnsName('notanaddress') // false (doesn't contain a dot)\n */\nexport const isEnsName = (nameOrAddress: string): boolean => {\n return nameOrAddress.includes('.') && !isAddress(nameOrAddress);\n};\n"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import {getConnection,switchChain}from'@wagmi/core';import {createPublicClient,http,isAddress}from'viem';import {mainnet}from'viem/chains';import {getEnsName,normalize,getEnsAvatar,getEnsAddress}from'viem/ens';async function N(e,r){let{connector:n,chainId:t}=getConnection(r);if(n&&t!==e)try{await switchChain(r,{chainId:e});}catch(o){throw o.cause?.name==="UserRejectedRequestError"?new Error("User rejected the request to switch network."):(console.error("Failed to switch network:",o),new Error("An error occurred while switching the network."))}}var s=new Map;function a(e,r){let n=s.get(e);if(n)return n;let t=r.find(o=>o.id===e);if(t){let o=createPublicClient({chain:t,transport:http()});return s.set(e,o),o}console.warn(`createViemClient: No chain configuration found for chainId ${e}. A client could not be created.`);}var l=new Map,u=new Map,d=new Map,i=a(mainnet.id,[mainnet]),V=async e=>{if(!i)return null;let r=l.get(e);if(r!==void 0)return r;try{let n=await getEnsName(i,{address:e});return l.set(e,n),n}catch(n){return console.error(`ENS name lookup failed for address ${e}:`,n),null}},j=async e=>{if(!i)return null;let r=normalize(e),n=u.get(r);if(n!==void 0)return n;try{let t=await getEnsAvatar(i,{name:r});return u.set(r,t),t}catch(t){return console.error(`ENS avatar lookup failed for name ${e}:`,t),null}},q=async e=>{if(!i)return null;let r=normalize(e),n=d.get(r);if(n!==void 0)return n;try{let t=await getEnsAddress(i,{name:r}),o=t?t.toLowerCase():null;return d.set(r,o),o}catch(t){return console.error(`ENS address lookup failed for name ${e}:`,t),null}},R=e=>e.includes(".")&&!isAddress(e);export{N as checkAndSwitchChain,a as createViemClient,q as getAddress,j as getAvatar,V as getName,R as isEnsName};//# sourceMappingURL=index.mjs.map
1
+ import {getConnection,switchChain}from'@wagmi/core';import {createPublicClient,http,isAddress}from'viem';import {mainnet}from'viem/chains';import {getEnsName,normalize,getEnsAvatar,getEnsAddress}from'viem/ens';function f(e){return e!=null&&typeof e=="number"&&e>0}function v(e){return !e||e.length===0?[]:e.map(r=>r.id).filter(f)}function A(e){return e.length>0&&e.every(r=>typeof r=="number")}async function P(e,r){let{connector:n,chainId:t}=getConnection(r);if(n&&t!==e)try{await switchChain(r,{chainId:e});}catch(o){throw o.cause?.name==="UserRejectedRequestError"?new Error("User rejected the request to switch network."):(console.error("Failed to switch network:",o),new Error("An error occurred while switching the network."))}}var s=new Map;function a(e,r){let n=s.get(e);if(n)return n;let t=r.find(o=>o.id===e);if(t){let o=createPublicClient({chain:t,transport:http()});return s.set(e,o),o}console.warn(`createViemClient: No chain configuration found for chainId ${e}. A client could not be created.`);}var l=new Map,u=new Map,m=new Map,i=a(mainnet.id,[mainnet]),R=async e=>{if(!i)return null;let r=l.get(e);if(r!==void 0)return r;try{let n=await getEnsName(i,{address:e});return l.set(e,n),n}catch(n){return console.error(`ENS name lookup failed for address ${e}:`,n),null}},F=async e=>{if(!i)return null;let r=normalize(e),n=u.get(r);if(n!==void 0)return n;try{let t=await getEnsAvatar(i,{name:r});return u.set(r,t),t}catch(t){return console.error(`ENS avatar lookup failed for name ${e}:`,t),null}},B=async e=>{if(!i)return null;let r=normalize(e),n=m.get(r);if(n!==void 0)return n;try{let t=await getEnsAddress(i,{name:r}),o=t?t.toLowerCase():null;return m.set(r,o),o}catch(t){return console.error(`ENS address lookup failed for name ${e}:`,t),null}},D=e=>e.includes(".")&&!isAddress(e);export{P as checkAndSwitchChain,a as createViemClient,B as getAddress,F as getAvatar,v as getEvmChains,R as getName,D as isEnsName,A as isEvmChainList};//# sourceMappingURL=index.mjs.map
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/checkAndSwitchChain.ts","../src/utils/createViemClient.ts","../src/utils/ensUtils.ts"],"names":["checkAndSwitchChain","chainId","config","connector","activeChainId","getConnection","switchChain","error","viemClientCache","createViemClient","chains","cachedClient","chain","c","newClient","createPublicClient","http","nameCache","avatarCache","addressCache","ensClient","mainnet","getName","address","cachedName","name","getEnsName","getAvatar","normalizedName","normalize","cachedAvatar","avatarUrl","getEnsAvatar","getAddress","cachedAddress","getEnsAddress","lowercasedAddress","isEnsName","nameOrAddress","isAddress"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @file This file contains a utility to ensure the user's wallet is connected to the correct chain before proceeding with a transaction.\n */\n\nimport { Config, getConnection, switchChain } from '@wagmi/core';\n\n/**\n * Checks if the user's wallet is connected to the specified chain. If not, it prompts\n * the user to switch to the correct chain.\n *\n * This function is a crucial prerequisite for any action that requires a specific network.\n *\n * @param {number} chainId - The ID of the desired blockchain network.\n * @param {Config} config - The wagmi configuration object.\n * @returns {Promise<void>} A promise that resolves when the wallet is on the correct chain.\n * It rejects if the user cancels the switch or if another error occurs.\n *\n * @throws {Error} Throws a specific error if the user rejects the chain switch or if the switch fails for other reasons.\n */\nexport async function checkAndSwitchChain(chainId: number, config: Config): Promise<void> {\n const { connector, chainId: activeChainId } = getConnection(config);\n\n // Proceed only if a wallet is connected and it is on a different chain than required.\n if (connector && activeChainId !== chainId) {\n try {\n // Pause execution and wait for the user to confirm the chain switch in their wallet.\n await switchChain(config, { chainId });\n } catch (error) {\n if ((error as any).cause?.name === 'UserRejectedRequestError') {\n throw new Error('User rejected the request to switch network.');\n }\n console.error('Failed to switch network:', error);\n throw new Error('An error occurred while switching the network.');\n }\n }\n}\n","/**\n * @file This file contains a utility function for creating a viem Public Client.\n */\n\nimport { createPublicClient, http, PublicClient } from 'viem';\nimport { Chain } from 'viem/chains';\n\nconst viemClientCache = new Map<number, PublicClient>();\n\n// -------------------\n\n/**\n * Creates or retrieves a cached viem Public Client for a specific chain.\n *\n * This client is used for read-only interactions with the blockchain, such as fetching\n * transaction receipts or reading contract state, without needing a wallet connection.\n *\n * @param {number} chainId - The ID of the chain for which to create the client.\n * @param {Chain[]} chains - An array of supported viem Chain objects.\n *\n * @returns {import('viem').PublicClient | undefined} A viem PublicClient instance if a matching chain is found, otherwise undefined.\n * It will also log a warning to the console if the chain is not configured.\n */\nexport function createViemClient(chainId: number, chains: readonly [Chain, ...Chain[]]): PublicClient | undefined {\n const cachedClient = viemClientCache.get(chainId);\n if (cachedClient) {\n return cachedClient;\n }\n\n const chain = chains.find((c) => c.id === chainId);\n\n if (chain) {\n const newClient = createPublicClient({\n chain: chain,\n transport: http(),\n });\n viemClientCache.set(chainId, newClient);\n return newClient;\n }\n\n // Log a warning for easier debugging if a chain configuration is missing.\n console.warn(`createViemClient: No chain configuration found for chainId ${chainId}. A client could not be created.`);\n\n return undefined;\n}\n","/**\n * @file This file contains utility functions for interacting with the Ethereum Name Service (ENS).\n * It provides methods for resolving names to addresses, addresses to names, and fetching avatars,\n * all specifically targeting the Ethereum Mainnet where ENS is deployed.\n */\n\nimport { Address, Hex, isAddress } from 'viem';\nimport { mainnet } from 'viem/chains';\nimport { getEnsAddress, getEnsAvatar, getEnsName, normalize } from 'viem/ens';\n\nimport { createViemClient } from './createViemClient';\n\nconst nameCache = new Map<Hex, string | null>();\nconst avatarCache = new Map<string, string | null>();\nconst addressCache = new Map<string, Address | null>();\n\n// -------------------\n\n// A single, shared viem client for all ENS lookups.\n// ENS lookups are always performed against Ethereum Mainnet, regardless of the app's connected chain.\nconst ensClient = createViemClient(mainnet.id, [mainnet]);\n\n/**\n * Fetches the primary ENS name for a given Ethereum address from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {Hex} address - The Ethereum address to look up.\n * @returns {Promise<string | null>} The ENS name if found, otherwise null.\n */\nexport const getName = async (address: Hex): Promise<string | null> => {\n if (!ensClient) return null;\n\n const cachedName = nameCache.get(address);\n if (cachedName !== undefined) {\n return cachedName;\n }\n\n try {\n const name = await getEnsName(ensClient, { address });\n nameCache.set(address, name);\n return name;\n } catch (error) {\n console.error(`ENS name lookup failed for address ${address}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the avatar URL for a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name (e.g., 'vitalik.eth').\n * @returns {Promise<string | null>} The URL of the avatar image if found, otherwise null.\n */\nexport const getAvatar = async (name: string): Promise<string | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAvatar = avatarCache.get(normalizedName);\n if (cachedAvatar !== undefined) {\n return cachedAvatar;\n }\n\n try {\n const avatarUrl = await getEnsAvatar(ensClient, { name: normalizedName });\n avatarCache.set(normalizedName, avatarUrl);\n return avatarUrl;\n } catch (error) {\n console.error(`ENS avatar lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the Ethereum address associated with a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name to resolve (e.g., 'vitalik.eth').\n * @returns {Promise<Address | null>} The associated Ethereum address (lowercase) or null if not found.\n */\nexport const getAddress = async (name: string): Promise<Address | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAddress = addressCache.get(normalizedName);\n if (cachedAddress !== undefined) {\n return cachedAddress;\n }\n\n try {\n const address = await getEnsAddress(ensClient, { name: normalizedName });\n const lowercasedAddress = address ? (address.toLowerCase() as Address) : null;\n addressCache.set(normalizedName, lowercasedAddress);\n return lowercasedAddress;\n } catch (error) {\n console.error(`ENS address lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * A heuristic to check if a string is likely an ENS name.\n *\n * This is not a foolproof validation but a quick check. A valid ENS name\n * must contain at least one dot and should not be a valid Ethereum address.\n *\n * @param {string} nameOrAddress - The string to check.\n * @returns {boolean} True if the string is likely an ENS name.\n *\n * @example\n * isEnsName('vitalik.eth') // true\n * isEnsName('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') // false\n * isEnsName('notanaddress') // false (doesn't contain a dot)\n */\nexport const isEnsName = (nameOrAddress: string): boolean => {\n return nameOrAddress.includes('.') && !isAddress(nameOrAddress);\n};\n"]}
1
+ {"version":3,"sources":["../src/utils/chainsUtils.ts","../src/utils/checkAndSwitchChain.ts","../src/utils/createViemClient.ts","../src/utils/ensUtils.ts"],"names":["isValidEvmChainId","id","getEvmChains","appChains","chain","isEvmChainList","chains","checkAndSwitchChain","chainId","config","connector","activeChainId","getConnection","switchChain","error","viemClientCache","createViemClient","cachedClient","c","newClient","createPublicClient","http","nameCache","avatarCache","addressCache","ensClient","mainnet","getName","address","cachedName","name","getEnsName","getAvatar","normalizedName","normalize","cachedAvatar","avatarUrl","getEnsAvatar","getAddress","cachedAddress","getEnsAddress","lowercasedAddress","isEnsName","nameOrAddress","isAddress"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Chain } from 'viem/chains';\n\n/**\n * Type guard to check if a value is a valid EVM chain ID\n */\nfunction isValidEvmChainId(id: unknown): id is number {\n return id !== undefined && id !== null && typeof id === 'number' && id > 0;\n}\n\n/**\n * Get EVM chain IDs from app chains configuration\n */\nexport function getEvmChains(appChains?: readonly [Chain, ...Chain[]]): number[] {\n if (!appChains || appChains.length === 0) {\n return [];\n }\n return appChains.map((chain) => chain.id).filter(isValidEvmChainId);\n}\n\n/**\n * Type guard to check if a chain list contains EVM chain IDs\n */\nexport function isEvmChainList(chains: (string | number)[]): chains is number[] {\n return chains.length > 0 && chains.every((chain) => typeof chain === 'number');\n}\n","/**\n * @file This file contains a utility to ensure the user's wallet is connected to the correct chain before proceeding with a transaction.\n */\n\nimport { Config, getConnection, switchChain } from '@wagmi/core';\n\n/**\n * Checks if the user's wallet is connected to the specified chain. If not, it prompts\n * the user to switch to the correct chain.\n *\n * This function is a crucial prerequisite for any action that requires a specific network.\n *\n * @param {number} chainId - The ID of the desired blockchain network.\n * @param {Config} config - The wagmi configuration object.\n * @returns {Promise<void>} A promise that resolves when the wallet is on the correct chain.\n * It rejects if the user cancels the switch or if another error occurs.\n *\n * @throws {Error} Throws a specific error if the user rejects the chain switch or if the switch fails for other reasons.\n */\nexport async function checkAndSwitchChain(chainId: number, config: Config): Promise<void> {\n const { connector, chainId: activeChainId } = getConnection(config);\n\n // Proceed only if a wallet is connected and it is on a different chain than required.\n if (connector && activeChainId !== chainId) {\n try {\n // Pause execution and wait for the user to confirm the chain switch in their wallet.\n await switchChain(config, { chainId });\n } catch (error) {\n if ((error as any).cause?.name === 'UserRejectedRequestError') {\n throw new Error('User rejected the request to switch network.');\n }\n console.error('Failed to switch network:', error);\n throw new Error('An error occurred while switching the network.');\n }\n }\n}\n","/**\n * @file This file contains a utility function for creating a viem Public Client.\n */\n\nimport { createPublicClient, http, PublicClient } from 'viem';\nimport { Chain } from 'viem/chains';\n\nconst viemClientCache = new Map<number, PublicClient>();\n\n// -------------------\n\n/**\n * Creates or retrieves a cached viem Public Client for a specific chain.\n *\n * This client is used for read-only interactions with the blockchain, such as fetching\n * transaction receipts or reading contract state, without needing a wallet connection.\n *\n * @param {number} chainId - The ID of the chain for which to create the client.\n * @param {Chain[]} chains - An array of supported viem Chain objects.\n *\n * @returns {import('viem').PublicClient | undefined} A viem PublicClient instance if a matching chain is found, otherwise undefined.\n * It will also log a warning to the console if the chain is not configured.\n */\nexport function createViemClient(chainId: number, chains: readonly [Chain, ...Chain[]]): PublicClient | undefined {\n const cachedClient = viemClientCache.get(chainId);\n if (cachedClient) {\n return cachedClient;\n }\n\n const chain = chains.find((c) => c.id === chainId);\n\n if (chain) {\n const newClient = createPublicClient({\n chain: chain,\n transport: http(),\n });\n viemClientCache.set(chainId, newClient);\n return newClient;\n }\n\n // Log a warning for easier debugging if a chain configuration is missing.\n console.warn(`createViemClient: No chain configuration found for chainId ${chainId}. A client could not be created.`);\n\n return undefined;\n}\n","/**\n * @file This file contains utility functions for interacting with the Ethereum Name Service (ENS).\n * It provides methods for resolving names to addresses, addresses to names, and fetching avatars,\n * all specifically targeting the Ethereum Mainnet where ENS is deployed.\n */\n\nimport { Address, Hex, isAddress } from 'viem';\nimport { mainnet } from 'viem/chains';\nimport { getEnsAddress, getEnsAvatar, getEnsName, normalize } from 'viem/ens';\n\nimport { createViemClient } from './createViemClient';\n\nconst nameCache = new Map<Hex, string | null>();\nconst avatarCache = new Map<string, string | null>();\nconst addressCache = new Map<string, Address | null>();\n\n// -------------------\n\n// A single, shared viem client for all ENS lookups.\n// ENS lookups are always performed against Ethereum Mainnet, regardless of the app's connected chain.\nconst ensClient = createViemClient(mainnet.id, [mainnet]);\n\n/**\n * Fetches the primary ENS name for a given Ethereum address from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {Hex} address - The Ethereum address to look up.\n * @returns {Promise<string | null>} The ENS name if found, otherwise null.\n */\nexport const getName = async (address: Hex): Promise<string | null> => {\n if (!ensClient) return null;\n\n const cachedName = nameCache.get(address);\n if (cachedName !== undefined) {\n return cachedName;\n }\n\n try {\n const name = await getEnsName(ensClient, { address });\n nameCache.set(address, name);\n return name;\n } catch (error) {\n console.error(`ENS name lookup failed for address ${address}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the avatar URL for a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name (e.g., 'vitalik.eth').\n * @returns {Promise<string | null>} The URL of the avatar image if found, otherwise null.\n */\nexport const getAvatar = async (name: string): Promise<string | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAvatar = avatarCache.get(normalizedName);\n if (cachedAvatar !== undefined) {\n return cachedAvatar;\n }\n\n try {\n const avatarUrl = await getEnsAvatar(ensClient, { name: normalizedName });\n avatarCache.set(normalizedName, avatarUrl);\n return avatarUrl;\n } catch (error) {\n console.error(`ENS avatar lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * Fetches the Ethereum address associated with a given ENS name from the Ethereum Mainnet.\n * Includes caching for performance.\n *\n * @param {string} name - The ENS name to resolve (e.g., 'vitalik.eth').\n * @returns {Promise<Address | null>} The associated Ethereum address (lowercase) or null if not found.\n */\nexport const getAddress = async (name: string): Promise<Address | null> => {\n if (!ensClient) return null;\n const normalizedName = normalize(name);\n\n const cachedAddress = addressCache.get(normalizedName);\n if (cachedAddress !== undefined) {\n return cachedAddress;\n }\n\n try {\n const address = await getEnsAddress(ensClient, { name: normalizedName });\n const lowercasedAddress = address ? (address.toLowerCase() as Address) : null;\n addressCache.set(normalizedName, lowercasedAddress);\n return lowercasedAddress;\n } catch (error) {\n console.error(`ENS address lookup failed for name ${name}:`, error);\n return null;\n }\n};\n\n/**\n * A heuristic to check if a string is likely an ENS name.\n *\n * This is not a foolproof validation but a quick check. A valid ENS name\n * must contain at least one dot and should not be a valid Ethereum address.\n *\n * @param {string} nameOrAddress - The string to check.\n * @returns {boolean} True if the string is likely an ENS name.\n *\n * @example\n * isEnsName('vitalik.eth') // true\n * isEnsName('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') // false\n * isEnsName('notanaddress') // false (doesn't contain a dot)\n */\nexport const isEnsName = (nameOrAddress: string): boolean => {\n return nameOrAddress.includes('.') && !isAddress(nameOrAddress);\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tuwaio/orbit-evm",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "private": false,
5
5
  "author": "Oleksandr Tkach",
6
6
  "license": "Apache-2.0",
@@ -40,10 +40,10 @@
40
40
  "viem": "2.x.x"
41
41
  },
42
42
  "devDependencies": {
43
- "@wagmi/core": "^3.0.0",
43
+ "@wagmi/core": "^3.0.1",
44
44
  "tsup": "^8.5.1",
45
45
  "typescript": "^5.9.3",
46
- "viem": "^2.41.2"
46
+ "viem": "^2.43.3"
47
47
  },
48
48
  "scripts": {
49
49
  "start": "tsup src/index.ts --watch",