@tuwaio/satellite-evm 0.10.0 → 0.10.1
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/README.md +2 -1
- package/dist/index.d.mts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
## 🏛️ Core Capabilities
|
|
11
11
|
|
|
12
12
|
- **Adapter:** `satelliteEVMAdapter(wagmiConfig, chains)` connects the connectors of your wagmi config (injected wallets found through EIP-6963, WalletConnect, Safe, Coinbase…) by connector type, such as `"evm:metamask"`. It asks the wallet to switch chains, reads native balances, builds block explorer links (`undefined` when the chain has no explorer), resolves ENS names and avatars on Ethereum Mainnet, and checks whether the account is a smart contract.
|
|
13
|
+
- **Restore without a prompt:** after a page load the store restores the last wallet with the adapter's `reconnect`: a wallet that still authorizes the site (`eth_accounts` of an injected wallet) is connected again without a prompt, on the chain it was saved with; a locked wallet, or one in which the site was disconnected, is left alone until the user connects it. A wallet that wagmi already holds in the page (connected through an earlier store on the same config, or restored by `WagmiProvider`) is taken over without a prompt, on restore and on `connect`; any other wallet shows its connect prompt when the user picks it (wagmi asks injected wallets for `wallet_requestPermissions`, which shows MetaMask's account picker). Disconnecting without a connection closes only the live wagmi connections that the adapter opened, never a connector without a connection or a connection opened by other code: wagmi's injected connector sends `wallet_revokePermissions` on every disconnect, and MetaMask revokes the site's permission for every tab of the origin.
|
|
13
14
|
- **Watcher:** `createEVMConnectionsWatcher` subscribes to wagmi's `watchConnections` and copies account and chain changes made in the wallet into the store; it disconnects the store when the wallet disconnects. With a SIWX session it also disconnects when the sign-in is rejected or fails, or when the wallet switches to another account or chain than the session. Pass the store's `getState`, and the watcher reads the current state on every event. React apps use `EVMConnectorsWatcher` from [`@tuwaio/satellite-react/evm`](https://satellite.docs.tuwa.io/packages/satellite-react) instead.
|
|
14
15
|
- **Contract accounts:** `checkIsWalletAddressContract` reads the account's code on the requested chain and caches the result in memory per chain and address.
|
|
15
16
|
- **wagmi config helpers:** `createDefaultTransports(chains)` creates an `http()` transport for every chain; `safeSdkOptions` are the options for the `safe` connector of `@wagmi/connectors`, with anchored Safe{Wallet} origins; `impersonated()` is a development connector that acts as a wallet for the address saved in `localStorage` and forwards requests to your node.
|
|
@@ -55,7 +56,7 @@ Pass `evmAdapter` to `createSatelliteConnectStore` from [`@tuwaio/satellite-core
|
|
|
55
56
|
|
|
56
57
|
## 🗄️ Browser Storage
|
|
57
58
|
|
|
58
|
-
The package writes nothing to `localStorage`. The `impersonated` connector reads `satellite-connect:impersonatedAddress` (set with `impersonatedHelpers.setImpersonated` from `@tuwaio/orbit-core`, for example by Nova Connect) on every request; `@tuwaio/satellite-core` removes the key on `disconnectAll` and when the last connection is disconnected. The keys that the store writes for EVM connections are listed on the [`@tuwaio/satellite-core`](https://satellite.docs.tuwa.io/packages/satellite-core) page. wagmi keeps its own state in the `storage` of your wagmi config.
|
|
59
|
+
The package writes nothing to `localStorage`. The `impersonated` connector reads `satellite-connect:impersonatedAddress` (set with `impersonatedHelpers.setImpersonated` from `@tuwaio/orbit-core`, for example by Nova Connect) on every request; `@tuwaio/satellite-core` removes the key on `initializeAutoConnect`, on `disconnectAll` and when the last connection is disconnected. The keys that the store writes for EVM connections are listed on the [`@tuwaio/satellite-core`](https://satellite.docs.tuwa.io/packages/satellite-core) page. wagmi keeps its own state in the `storage` of your wagmi config.
|
|
59
60
|
|
|
60
61
|
---
|
|
61
62
|
|
package/dist/index.d.mts
CHANGED
|
@@ -23,8 +23,27 @@ interface EVMConnection extends BaseConnector {
|
|
|
23
23
|
* through `formatConnectorName` from `@tuwaio/orbit-core` (for example, the `Safe` connector is `"evm:safe"`).
|
|
24
24
|
* - `connect` runs wagmi's `connect` with the requested chain and returns an {@link EVMConnection}: the account (the
|
|
25
25
|
* zero address if wagmi reports none), the chain (`1` if unknown), the first default RPC URL of the chain, the
|
|
26
|
-
* connector icon and a `signMessage` that signs with wagmi's `signMessage`.
|
|
27
|
-
*
|
|
26
|
+
* connector icon and a `signMessage` that signs with wagmi's `signMessage`. An injected wallet shows its connect
|
|
27
|
+
* prompt (wagmi requests `wallet_requestPermissions`, then `eth_requestAccounts`). A wallet that wagmi already holds
|
|
28
|
+
* in this page (an earlier store on the same config connected it, or `WagmiProvider` restored it) is taken over
|
|
29
|
+
* without a request: it becomes wagmi's current connection, and wagmi's `switchChain` asks it to move to the
|
|
30
|
+
* requested chain (when it declines, the connection stays on its chain).
|
|
31
|
+
* - `reconnect` restores a wallet without a prompt, for `initializeAutoConnect`: a wallet that wagmi already holds in
|
|
32
|
+
* this page is taken over as by `connect`; otherwise, when the connector reports authorized accounts
|
|
33
|
+
* (`eth_accounts` for injected wallets), wagmi's `connect` runs with `isReconnecting`, so the connector reads those
|
|
34
|
+
* accounts instead of asking for them. It resolves to `undefined` when the wallet reports no accounts (locked, or the
|
|
35
|
+
* site was disconnected in the wallet). When the wallet is on another chain than the requested one, wagmi's
|
|
36
|
+
* `switchChain` asks it to switch; when it declines, the connection stays on its chain.
|
|
37
|
+
* - `getLiveConnections` lists, as {@link EVMConnection} objects, the live wagmi connections that this adapter object
|
|
38
|
+
* opened or took over (with `connect` or `reconnect`) and has not disconnected. The record of their connectors lives
|
|
39
|
+
* in memory, in the adapter object. Connections that other code opened or restored on the same config (for example
|
|
40
|
+
* `WagmiProvider`, or a store with another adapter object) are not listed.
|
|
41
|
+
* - `disconnect` disconnects the given connection with wagmi's `disconnect`. Without a connection (or with one that is
|
|
42
|
+
* not connected), it disconnects only the live connections of `getLiveConnections` (of that connection's connector
|
|
43
|
+
* type), never a connector without a connection or a connection opened by other code: wagmi's injected connector
|
|
44
|
+
* sends `wallet_revokePermissions` on every disconnect, and wallets such as MetaMask revoke the site's permission for
|
|
45
|
+
* every tab of the origin. Two stores on one wagmi config with their own adapter objects do not close each other's
|
|
46
|
+
* wallets this way (a wallet both of them connected is still one wagmi connection).
|
|
28
47
|
* - `checkAndSwitchNetwork` asks the wallet to switch chains with `checkAndSwitchChain` from `@tuwaio/orbit-evm`.
|
|
29
48
|
* - `getBalance` reads the native balance through the wagmi transports and formats it with the chain's decimals.
|
|
30
49
|
* - `getExplorerUrl(url?, chainId?)` joins `url` to the block explorer of `chainId` (looked up in `chains`, then in
|
package/dist/index.d.ts
CHANGED
|
@@ -23,8 +23,27 @@ interface EVMConnection extends BaseConnector {
|
|
|
23
23
|
* through `formatConnectorName` from `@tuwaio/orbit-core` (for example, the `Safe` connector is `"evm:safe"`).
|
|
24
24
|
* - `connect` runs wagmi's `connect` with the requested chain and returns an {@link EVMConnection}: the account (the
|
|
25
25
|
* zero address if wagmi reports none), the chain (`1` if unknown), the first default RPC URL of the chain, the
|
|
26
|
-
* connector icon and a `signMessage` that signs with wagmi's `signMessage`.
|
|
27
|
-
*
|
|
26
|
+
* connector icon and a `signMessage` that signs with wagmi's `signMessage`. An injected wallet shows its connect
|
|
27
|
+
* prompt (wagmi requests `wallet_requestPermissions`, then `eth_requestAccounts`). A wallet that wagmi already holds
|
|
28
|
+
* in this page (an earlier store on the same config connected it, or `WagmiProvider` restored it) is taken over
|
|
29
|
+
* without a request: it becomes wagmi's current connection, and wagmi's `switchChain` asks it to move to the
|
|
30
|
+
* requested chain (when it declines, the connection stays on its chain).
|
|
31
|
+
* - `reconnect` restores a wallet without a prompt, for `initializeAutoConnect`: a wallet that wagmi already holds in
|
|
32
|
+
* this page is taken over as by `connect`; otherwise, when the connector reports authorized accounts
|
|
33
|
+
* (`eth_accounts` for injected wallets), wagmi's `connect` runs with `isReconnecting`, so the connector reads those
|
|
34
|
+
* accounts instead of asking for them. It resolves to `undefined` when the wallet reports no accounts (locked, or the
|
|
35
|
+
* site was disconnected in the wallet). When the wallet is on another chain than the requested one, wagmi's
|
|
36
|
+
* `switchChain` asks it to switch; when it declines, the connection stays on its chain.
|
|
37
|
+
* - `getLiveConnections` lists, as {@link EVMConnection} objects, the live wagmi connections that this adapter object
|
|
38
|
+
* opened or took over (with `connect` or `reconnect`) and has not disconnected. The record of their connectors lives
|
|
39
|
+
* in memory, in the adapter object. Connections that other code opened or restored on the same config (for example
|
|
40
|
+
* `WagmiProvider`, or a store with another adapter object) are not listed.
|
|
41
|
+
* - `disconnect` disconnects the given connection with wagmi's `disconnect`. Without a connection (or with one that is
|
|
42
|
+
* not connected), it disconnects only the live connections of `getLiveConnections` (of that connection's connector
|
|
43
|
+
* type), never a connector without a connection or a connection opened by other code: wagmi's injected connector
|
|
44
|
+
* sends `wallet_revokePermissions` on every disconnect, and wallets such as MetaMask revoke the site's permission for
|
|
45
|
+
* every tab of the origin. Two stores on one wagmi config with their own adapter objects do not close each other's
|
|
46
|
+
* wallets this way (a wallet both of them connected is still one wagmi connection).
|
|
28
47
|
* - `checkAndSwitchNetwork` asks the wallet to switch chains with `checkAndSwitchChain` from `@tuwaio/orbit-evm`.
|
|
29
48
|
* - `getBalance` reads the native balance through the wagmi transports and formats it with the chain's decimals.
|
|
30
49
|
* - `getExplorerUrl(url?, chainId?)` joins `url` to the block explorer of `chainId` (looked up in `chains`, then in
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitEvm=require('@tuwaio/orbit-evm'),core=require('@wagmi/core'),viem=require('viem'),chains=require('viem/chains'),utils=require('viem/utils');var
|
|
1
|
+
'use strict';var orbitCore=require('@tuwaio/orbit-core'),orbitEvm=require('@tuwaio/orbit-evm'),core=require('@wagmi/core'),viem=require('viem'),chains=require('viem/chains'),utils=require('viem/utils');var E=new Map;async function V({config:r,address:s,chainId:d,chains:c}){let h=`${Number(d)}:${s.toLowerCase()}`;if(E.has(h))return E.get(h);if(orbitEvm.createViemClient(Number(d),c)){let u=!!await core.getBytecode(r,{address:s,chainId:Number(d)});return E.set(h,u),u}else return false}function ve(r,s){if(!r)throw new Error("Satellite EVM adapter requires a wagmi config object.");let d=t=>orbitCore.getConnectorTypeFromName(orbitCore.OrbitAdapter.EVM,orbitCore.formatConnectorName(t.name)),c=t=>core.getConnectors(r).find(n=>d(n)===t),h=new Set,p=()=>[...r.state.connections.values()].filter(({connector:t})=>h.has(t.uid)),a=(t,n)=>{let e=core.getConnection(r);return {connectorType:t,address:e.address??viem.zeroAddress,chainId:e.chainId??chains.mainnet.id,rpcURL:e.chain?.rpcUrls.default.http[0]??chains.mainnet.rpcUrls.default.http[0],isConnected:e.isConnected,isContractAddress:false,icon:n?.icon?.trim(),connector:n,signMessage:o=>core.signMessage(r,{message:o})}},u=async(t,n,e)=>(r.state.current!==n.uid&&await core.switchConnection(r,{connector:n}),Number(e)&&core.getConnection(r).chainId!==Number(e)&&await core.switchChain(r,{chainId:Number(e),connector:n}).catch(()=>{}),h.add(n.uid),a(t,n));return {key:orbitCore.OrbitAdapter.EVM,connect:async({connectorType:t,chainId:n})=>{let e=c(t);if(!e)throw new Error("Cannot find connector with this wallet type");try{return r.state.connections.has(e.uid)?await u(t,e,n):(await core.connect(r,{connector:e,chainId:n}),h.add(e.uid),a(t,e))}catch(o){throw new Error(o instanceof Error?o.message:String(o),{cause:o})}},reconnect:async({connectorType:t,chainId:n})=>{let e=c(t);if(!e)throw new Error("Cannot find connector with this wallet type");try{if(!r.state.connections.has(e.uid)){if((await e.getAccounts().catch(()=>[])).length===0)return;let i={connector:e,isReconnecting:!0};r.state.connections.has(e.uid)||await core.connect(r,i);}return await u(t,e,n)}catch(o){throw new Error(o instanceof Error?o.message:String(o),{cause:o})}},getLiveConnections:async()=>p().map(({connector:t,accounts:n,chainId:e})=>{let o=core.getChains(r).find(({id:i})=>i===e);return {connectorType:d(t),address:n[0]??viem.zeroAddress,chainId:e,rpcURL:o?.rpcUrls.default.http[0]??chains.mainnet.rpcUrls.default.http[0],isConnected:true,isContractAddress:false,icon:t.icon?.trim(),connector:t,signMessage:i=>core.signMessage(r,{message:i,connector:t})}}),disconnect:async t=>{if(t&&t.isConnected){let{connector:e}=t;await core.disconnect(r,{connector:e}),e&&h.delete(e.uid);return}let n=p().filter(({connector:e})=>!t||d(e)===t.connectorType);for(let{connector:e}of n){h.delete(e.uid);try{await core.disconnect(r,{connector:e});}catch{}}},getConnectors:()=>{let t=core.getConnectors(r);return {adapter:orbitCore.OrbitAdapter.EVM,connectors:t.map(n=>n)}},checkAndSwitchNetwork:async t=>await orbitEvm.checkAndSwitchChain(Number(t),r),getBalance:async(t,n)=>{let e=await core.getBalance(r,{address:t,chainId:Number(n)});return {value:viem.formatUnits(e.value,e.decimals),symbol:e.symbol}},getExplorerUrl:(t,n)=>{let o=(n===void 0?core.getConnection(r).chain:s.find(i=>i.id===Number(n))??core.getChains(r).find(i=>i.id===Number(n)))?.blockExplorers?.default.url;if(o)return t?`${o.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`:o},getName:t=>orbitEvm.getName(t,s),getAvatar:t=>orbitEvm.getAvatar(t,s),getAddress:t=>orbitEvm.getAddress(t,s),checkIsContractAddress:async({address:t,chainId:n})=>{let e=core.getChains(r);return await V({config:r,address:t,chainId:n,chains:e})},getSafeConnectorChainId:async()=>{let n=core.getConnectors(r).find(e=>e.name==="Safe");if(n)return await n.getChainId()},switchConnection:async t=>{let n=c(t);if(!n)throw new Error(`Cannot find connector with type: ${t}`);try{await core.switchConnection(r,{connector:n});}catch(e){throw new Error(`Failed to switch to connector ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}}}F.type="impersonated";function F(r){let s=r.features??{},d=false,c,h;return core.createConnector(p=>({id:"impersonated",name:"Impersonated Connector",type:F.type,async setup(){c=p.chains[0].id;},async connect({chainId:a}={}){if(s.connectError)throw typeof s.connectError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to connect.")):s.connectError;let{request:u}=await this.getProvider(),t=await u({method:"eth_requestAccounts"}),n=await this.getChainId();return a&&n!==a&&(n=(await this.switchChain({chainId:a})).id),d=true,{accounts:t,chainId:n}},async disconnect(){d=false,h=void 0;},async getAccounts(){if(!d)throw new Error("Not connected connector");let{request:a}=await this.getProvider();return (await a({method:"eth_accounts"})).map(viem.getAddress)},async getChainId(){let{request:a}=await this.getProvider(),u=await a({method:"eth_chainId"});return viem.fromHex(u,"number")},async isAuthorized(){return d?!!(await this.getAccounts()).length:false},async switchChain({chainId:a}){let u=p.chains.find(n=>n.id===a);if(!u)throw new viem.SwitchChainError(new core.ChainNotConfiguredError);let{request:t}=await this.getProvider();return await t({method:"wallet_switchEthereumChain",params:[{chainId:viem.numberToHex(a)}]}),u},onAccountsChanged(a){a.length===0?this.onDisconnect():p.emitter.emit("change",{accounts:a.map(viem.getAddress)});},onChainChanged(a){let u=Number(a);p.emitter.emit("change",{chainId:u});},async onDisconnect(){p.emitter.emit("disconnect"),d=false,h=void 0;},async getProvider({chainId:a}={}){h=orbitCore.impersonatedHelpers?.getImpersonated()?[orbitCore.impersonatedHelpers.getImpersonated()||viem.zeroAddress]:void 0;let t=(p.chains.find(e=>e.id===a)??p.chains[0]).rpcUrls.default.http[0];return viem.custom({request:async({method:e,params:o})=>{if(e==="eth_chainId")return viem.numberToHex(c);if(e==="eth_requestAccounts"||e==="eth_accounts")return h??[];if(e==="eth_signTypedData_v4"&&s.signTypedDataError)throw typeof s.signTypedDataError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to sign typed data.")):s.signTypedDataError;if(e==="wallet_switchEthereumChain"){if(s.switchChainError)throw typeof s.switchChainError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to switch chain.")):s.switchChainError;c=viem.fromHex(o[0].chainId,"number"),this.onChainChanged(c.toString());return}if(e==="personal_sign"){if(s.signMessageError)throw typeof s.signMessageError=="boolean"?new viem.UserRejectedRequestError(new Error("Failed to sign message.")):s.signMessageError;e="eth_sign",o=[o[1],o[0]];}let i={method:e,params:o},{error:C,result:m}=await utils.rpc.http(t,{body:i});if(C)throw new viem.RpcRequestError({body:i,error:C,url:t});return m}})({retryCount:1})}}))}var Ue={allowedDomains:[/^https:\/\/([a-z0-9-]+\.)*gnosis-safe\.io$/,/^https:\/\/([a-z0-9-]+\.)*app\.safe\.global$/,/^https:\/\/([a-z0-9-]+\.)*metissafe\.tech$/],debug:false};var je=r=>r.reduce((s,d)=>{let c=d.id;return s[c]=viem.http(),s},{});function Je(r,s){let{wagmiConfig:d}=r,c=r.siwx??(r.siwe?{enabled:r.siwe.enabled,isSignedIn:r.siwe.isSignedIn,isRejected:r.siwe.isRejected}:void 0),{disconnect:h,updateActiveConnection:p}=s,a=()=>s.getState?.()??s,u=()=>{let o=c?.isRejected||c?.status==="error",i=c?.isSignedIn??c?.isAuthenticated??false;if(c?.enabled!==false&&!i&&o){let{activeConnection:m}=a();m&&h(m.connectorType);}},t=o=>{let{activeConnection:i,connectionError:C}=a();if(i&&orbitCore.getAdapterFromConnectorType(i.connectorType)!==orbitCore.OrbitAdapter.EVM)return;if(o.length===0){i&&h(i.connectorType);return}let m=core.getConnection(d);if(i&&orbitCore.getAdapterFromConnectorType(i.connectorType)!==orbitCore.OrbitAdapter.EVM||!m||C)return;let g=c?.address??c?.session?.address,T=c?.chainId??c?.session?.chainId;if((c?.isSignedIn??c?.isAuthenticated??false)&&i){let l=g&&(orbitCore.parseCaip10AccountId(g)?.address??g),L=m.address&&l&&m.address.toLowerCase()!==l.toLowerCase(),O=m.chainId&&T&&orbitCore.toEvmChainId(T)!==m.chainId;if(L||O){h(i.connectorType);return}}let x=m.connector,j={connectorType:x?`${orbitCore.OrbitAdapter.EVM}:${orbitCore.formatConnectorName(x.name)}`:i?.connectorType,address:m.address,chainId:m.chainId,rpcURL:m?.chain?.rpcUrls.default.http[0],isConnected:true,signMessage:l=>core.signMessage(d,{message:l})};p(j);};u();let{activeConnection:n}=a();if(n&&orbitCore.getAdapterFromConnectorType(n.connectorType)===orbitCore.OrbitAdapter.EVM){let o=core.getConnection(d);o&&o.isConnected&&p({signMessage:i=>core.signMessage(d,{message:i})});}return core.watchConnections(d,{onChange:t})}exports.checkIsWalletAddressContract=V;exports.createDefaultTransports=je;exports.createEVMConnectionsWatcher=Je;exports.impersonated=F;exports.safeSdkOptions=Ue;exports.satelliteEVMAdapter=ve;
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {OrbitAdapter,
|
|
1
|
+
import {OrbitAdapter,impersonatedHelpers,getAdapterFromConnectorType,parseCaip10AccountId,toEvmChainId,formatConnectorName,getConnectorTypeFromName}from'@tuwaio/orbit-core';import {createViemClient,getAddress,getAvatar,getName,checkAndSwitchChain}from'@tuwaio/orbit-evm';import {getBytecode,switchConnection,getConnectors,getChains,getConnection,getBalance,disconnect,signMessage,connect,createConnector,ChainNotConfiguredError,watchConnections,switchChain}from'@wagmi/core';import {formatUnits,zeroAddress,custom,numberToHex,UserRejectedRequestError,fromHex,RpcRequestError,getAddress as getAddress$1,SwitchChainError,http}from'viem';import {mainnet}from'viem/chains';import {rpc}from'viem/utils';var E=new Map;async function V({config:r,address:s,chainId:d,chains:c}){let h=`${Number(d)}:${s.toLowerCase()}`;if(E.has(h))return E.get(h);if(createViemClient(Number(d),c)){let u=!!await getBytecode(r,{address:s,chainId:Number(d)});return E.set(h,u),u}else return false}function ve(r,s){if(!r)throw new Error("Satellite EVM adapter requires a wagmi config object.");let d=t=>getConnectorTypeFromName(OrbitAdapter.EVM,formatConnectorName(t.name)),c=t=>getConnectors(r).find(n=>d(n)===t),h=new Set,p=()=>[...r.state.connections.values()].filter(({connector:t})=>h.has(t.uid)),a=(t,n)=>{let e=getConnection(r);return {connectorType:t,address:e.address??zeroAddress,chainId:e.chainId??mainnet.id,rpcURL:e.chain?.rpcUrls.default.http[0]??mainnet.rpcUrls.default.http[0],isConnected:e.isConnected,isContractAddress:false,icon:n?.icon?.trim(),connector:n,signMessage:o=>signMessage(r,{message:o})}},u=async(t,n,e)=>(r.state.current!==n.uid&&await switchConnection(r,{connector:n}),Number(e)&&getConnection(r).chainId!==Number(e)&&await switchChain(r,{chainId:Number(e),connector:n}).catch(()=>{}),h.add(n.uid),a(t,n));return {key:OrbitAdapter.EVM,connect:async({connectorType:t,chainId:n})=>{let e=c(t);if(!e)throw new Error("Cannot find connector with this wallet type");try{return r.state.connections.has(e.uid)?await u(t,e,n):(await connect(r,{connector:e,chainId:n}),h.add(e.uid),a(t,e))}catch(o){throw new Error(o instanceof Error?o.message:String(o),{cause:o})}},reconnect:async({connectorType:t,chainId:n})=>{let e=c(t);if(!e)throw new Error("Cannot find connector with this wallet type");try{if(!r.state.connections.has(e.uid)){if((await e.getAccounts().catch(()=>[])).length===0)return;let i={connector:e,isReconnecting:!0};r.state.connections.has(e.uid)||await connect(r,i);}return await u(t,e,n)}catch(o){throw new Error(o instanceof Error?o.message:String(o),{cause:o})}},getLiveConnections:async()=>p().map(({connector:t,accounts:n,chainId:e})=>{let o=getChains(r).find(({id:i})=>i===e);return {connectorType:d(t),address:n[0]??zeroAddress,chainId:e,rpcURL:o?.rpcUrls.default.http[0]??mainnet.rpcUrls.default.http[0],isConnected:true,isContractAddress:false,icon:t.icon?.trim(),connector:t,signMessage:i=>signMessage(r,{message:i,connector:t})}}),disconnect:async t=>{if(t&&t.isConnected){let{connector:e}=t;await disconnect(r,{connector:e}),e&&h.delete(e.uid);return}let n=p().filter(({connector:e})=>!t||d(e)===t.connectorType);for(let{connector:e}of n){h.delete(e.uid);try{await disconnect(r,{connector:e});}catch{}}},getConnectors:()=>{let t=getConnectors(r);return {adapter:OrbitAdapter.EVM,connectors:t.map(n=>n)}},checkAndSwitchNetwork:async t=>await checkAndSwitchChain(Number(t),r),getBalance:async(t,n)=>{let e=await getBalance(r,{address:t,chainId:Number(n)});return {value:formatUnits(e.value,e.decimals),symbol:e.symbol}},getExplorerUrl:(t,n)=>{let o=(n===void 0?getConnection(r).chain:s.find(i=>i.id===Number(n))??getChains(r).find(i=>i.id===Number(n)))?.blockExplorers?.default.url;if(o)return t?`${o.replace(/\/+$/,"")}/${t.replace(/^\/+/,"")}`:o},getName:t=>getName(t,s),getAvatar:t=>getAvatar(t,s),getAddress:t=>getAddress(t,s),checkIsContractAddress:async({address:t,chainId:n})=>{let e=getChains(r);return await V({config:r,address:t,chainId:n,chains:e})},getSafeConnectorChainId:async()=>{let n=getConnectors(r).find(e=>e.name==="Safe");if(n)return await n.getChainId()},switchConnection:async t=>{let n=c(t);if(!n)throw new Error(`Cannot find connector with type: ${t}`);try{await switchConnection(r,{connector:n});}catch(e){throw new Error(`Failed to switch to connector ${t}: ${e instanceof Error?e.message:String(e)}`,{cause:e})}}}}F.type="impersonated";function F(r){let s=r.features??{},d=false,c,h;return createConnector(p=>({id:"impersonated",name:"Impersonated Connector",type:F.type,async setup(){c=p.chains[0].id;},async connect({chainId:a}={}){if(s.connectError)throw typeof s.connectError=="boolean"?new UserRejectedRequestError(new Error("Failed to connect.")):s.connectError;let{request:u}=await this.getProvider(),t=await u({method:"eth_requestAccounts"}),n=await this.getChainId();return a&&n!==a&&(n=(await this.switchChain({chainId:a})).id),d=true,{accounts:t,chainId:n}},async disconnect(){d=false,h=void 0;},async getAccounts(){if(!d)throw new Error("Not connected connector");let{request:a}=await this.getProvider();return (await a({method:"eth_accounts"})).map(getAddress$1)},async getChainId(){let{request:a}=await this.getProvider(),u=await a({method:"eth_chainId"});return fromHex(u,"number")},async isAuthorized(){return d?!!(await this.getAccounts()).length:false},async switchChain({chainId:a}){let u=p.chains.find(n=>n.id===a);if(!u)throw new SwitchChainError(new ChainNotConfiguredError);let{request:t}=await this.getProvider();return await t({method:"wallet_switchEthereumChain",params:[{chainId:numberToHex(a)}]}),u},onAccountsChanged(a){a.length===0?this.onDisconnect():p.emitter.emit("change",{accounts:a.map(getAddress$1)});},onChainChanged(a){let u=Number(a);p.emitter.emit("change",{chainId:u});},async onDisconnect(){p.emitter.emit("disconnect"),d=false,h=void 0;},async getProvider({chainId:a}={}){h=impersonatedHelpers?.getImpersonated()?[impersonatedHelpers.getImpersonated()||zeroAddress]:void 0;let t=(p.chains.find(e=>e.id===a)??p.chains[0]).rpcUrls.default.http[0];return custom({request:async({method:e,params:o})=>{if(e==="eth_chainId")return numberToHex(c);if(e==="eth_requestAccounts"||e==="eth_accounts")return h??[];if(e==="eth_signTypedData_v4"&&s.signTypedDataError)throw typeof s.signTypedDataError=="boolean"?new UserRejectedRequestError(new Error("Failed to sign typed data.")):s.signTypedDataError;if(e==="wallet_switchEthereumChain"){if(s.switchChainError)throw typeof s.switchChainError=="boolean"?new UserRejectedRequestError(new Error("Failed to switch chain.")):s.switchChainError;c=fromHex(o[0].chainId,"number"),this.onChainChanged(c.toString());return}if(e==="personal_sign"){if(s.signMessageError)throw typeof s.signMessageError=="boolean"?new UserRejectedRequestError(new Error("Failed to sign message.")):s.signMessageError;e="eth_sign",o=[o[1],o[0]];}let i={method:e,params:o},{error:C,result:m}=await rpc.http(t,{body:i});if(C)throw new RpcRequestError({body:i,error:C,url:t});return m}})({retryCount:1})}}))}var Ue={allowedDomains:[/^https:\/\/([a-z0-9-]+\.)*gnosis-safe\.io$/,/^https:\/\/([a-z0-9-]+\.)*app\.safe\.global$/,/^https:\/\/([a-z0-9-]+\.)*metissafe\.tech$/],debug:false};var je=r=>r.reduce((s,d)=>{let c=d.id;return s[c]=http(),s},{});function Je(r,s){let{wagmiConfig:d}=r,c=r.siwx??(r.siwe?{enabled:r.siwe.enabled,isSignedIn:r.siwe.isSignedIn,isRejected:r.siwe.isRejected}:void 0),{disconnect:h,updateActiveConnection:p}=s,a=()=>s.getState?.()??s,u=()=>{let o=c?.isRejected||c?.status==="error",i=c?.isSignedIn??c?.isAuthenticated??false;if(c?.enabled!==false&&!i&&o){let{activeConnection:m}=a();m&&h(m.connectorType);}},t=o=>{let{activeConnection:i,connectionError:C}=a();if(i&&getAdapterFromConnectorType(i.connectorType)!==OrbitAdapter.EVM)return;if(o.length===0){i&&h(i.connectorType);return}let m=getConnection(d);if(i&&getAdapterFromConnectorType(i.connectorType)!==OrbitAdapter.EVM||!m||C)return;let g=c?.address??c?.session?.address,T=c?.chainId??c?.session?.chainId;if((c?.isSignedIn??c?.isAuthenticated??false)&&i){let l=g&&(parseCaip10AccountId(g)?.address??g),L=m.address&&l&&m.address.toLowerCase()!==l.toLowerCase(),O=m.chainId&&T&&toEvmChainId(T)!==m.chainId;if(L||O){h(i.connectorType);return}}let x=m.connector,j={connectorType:x?`${OrbitAdapter.EVM}:${formatConnectorName(x.name)}`:i?.connectorType,address:m.address,chainId:m.chainId,rpcURL:m?.chain?.rpcUrls.default.http[0],isConnected:true,signMessage:l=>signMessage(d,{message:l})};p(j);};u();let{activeConnection:n}=a();if(n&&getAdapterFromConnectorType(n.connectorType)===OrbitAdapter.EVM){let o=getConnection(d);o&&o.isConnected&&p({signMessage:i=>signMessage(d,{message:i})});}return watchConnections(d,{onChange:t})}export{V as checkIsWalletAddressContract,je as createDefaultTransports,Je as createEVMConnectionsWatcher,F as impersonated,Ue as safeSdkOptions,ve as satelliteEVMAdapter};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuwaio/satellite-evm",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Oleksandr Tkach",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@tuwaio/orbit-core": "^0.6.0",
|
|
55
55
|
"@tuwaio/orbit-evm": "^0.4.0",
|
|
56
|
-
"@tuwaio/satellite-core": "^0.
|
|
56
|
+
"@tuwaio/satellite-core": "^0.11.1",
|
|
57
57
|
"@wagmi/core": "^3.6.5",
|
|
58
58
|
"tsup": "^9.0.0",
|
|
59
59
|
"typescript": "6.0.3",
|