@tuwaio/orbit-evm 0.3.0 → 0.3.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 +79 -75
- package/dist/index.d.mts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +14 -5
package/README.md
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
# @tuwaio/orbit-evm
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@tuwaio/orbit-evm)
|
|
4
|
-
[](
|
|
4
|
+
[](https://github.com/TuwaIO/orbit/blob/main/packages/orbit-evm/LICENSE)
|
|
5
5
|
|
|
6
|
-
`@tuwaio/orbit-evm`
|
|
6
|
+
`@tuwaio/orbit-evm` is the EVM Layer 2 (L2) package of **Orbit Utils**, the Stage 1 primitives layer of the TUWA ecosystem. It wraps **`viem`** and **`@wagmi/core`** into small, framework-agnostic helpers: cached public clients, chain switching, ENS resolution, and ERC-4337 smart accounts built on Solady with a Pimlico bundler and paymaster. It does not use `ethers.js` or `web3.js`.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
## 🏛️ Core Capabilities
|
|
11
11
|
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **Strict Compile-Time Types:** Fully integrated with TypeScript standards v5.9+ and native Viem/Wagmi typings.
|
|
12
|
+
- **Public clients:** `createViemClient` returns a cached `viem` public client per chain, so repeated reads do not create new clients.
|
|
13
|
+
- **Chain alignment:** `checkAndSwitchChain` asks the connected wallet to switch networks only when it is on a different chain, and throws a readable error when the user rejects.
|
|
14
|
+
- **ENS resolution:** `getName`, `getAvatar` and `getAddress` always resolve against Ethereum Mainnet and cache results in memory; `isEnsName` tells names and addresses apart.
|
|
15
|
+
- **ERC-4337 smart accounts:** `createPimlicoSmartAccountClient` sets up a Solady smart account (EntryPoint v0.7), a bundler client and an optional gas-sponsoring paymaster in one call. Bundler and paymaster clients are cached in memory per endpoint. The building blocks (`createSoladySmartAccount`, `createBundlerRpcClient`, `createPimlicoPaymasterClient`, `createPimlicoRpcUrl`, `clearBundlerCache`) are exported for custom setups.
|
|
16
|
+
- **Chain lists:** `getEvmChains` and `isEvmChainList` extract and detect EVM chain IDs in mixed multi-chain configurations.
|
|
18
17
|
|
|
19
18
|
---
|
|
20
19
|
|
|
@@ -24,119 +23,124 @@
|
|
|
24
23
|
pnpm add @tuwaio/orbit-evm @wagmi/core viem
|
|
25
24
|
```
|
|
26
25
|
|
|
27
|
-
If using `@tuwaio/orbit-core` adapters and type definitions alongside EVM primitives:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
pnpm add @tuwaio/orbit-evm @tuwaio/orbit-core @wagmi/core viem
|
|
31
|
-
```
|
|
32
|
-
|
|
33
26
|
> [!IMPORTANT]
|
|
34
|
-
>
|
|
27
|
+
> `viem` (2.x) and `@wagmi/core` (3.x) are peer dependencies and must be installed alongside `@tuwaio/orbit-evm`.
|
|
35
28
|
|
|
36
29
|
---
|
|
37
30
|
|
|
38
|
-
## 🚀
|
|
39
|
-
|
|
40
|
-
### Cached Client Generation & Routing
|
|
31
|
+
## 🚀 Usage
|
|
41
32
|
|
|
42
|
-
|
|
33
|
+
### Cached public client
|
|
43
34
|
|
|
44
35
|
```typescript
|
|
45
36
|
import { createViemClient } from '@tuwaio/orbit-evm';
|
|
46
|
-
import { mainnet } from 'viem/chains';
|
|
37
|
+
import { mainnet, sepolia } from 'viem/chains';
|
|
38
|
+
|
|
39
|
+
const chains = [mainnet, sepolia] as const;
|
|
47
40
|
|
|
48
|
-
//
|
|
49
|
-
const client = createViemClient(
|
|
41
|
+
// Returns undefined (and logs a warning) if the chain ID is not in `chains`.
|
|
42
|
+
const client = createViemClient(sepolia.id, chains);
|
|
43
|
+
const blockNumber = await client?.getBlockNumber();
|
|
50
44
|
```
|
|
51
45
|
|
|
52
|
-
|
|
46
|
+
The client uses the chain's default RPC URL. The cache is keyed by chain ID and is rebuilt when that URL changes.
|
|
53
47
|
|
|
54
|
-
|
|
48
|
+
### Chain switching
|
|
55
49
|
|
|
56
50
|
```typescript
|
|
57
|
-
import { checkAndSwitchChain } from '@tuwaio/orbit-evm';
|
|
58
51
|
import { type Config } from '@wagmi/core';
|
|
52
|
+
import { checkAndSwitchChain } from '@tuwaio/orbit-evm';
|
|
59
53
|
|
|
60
|
-
declare const
|
|
54
|
+
declare const wagmiConfig: Config;
|
|
61
55
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
console.error('Chain switch rejected:', error);
|
|
68
|
-
}
|
|
56
|
+
try {
|
|
57
|
+
await checkAndSwitchChain(11155111, wagmiConfig);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
// "User rejected the request to switch network." or a generic switch error (original error in `cause`).
|
|
60
|
+
console.error(error);
|
|
69
61
|
}
|
|
70
62
|
```
|
|
71
63
|
|
|
72
|
-
###
|
|
73
|
-
|
|
74
|
-
Instantiate a fully configured Solady smart account client with automated Pimlico bundler and paymaster sponsorship:
|
|
64
|
+
### ENS resolution
|
|
75
65
|
|
|
76
66
|
```typescript
|
|
77
|
-
import {
|
|
78
|
-
import {
|
|
79
|
-
import { type Config } from '@wagmi/core';
|
|
67
|
+
import { getAddress, getAvatar, getName, isEnsName } from '@tuwaio/orbit-evm';
|
|
68
|
+
import { mainnet } from 'viem/chains';
|
|
80
69
|
|
|
81
|
-
|
|
70
|
+
const chains = [mainnet] as const;
|
|
82
71
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
chain: sepolia,
|
|
86
|
-
wagmiConfig,
|
|
87
|
-
apiKey: process.env.NEXT_PUBLIC_PIMLICO_API_KEY, // or custom bundlerUrl
|
|
88
|
-
sponsor: true, // Enables Pimlico paymaster gas sponsorship
|
|
89
|
-
});
|
|
72
|
+
const name = await getName('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', chains); // "vitalik.eth" or null
|
|
73
|
+
const avatar = name ? await getAvatar(name, chains) : null;
|
|
90
74
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
75
|
+
const input = 'vitalik.eth';
|
|
76
|
+
const address = isEnsName(input) ? await getAddress(input, chains) : null; // lowercased address or null
|
|
94
77
|
```
|
|
95
78
|
|
|
96
|
-
|
|
79
|
+
Lookups use the mainnet entry of `chains` when present (so your own RPC URL is used), otherwise viem's default mainnet RPC.
|
|
97
80
|
|
|
98
|
-
|
|
81
|
+
### ERC-4337 smart account with Pimlico
|
|
99
82
|
|
|
100
83
|
```typescript
|
|
101
|
-
import {
|
|
84
|
+
import { type Config } from '@wagmi/core';
|
|
85
|
+
import { createPimlicoSmartAccountClient } from '@tuwaio/orbit-evm';
|
|
86
|
+
import { sepolia } from 'viem/chains';
|
|
87
|
+
|
|
88
|
+
declare const wagmiConfig: Config;
|
|
89
|
+
|
|
90
|
+
const { account, bundlerClient } = await createPimlicoSmartAccountClient({
|
|
91
|
+
chain: sepolia,
|
|
92
|
+
wagmiConfig, // or pass `walletClient` directly
|
|
93
|
+
apiKey: process.env.NEXT_PUBLIC_PIMLICO_API_KEY, // or `bundlerUrl` for your own bundler endpoint
|
|
94
|
+
});
|
|
102
95
|
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
const userOpHash = await bundlerClient.sendUserOperation({
|
|
97
|
+
account,
|
|
98
|
+
calls: [{ to: '0x0000000000000000000000000000000000000000', value: 0n }],
|
|
99
|
+
});
|
|
100
|
+
const receipt = await bundlerClient.waitForUserOperationReceipt({ hash: userOpHash });
|
|
105
101
|
```
|
|
106
102
|
|
|
107
|
-
|
|
103
|
+
- A connected wallet is required: the EOA signs for the smart account.
|
|
104
|
+
- Gas sponsorship (`sponsor`) is on by default when `apiKey` or `bundlerUrl` is set. Without either, the public Pimlico endpoint is used and no paymaster is attached.
|
|
105
|
+
- The smart account uses viem's Solady implementation with its default EntryPoint v0.7 (`entryPoint07Address`).
|
|
106
|
+
- The account salt defaults to the owner address right-padded to 32 bytes (`pad(owner, { dir: 'right', size: 32 })`). This satisfies the Solady factory's owner-prefix check (`SaltDoesNotStartWith()`) and gives every owner a deterministic, unique account address. Pass `salt` to override it.
|
|
108
107
|
|
|
109
|
-
|
|
108
|
+
> [!WARNING]
|
|
109
|
+
> The Pimlico API key becomes part of the bundler URL used by the browser. Use a key restricted to your domains and sponsorship policies, or proxy the bundler through your backend and pass its address as `bundlerUrl`.
|
|
110
|
+
|
|
111
|
+
### Low-level bundler building blocks
|
|
110
112
|
|
|
111
113
|
```typescript
|
|
112
|
-
import {
|
|
114
|
+
import {
|
|
115
|
+
clearBundlerCache,
|
|
116
|
+
createBundlerRpcClient,
|
|
117
|
+
createPimlicoPaymasterClient,
|
|
118
|
+
createPimlicoRpcUrl,
|
|
119
|
+
} from '@tuwaio/orbit-evm';
|
|
113
120
|
|
|
114
|
-
//
|
|
115
|
-
const rpcUrl = createPimlicoRpcUrl({
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
});
|
|
121
|
+
// Resolution order: bundlerUrl → https://api.pimlico.io/v2/{chainId}/rpc?apikey=… → https://public.pimlico.io/v2/{chainId}/rpc
|
|
122
|
+
const rpcUrl = createPimlicoRpcUrl({ chainId: 11155111, apiKey: process.env.PIMLICO_API_KEY });
|
|
123
|
+
|
|
124
|
+
// Cached by resolved URL.
|
|
125
|
+
const paymasterClient = createPimlicoPaymasterClient({ chainId: 11155111, apiKey: process.env.PIMLICO_API_KEY });
|
|
119
126
|
|
|
120
|
-
//
|
|
127
|
+
// Cached by resolved URL, paymaster presence and client presence.
|
|
121
128
|
const bundlerClient = createBundlerRpcClient({
|
|
122
129
|
chainId: 11155111,
|
|
123
|
-
apiKey:
|
|
130
|
+
apiKey: process.env.PIMLICO_API_KEY,
|
|
131
|
+
paymaster: paymasterClient,
|
|
124
132
|
});
|
|
133
|
+
|
|
134
|
+
// Drops cached URLs, bundler and paymaster clients (e.g. after rotating the API key).
|
|
135
|
+
clearBundlerCache();
|
|
125
136
|
```
|
|
126
137
|
|
|
127
138
|
---
|
|
128
139
|
|
|
129
|
-
##
|
|
130
|
-
|
|
131
|
-
`@tuwaio/orbit-evm` exposes the following modules:
|
|
140
|
+
## 📚 API Reference
|
|
132
141
|
|
|
133
|
-
|
|
134
|
-
- **Chain Alignment:** `checkAndSwitchChain`, `normalizeChainId`.
|
|
135
|
-
- **Client Factory:** `createViemClient`, `clearViemClientCache`.
|
|
136
|
-
- **ENS Resolvers:** `getAddress`, `getAvatar`, `getName`, `isEnsName`.
|
|
137
|
-
|
|
138
|
-
---
|
|
142
|
+
Every export, with signatures and types generated from the source, is documented at **[orbit.docs.tuwa.io/packages/orbit-evm](https://orbit.docs.tuwa.io/packages/orbit-evm)**. For a full walkthrough of sovereign account abstraction with Orbit, Pulsar and Quasar, see the [ERC-4337 guide](https://docs.tuwa.io/guides/erc-4337-sovereign-account-abstraction).
|
|
139
143
|
|
|
140
144
|
## 📄 License
|
|
141
145
|
|
|
142
|
-
Licensed under the **Apache-2.0 License**. See the [LICENSE](
|
|
146
|
+
Licensed under the **Apache-2.0 License**. See the [LICENSE](https://github.com/TuwaIO/orbit/blob/main/packages/orbit-evm/LICENSE) file for details.
|
package/dist/index.d.mts
CHANGED
|
@@ -102,10 +102,11 @@ declare function createPimlicoRpcUrl(config: PimlicoUrlConfig): string;
|
|
|
102
102
|
*/
|
|
103
103
|
declare function createBundlerRpcClient(config: BundlerRpcClientConfig): BundlerClient<HttpTransport>;
|
|
104
104
|
/**
|
|
105
|
-
* Creates a Viem Paymaster Client configured with the resolved Pimlico RPC endpoint.
|
|
105
|
+
* Creates or retrieves a cached Viem Paymaster Client configured with the resolved Pimlico RPC endpoint.
|
|
106
|
+
* Side effect: stores the client in an in-memory cache keyed by the resolved RPC URL (see `clearBundlerCache`).
|
|
106
107
|
*
|
|
107
108
|
* @param config - Pimlico URL configuration.
|
|
108
|
-
* @returns PaymasterClient
|
|
109
|
+
* @returns Cached or newly instantiated PaymasterClient configured for Pimlico gas sponsorship.
|
|
109
110
|
*/
|
|
110
111
|
declare function createPimlicoPaymasterClient(config: PimlicoUrlConfig): PaymasterClient;
|
|
111
112
|
/**
|
|
@@ -125,17 +126,23 @@ declare function createSoladySmartAccount({ client, walletClient, salt, }: Creat
|
|
|
125
126
|
*/
|
|
126
127
|
declare function createPimlicoSmartAccountClient(config: PimlicoSmartAccountClientConfig): Promise<PimlicoSmartAccountClientResult>;
|
|
127
128
|
/**
|
|
128
|
-
* Clears the in-memory
|
|
129
|
-
* Useful for testing and resetting runtime state.
|
|
129
|
+
* Clears the in-memory caches of Pimlico URLs, Bundler clients and Paymaster clients.
|
|
130
|
+
* Useful for testing and resetting runtime state (e.g. after rotating an API key).
|
|
130
131
|
*/
|
|
131
132
|
declare function clearBundlerCache(): void;
|
|
132
133
|
|
|
133
134
|
/**
|
|
134
|
-
*
|
|
135
|
+
* Gets the EVM chain IDs from an app's viem chain configuration.
|
|
136
|
+
*
|
|
137
|
+
* @param appChains - The viem chains configured in the app.
|
|
138
|
+
* @returns The positive numeric chain IDs, or an empty array if no chains are provided.
|
|
135
139
|
*/
|
|
136
140
|
declare function getEvmChains(appChains?: readonly [Chain$1, ...Chain$1[]]): number[];
|
|
137
141
|
/**
|
|
138
|
-
* Type guard to check if a chain list contains EVM chain IDs
|
|
142
|
+
* Type guard to check if a chain list contains EVM chain IDs.
|
|
143
|
+
*
|
|
144
|
+
* @param chains - Mixed list of chain identifiers.
|
|
145
|
+
* @returns `true` if the list is non-empty and contains only numbers.
|
|
139
146
|
*/
|
|
140
147
|
declare function isEvmChainList(chains: (string | number)[]): chains is number[];
|
|
141
148
|
|
package/dist/index.d.ts
CHANGED
|
@@ -102,10 +102,11 @@ declare function createPimlicoRpcUrl(config: PimlicoUrlConfig): string;
|
|
|
102
102
|
*/
|
|
103
103
|
declare function createBundlerRpcClient(config: BundlerRpcClientConfig): BundlerClient<HttpTransport>;
|
|
104
104
|
/**
|
|
105
|
-
* Creates a Viem Paymaster Client configured with the resolved Pimlico RPC endpoint.
|
|
105
|
+
* Creates or retrieves a cached Viem Paymaster Client configured with the resolved Pimlico RPC endpoint.
|
|
106
|
+
* Side effect: stores the client in an in-memory cache keyed by the resolved RPC URL (see `clearBundlerCache`).
|
|
106
107
|
*
|
|
107
108
|
* @param config - Pimlico URL configuration.
|
|
108
|
-
* @returns PaymasterClient
|
|
109
|
+
* @returns Cached or newly instantiated PaymasterClient configured for Pimlico gas sponsorship.
|
|
109
110
|
*/
|
|
110
111
|
declare function createPimlicoPaymasterClient(config: PimlicoUrlConfig): PaymasterClient;
|
|
111
112
|
/**
|
|
@@ -125,17 +126,23 @@ declare function createSoladySmartAccount({ client, walletClient, salt, }: Creat
|
|
|
125
126
|
*/
|
|
126
127
|
declare function createPimlicoSmartAccountClient(config: PimlicoSmartAccountClientConfig): Promise<PimlicoSmartAccountClientResult>;
|
|
127
128
|
/**
|
|
128
|
-
* Clears the in-memory
|
|
129
|
-
* Useful for testing and resetting runtime state.
|
|
129
|
+
* Clears the in-memory caches of Pimlico URLs, Bundler clients and Paymaster clients.
|
|
130
|
+
* Useful for testing and resetting runtime state (e.g. after rotating an API key).
|
|
130
131
|
*/
|
|
131
132
|
declare function clearBundlerCache(): void;
|
|
132
133
|
|
|
133
134
|
/**
|
|
134
|
-
*
|
|
135
|
+
* Gets the EVM chain IDs from an app's viem chain configuration.
|
|
136
|
+
*
|
|
137
|
+
* @param appChains - The viem chains configured in the app.
|
|
138
|
+
* @returns The positive numeric chain IDs, or an empty array if no chains are provided.
|
|
135
139
|
*/
|
|
136
140
|
declare function getEvmChains(appChains?: readonly [Chain$1, ...Chain$1[]]): number[];
|
|
137
141
|
/**
|
|
138
|
-
* Type guard to check if a chain list contains EVM chain IDs
|
|
142
|
+
* Type guard to check if a chain list contains EVM chain IDs.
|
|
143
|
+
*
|
|
144
|
+
* @param chains - Mixed list of chain identifiers.
|
|
145
|
+
* @returns `true` if the list is non-empty and contains only numbers.
|
|
139
146
|
*/
|
|
140
147
|
declare function isEvmChainList(chains: (string | number)[]): chains is number[];
|
|
141
148
|
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var core=require('@wagmi/core'),viem=require('viem'),accountAbstraction=require('viem/account-abstraction'),accounts=require('viem/accounts'),chains=require('viem/chains'),ens=require('viem/ens');var m=new Map,p=new Map;function
|
|
2
|
-
exports.checkAndSwitchChain=
|
|
1
|
+
'use strict';var core=require('@wagmi/core'),viem=require('viem'),accountAbstraction=require('viem/account-abstraction'),accounts=require('viem/accounts'),chains=require('viem/chains'),ens=require('viem/ens');var m=new Map,p=new Map,C=new Map;function K(e){return e.bundlerUrl?`custom:${e.bundlerUrl.trim()}`:`${e.chainId}:${e.apiKey?.trim()??"public"}`}function N(e){let t=f(e),r=!!e.paymaster,n=!!e.client;return `${t}:pm=${r}:client=${n}`}function f(e){let t=K(e),r=m.get(t);if(r)return r;let n;return e.bundlerUrl?n=e.bundlerUrl.trim():e.apiKey?n=`https://api.pimlico.io/v2/${e.chainId}/rpc?apikey=${e.apiKey.trim()}`:n=`https://public.pimlico.io/v2/${e.chainId}/rpc`,m.set(t,n),n}function R(e){let t=N(e),r=p.get(t);if(r)return r;let n=f(e),i={...e};delete i.bundlerUrl,delete i.apiKey;let a=accountAbstraction.createBundlerClient({...i,transport:viem.http(n)});return p.set(t,a),a}function k(e){let t=f(e),r=C.get(t);if(r)return r;let n=accountAbstraction.createPaymasterClient({transport:viem.http(t)});return C.set(t,n),n}async function M({client:e,walletClient:t,salt:r}){if(!t.account)throw new Error("WalletClient must have an active account.");let n=t.account,i=accounts.toAccount({address:n.address,async signMessage({message:o}){return t.signMessage({account:n,message:o})},async signTransaction(o){return t.signTransaction({account:n,...o})},async signTypedData(o){return t.signTypedData({account:n,...o})}}),a=r??viem.pad(n.address,{dir:"right",size:32});return accountAbstraction.toSoladySmartAccount({client:e,owner:i,salt:a})}async function X(e){let{chain:t,apiKey:r,bundlerUrl:n,rpcUrl:i,salt:a,sponsor:o=!!(r||n)}=e,l=e.walletClient;if(!l&&e.wagmiConfig&&(l=await core.getWalletClient(e.wagmiConfig,{chainId:t.id})),!l||!l.account)throw new Error("Active wallet connection with account is required (provide walletClient or wagmiConfig).");let u=e.client??viem.createPublicClient({chain:t,transport:i?viem.http(i):viem.http()}),x=await M({client:u,walletClient:l,salt:a}),d=o&&(r||n)?k({chainId:t.id,apiKey:r,bundlerUrl:n}):void 0,S=R({chainId:t.id,apiKey:r,bundlerUrl:n,client:u,...d?{paymaster:d}:{}});return {account:x,bundlerClient:S,publicClient:u,paymasterClient:d}}function Y(){m.clear(),p.clear(),C.clear();}function I(e){return e!=null&&typeof e=="number"&&e>0}function _(e){return !e||e.length===0?[]:e.map(t=>t.id).filter(I)}function ee(e){return e.length>0&&e.every(t=>typeof t=="number")}async function ie(e,t){let{connector:r,chainId:n}=core.getConnection(t);if(r&&n!==e)try{await core.switchChain(t,{chainId:e});}catch(i){throw i?.cause?.name==="UserRejectedRequestError"?new Error("User rejected the request to switch network.",{cause:i}):(console.error("Failed to switch network:",i),new Error("An error occurred while switching the network.",{cause:i}))}}var g=new Map;function h(e,t){let r=t.find(i=>i.id===e),n=g.get(e);if(n&&n.chain?.rpcUrls.default.http[0]===r?.rpcUrls.default.http[0])return n;if(r){let i=viem.createPublicClient({chain:r,transport:viem.http()});return g.set(e,i),i}console.warn(`createViemClient: No chain configuration found for chainId ${e}. A client could not be created.`);}var w=new Map,P=new Map,b=new Map,y=e=>{let t=e.find(r=>r.id===chains.mainnet.id);return t?h(chains.mainnet.id,[t]):h(chains.mainnet.id,[chains.mainnet])},he=async(e,t)=>{let r=y(t);if(!r)return null;let n=w.get(e);if(n!==void 0)return n;try{let i=await ens.getEnsName(r,{address:e});return w.set(e,i),i}catch(i){return console.error(`ENS name lookup failed for address ${e}:`,i),null}},ye=async(e,t)=>{let r=y(t);if(!r)return null;let n=ens.normalize(e),i=P.get(n);if(i!==void 0)return i;try{let a=await ens.getEnsAvatar(r,{name:n});return P.set(n,a),a}catch(a){return console.error(`ENS avatar lookup failed for name ${e}:`,a),null}},ge=async(e,t)=>{let r=y(t);if(!r)return null;let n=ens.normalize(e),i=b.get(n);if(i!==void 0)return i;try{let a=await ens.getEnsAddress(r,{name:n}),o=a?a.toLowerCase():null;return b.set(n,o),o}catch(a){return console.error(`ENS address lookup failed for name ${e}:`,a),null}},we=e=>e.includes(".")&&!viem.isAddress(e);
|
|
2
|
+
exports.checkAndSwitchChain=ie;exports.clearBundlerCache=Y;exports.createBundlerRpcClient=R;exports.createPimlicoPaymasterClient=k;exports.createPimlicoRpcUrl=f;exports.createPimlicoSmartAccountClient=X;exports.createSoladySmartAccount=M;exports.createViemClient=h;exports.getAddress=ge;exports.getAvatar=ye;exports.getEvmChains=_;exports.getName=he;exports.isEnsName=we;exports.isEvmChainList=ee;
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {getWalletClient,getConnection,switchChain}from'@wagmi/core';import {http,pad,createPublicClient,isAddress}from'viem';import {createBundlerClient,createPaymasterClient,toSoladySmartAccount}from'viem/account-abstraction';import {toAccount}from'viem/accounts';import {mainnet}from'viem/chains';import {getEnsName,normalize,getEnsAvatar,getEnsAddress}from'viem/ens';var m=new Map,p=new Map;function
|
|
2
|
-
export{
|
|
1
|
+
import {getWalletClient,getConnection,switchChain}from'@wagmi/core';import {http,pad,createPublicClient,isAddress}from'viem';import {createBundlerClient,createPaymasterClient,toSoladySmartAccount}from'viem/account-abstraction';import {toAccount}from'viem/accounts';import {mainnet}from'viem/chains';import {getEnsName,normalize,getEnsAvatar,getEnsAddress}from'viem/ens';var m=new Map,p=new Map,C=new Map;function K(e){return e.bundlerUrl?`custom:${e.bundlerUrl.trim()}`:`${e.chainId}:${e.apiKey?.trim()??"public"}`}function N(e){let t=f(e),r=!!e.paymaster,n=!!e.client;return `${t}:pm=${r}:client=${n}`}function f(e){let t=K(e),r=m.get(t);if(r)return r;let n;return e.bundlerUrl?n=e.bundlerUrl.trim():e.apiKey?n=`https://api.pimlico.io/v2/${e.chainId}/rpc?apikey=${e.apiKey.trim()}`:n=`https://public.pimlico.io/v2/${e.chainId}/rpc`,m.set(t,n),n}function R(e){let t=N(e),r=p.get(t);if(r)return r;let n=f(e),i={...e};delete i.bundlerUrl,delete i.apiKey;let a=createBundlerClient({...i,transport:http(n)});return p.set(t,a),a}function k(e){let t=f(e),r=C.get(t);if(r)return r;let n=createPaymasterClient({transport:http(t)});return C.set(t,n),n}async function M({client:e,walletClient:t,salt:r}){if(!t.account)throw new Error("WalletClient must have an active account.");let n=t.account,i=toAccount({address:n.address,async signMessage({message:o}){return t.signMessage({account:n,message:o})},async signTransaction(o){return t.signTransaction({account:n,...o})},async signTypedData(o){return t.signTypedData({account:n,...o})}}),a=r??pad(n.address,{dir:"right",size:32});return toSoladySmartAccount({client:e,owner:i,salt:a})}async function X(e){let{chain:t,apiKey:r,bundlerUrl:n,rpcUrl:i,salt:a,sponsor:o=!!(r||n)}=e,l=e.walletClient;if(!l&&e.wagmiConfig&&(l=await getWalletClient(e.wagmiConfig,{chainId:t.id})),!l||!l.account)throw new Error("Active wallet connection with account is required (provide walletClient or wagmiConfig).");let u=e.client??createPublicClient({chain:t,transport:i?http(i):http()}),x=await M({client:u,walletClient:l,salt:a}),d=o&&(r||n)?k({chainId:t.id,apiKey:r,bundlerUrl:n}):void 0,S=R({chainId:t.id,apiKey:r,bundlerUrl:n,client:u,...d?{paymaster:d}:{}});return {account:x,bundlerClient:S,publicClient:u,paymasterClient:d}}function Y(){m.clear(),p.clear(),C.clear();}function I(e){return e!=null&&typeof e=="number"&&e>0}function _(e){return !e||e.length===0?[]:e.map(t=>t.id).filter(I)}function ee(e){return e.length>0&&e.every(t=>typeof t=="number")}async function ie(e,t){let{connector:r,chainId:n}=getConnection(t);if(r&&n!==e)try{await switchChain(t,{chainId:e});}catch(i){throw i?.cause?.name==="UserRejectedRequestError"?new Error("User rejected the request to switch network.",{cause:i}):(console.error("Failed to switch network:",i),new Error("An error occurred while switching the network.",{cause:i}))}}var g=new Map;function h(e,t){let r=t.find(i=>i.id===e),n=g.get(e);if(n&&n.chain?.rpcUrls.default.http[0]===r?.rpcUrls.default.http[0])return n;if(r){let i=createPublicClient({chain:r,transport:http()});return g.set(e,i),i}console.warn(`createViemClient: No chain configuration found for chainId ${e}. A client could not be created.`);}var w=new Map,P=new Map,b=new Map,y=e=>{let t=e.find(r=>r.id===mainnet.id);return t?h(mainnet.id,[t]):h(mainnet.id,[mainnet])},he=async(e,t)=>{let r=y(t);if(!r)return null;let n=w.get(e);if(n!==void 0)return n;try{let i=await getEnsName(r,{address:e});return w.set(e,i),i}catch(i){return console.error(`ENS name lookup failed for address ${e}:`,i),null}},ye=async(e,t)=>{let r=y(t);if(!r)return null;let n=normalize(e),i=P.get(n);if(i!==void 0)return i;try{let a=await getEnsAvatar(r,{name:n});return P.set(n,a),a}catch(a){return console.error(`ENS avatar lookup failed for name ${e}:`,a),null}},ge=async(e,t)=>{let r=y(t);if(!r)return null;let n=normalize(e),i=b.get(n);if(i!==void 0)return i;try{let a=await getEnsAddress(r,{name:n}),o=a?a.toLowerCase():null;return b.set(n,o),o}catch(a){return console.error(`ENS address lookup failed for name ${e}:`,a),null}},we=e=>e.includes(".")&&!isAddress(e);
|
|
2
|
+
export{ie as checkAndSwitchChain,Y as clearBundlerCache,R as createBundlerRpcClient,k as createPimlicoPaymasterClient,f as createPimlicoRpcUrl,X as createPimlicoSmartAccountClient,M as createSoladySmartAccount,h as createViemClient,ge as getAddress,ye as getAvatar,_ as getEvmChains,he as getName,we as isEnsName,ee as isEvmChainList};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuwaio/orbit-evm",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Oleksandr Tkach",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "L2 EVM package of Orbit Utils (TUWA): cached viem clients, chain switching, ENS resolution and ERC-4337 smart accounts (Solady + Pimlico bundler/paymaster), built on viem and @wagmi/core.",
|
|
8
8
|
"main": "./dist/index.js",
|
|
9
9
|
"module": "./dist/index.mjs",
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
@@ -16,9 +16,18 @@
|
|
|
16
16
|
"socket.json"
|
|
17
17
|
],
|
|
18
18
|
"keywords": [
|
|
19
|
+
"tuwa",
|
|
20
|
+
"orbit",
|
|
19
21
|
"web3",
|
|
20
|
-
"typescript",
|
|
21
22
|
"evm",
|
|
23
|
+
"viem",
|
|
24
|
+
"wagmi",
|
|
25
|
+
"ens",
|
|
26
|
+
"erc-4337",
|
|
27
|
+
"account-abstraction",
|
|
28
|
+
"pimlico",
|
|
29
|
+
"solady",
|
|
30
|
+
"typescript",
|
|
22
31
|
"headless"
|
|
23
32
|
],
|
|
24
33
|
"repository": {
|
|
@@ -43,8 +52,8 @@
|
|
|
43
52
|
"devDependencies": {
|
|
44
53
|
"@wagmi/core": "^3.6.5",
|
|
45
54
|
"tsup": "^8.5.1",
|
|
46
|
-
"typescript": "
|
|
47
|
-
"viem": "^2.56.
|
|
55
|
+
"typescript": "6.0.3",
|
|
56
|
+
"viem": "^2.56.9"
|
|
48
57
|
},
|
|
49
58
|
"scripts": {
|
|
50
59
|
"start": "tsup src/index.ts --watch",
|