@zyfai/sdk 0.1.26 → 0.1.28
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/LICENSE +1 -1
- package/README.md +21 -33
- package/dist/index.d.mts +7 -11
- package/dist/index.d.ts +7 -11
- package/dist/index.js +50 -225
- package/dist/index.mjs +55 -238
- package/package.json +2 -2
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Zyfai SDK
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@zyfai/sdk)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
|
|
6
|
-
TypeScript SDK for interacting with the
|
|
6
|
+
TypeScript SDK for interacting with the Zyfai Yield Optimization Engine. This SDK provides easy-to-use methods for deploying Safe smart wallets, managing DeFi positions, and optimizing yield across multiple protocols.
|
|
7
7
|
|
|
8
8
|
You can generate an api key from here: https://sdk.zyf.ai/
|
|
9
9
|
|
|
@@ -28,10 +28,8 @@ pnpm add @zyfai/sdk viem
|
|
|
28
28
|
## Prerequisites
|
|
29
29
|
|
|
30
30
|
1. **API Key**: Single API key for both Execution API (Safe deployment, transactions, session keys) and Data API (earnings, opportunities, analytics)
|
|
31
|
-
2. **Bundler API Key**: Required for Safe deployment. Get it from:
|
|
32
|
-
- [Pimlico](https://www.pimlico.io/) (Recommended)
|
|
33
31
|
|
|
34
|
-
**Get your API key from [
|
|
32
|
+
**Get your API key from [Zyfai Dashboard](https://sdk.zyf.ai)**
|
|
35
33
|
|
|
36
34
|
## Quick Start
|
|
37
35
|
|
|
@@ -44,8 +42,7 @@ import { ZyfaiSDK } from "@zyfai/sdk";
|
|
|
44
42
|
|
|
45
43
|
// Option 1: Full configuration object
|
|
46
44
|
const sdk = new ZyfaiSDK({
|
|
47
|
-
apiKey: "your-api-key",
|
|
48
|
-
bundlerApiKey: "your-bundler-api-key", // Required for Safe deployment
|
|
45
|
+
apiKey: "your-api-key",
|
|
49
46
|
environment: "production", // or 'staging' (default: 'production')
|
|
50
47
|
});
|
|
51
48
|
|
|
@@ -55,11 +52,10 @@ const sdk = new ZyfaiSDK("your-api-key");
|
|
|
55
52
|
|
|
56
53
|
**Configuration Options:**
|
|
57
54
|
|
|
58
|
-
| Option
|
|
59
|
-
|
|
|
60
|
-
| `apiKey`
|
|
61
|
-
| `
|
|
62
|
-
| `environment` | No | `"production"` or `"staging"` (default: `"production"`) |
|
|
55
|
+
| Option | Required | Description |
|
|
56
|
+
| ------------- | -------- | ---------------------------------------------------------------------------------------------------- |
|
|
57
|
+
| `apiKey` | Yes | API key for both Execution API and Data API (Safe deployment, transactions, session keys, analytics) |
|
|
58
|
+
| `environment` | No | `"production"` or `"staging"` (default: `"production"`) |
|
|
63
59
|
|
|
64
60
|
### Connect Account
|
|
65
61
|
|
|
@@ -124,16 +120,11 @@ const result = await sdk.deploySafe(userAddress, 8453);
|
|
|
124
120
|
if (result.success) {
|
|
125
121
|
console.log("Safe Address:", result.safeAddress);
|
|
126
122
|
console.log("Status:", result.status); // 'deployed' | 'failed'
|
|
127
|
-
|
|
128
|
-
if (result.alreadyDeployed) {
|
|
129
|
-
console.log("Safe was already deployed - no action needed");
|
|
130
|
-
} else {
|
|
131
|
-
console.log("Transaction Hash:", result.txHash);
|
|
132
|
-
}
|
|
123
|
+
console.log("Transaction Hash:", result.txHash);
|
|
133
124
|
}
|
|
134
125
|
```
|
|
135
126
|
|
|
136
|
-
**Note:** The SDK proactively checks if the Safe is already deployed before attempting deployment. If it exists, it returns
|
|
127
|
+
**Note:** The SDK proactively checks if the Safe is already deployed before attempting deployment. If it exists, it returns early without making any transactions.
|
|
137
128
|
|
|
138
129
|
### 2. Multi-Chain Support
|
|
139
130
|
|
|
@@ -176,10 +167,9 @@ new ZyfaiSDK(config: SDKConfig | string)
|
|
|
176
167
|
- `config`: Configuration object or API key string
|
|
177
168
|
- If a string is provided, it's treated as the `apiKey`
|
|
178
169
|
- If an object is provided:
|
|
179
|
-
- `apiKey` (string): Your
|
|
170
|
+
- `apiKey` (string): Your Zyfai API key (required)
|
|
180
171
|
- `environment` ('production' | 'staging', optional): API environment (default: 'production')
|
|
181
|
-
- `
|
|
182
|
-
- `rpcUrls` (object, optional): Custom RPC URLs per chain to avoid rate limiting
|
|
172
|
+
- `rpcUrls` (object, optional): Custom RPC URLs per chain to avoid rate limiting (optional, only needed for local operations like `getSmartWalletAddress`)
|
|
183
173
|
- `8453` (string, optional): Base Mainnet RPC URL
|
|
184
174
|
- `42161` (string, optional): Arbitrum One RPC URL
|
|
185
175
|
- `9745` (string, optional): Plasma Mainnet RPC URL
|
|
@@ -193,14 +183,12 @@ const sdk = new ZyfaiSDK("your-api-key");
|
|
|
193
183
|
// Option 2: Object initialization (full configuration)
|
|
194
184
|
const sdk = new ZyfaiSDK({
|
|
195
185
|
apiKey: "your-api-key",
|
|
196
|
-
bundlerApiKey: "your-bundler-api-key",
|
|
197
186
|
environment: "production",
|
|
198
187
|
});
|
|
199
188
|
|
|
200
189
|
// Option 3: With custom RPC URLs (recommended to avoid rate limiting)
|
|
201
190
|
const sdk = new ZyfaiSDK({
|
|
202
191
|
apiKey: "your-api-key",
|
|
203
|
-
bundlerApiKey: "your-bundler-api-key",
|
|
204
192
|
environment: "production",
|
|
205
193
|
rpcUrls: {
|
|
206
194
|
8453: "https://base-mainnet.g.alchemy.com/v2/YOUR_API_KEY", // Base
|
|
@@ -283,7 +271,7 @@ Get the Smart Wallet (Safe) address for a user.
|
|
|
283
271
|
|
|
284
272
|
##### `deploySafe(userAddress: string, chainId: SupportedChainId): Promise<DeploySafeResponse>`
|
|
285
273
|
|
|
286
|
-
Deploy a Safe smart wallet for a user.
|
|
274
|
+
Deploy a Safe smart wallet for a user. **Deployment is handled by the backend API**, which manages all RPC calls and bundler interactions. This avoids rate limiting issues.
|
|
287
275
|
|
|
288
276
|
**Parameters:**
|
|
289
277
|
|
|
@@ -298,10 +286,14 @@ Deploy a Safe smart wallet for a user.
|
|
|
298
286
|
safeAddress: Address;
|
|
299
287
|
txHash: string;
|
|
300
288
|
status: "deployed" | "failed";
|
|
301
|
-
alreadyDeployed?: boolean; // True if the Safe was already deployed (no new deployment needed)
|
|
302
289
|
}
|
|
303
290
|
```
|
|
304
291
|
|
|
292
|
+
**Note:**
|
|
293
|
+
|
|
294
|
+
- User must be authenticated (automatically done via `connectAccount()`)
|
|
295
|
+
- Backend handles all RPC calls, avoiding rate limiting
|
|
296
|
+
|
|
305
297
|
##### `addWalletToSdk(walletAddress: string): Promise<AddWalletToSdkResponse>`
|
|
306
298
|
|
|
307
299
|
Add a wallet address to the SDK API key's allowedWallets list. This endpoint requires SDK API key authentication (API key starting with "zyfai\_").
|
|
@@ -327,7 +319,7 @@ Session keys enable delegated transaction execution without exposing the main pr
|
|
|
327
319
|
|
|
328
320
|
#### Simple Usage (Recommended)
|
|
329
321
|
|
|
330
|
-
The SDK automatically fetches optimal session configuration from
|
|
322
|
+
The SDK automatically fetches optimal session configuration from Zyfai API:
|
|
331
323
|
|
|
332
324
|
```typescript
|
|
333
325
|
// SDK automatically:
|
|
@@ -383,7 +375,7 @@ if (result.success) {
|
|
|
383
375
|
|
|
384
376
|
- Amount must be in least decimal units. For USDC (6 decimals): 1 USDC = 1000000
|
|
385
377
|
- Token address is automatically selected based on chain (USDC for Base/Arbitrum, USDT for Plasma)
|
|
386
|
-
- The SDK automatically authenticates via SIWE before logging the deposit with
|
|
378
|
+
- The SDK automatically authenticates via SIWE before logging the deposit with Zyfai's API, so no extra steps are required on your end once the transfer confirms
|
|
387
379
|
|
|
388
380
|
### 5. Withdraw Funds
|
|
389
381
|
|
|
@@ -710,7 +702,6 @@ import { ZyfaiSDK } from "@zyfai/sdk";
|
|
|
710
702
|
async function main() {
|
|
711
703
|
const sdk = new ZyfaiSDK({
|
|
712
704
|
apiKey: process.env.ZYFAI_API_KEY!,
|
|
713
|
-
bundlerApiKey: process.env.BUNDLER_API_KEY!,
|
|
714
705
|
});
|
|
715
706
|
|
|
716
707
|
// Connect account (automatically authenticates via SIWE)
|
|
@@ -865,9 +856,6 @@ For running the examples, set up the following environment variables:
|
|
|
865
856
|
# Required: API key (used for both Execution API and Data API)
|
|
866
857
|
ZYFAI_API_KEY=your-api-key
|
|
867
858
|
|
|
868
|
-
# Required for Safe deployment: Bundler API key (e.g., Pimlico)
|
|
869
|
-
BUNDLER_API_KEY=your-pimlico-api-key
|
|
870
|
-
|
|
871
859
|
# Required for examples: Private key for signing transactions
|
|
872
860
|
# WARNING: Never commit your private key to version control!
|
|
873
861
|
PRIVATE_KEY=0x...
|
|
@@ -914,7 +902,7 @@ If `withdrawFunds` returns without a `txHash`, the withdrawal is being processed
|
|
|
914
902
|
|
|
915
903
|
### Data API CORS Errors
|
|
916
904
|
|
|
917
|
-
Some Data API endpoints may require server-side CORS configuration. If you see CORS errors for endpoints like `onchain-earnings`, `calculate-onchain-earnings`, or `opportunities`, contact
|
|
905
|
+
Some Data API endpoints may require server-side CORS configuration. If you see CORS errors for endpoints like `onchain-earnings`, `calculate-onchain-earnings`, or `opportunities`, contact Zyfai support to ensure your origin is whitelisted.
|
|
918
906
|
|
|
919
907
|
## Contributing
|
|
920
908
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Chain, PublicClient } from 'viem';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Zyfai SDK Types
|
|
5
5
|
*/
|
|
6
6
|
type Address = `0x${string}`;
|
|
7
7
|
type Hex = `0x${string}`;
|
|
@@ -14,7 +14,6 @@ interface RpcUrlsConfig {
|
|
|
14
14
|
interface SDKConfig {
|
|
15
15
|
apiKey: string;
|
|
16
16
|
environment?: Environment;
|
|
17
|
-
bundlerApiKey?: string;
|
|
18
17
|
rpcUrls?: RpcUrlsConfig;
|
|
19
18
|
}
|
|
20
19
|
interface DeploySafeResponse {
|
|
@@ -22,8 +21,6 @@ interface DeploySafeResponse {
|
|
|
22
21
|
safeAddress: Address;
|
|
23
22
|
txHash: string;
|
|
24
23
|
status: "deployed" | "failed";
|
|
25
|
-
/** True if the Safe was already deployed (no new deployment needed) */
|
|
26
|
-
alreadyDeployed?: boolean;
|
|
27
24
|
}
|
|
28
25
|
/** @internal */
|
|
29
26
|
interface UpdateUserProfileRequest {
|
|
@@ -407,14 +404,13 @@ declare const isSupportedChain: (chainId: number) => chainId is SupportedChainId
|
|
|
407
404
|
declare const getSupportedChainIds: () => SupportedChainId[];
|
|
408
405
|
|
|
409
406
|
/**
|
|
410
|
-
*
|
|
407
|
+
* Zyfai SDK Main Class
|
|
411
408
|
*/
|
|
412
409
|
|
|
413
410
|
declare class ZyfaiSDK {
|
|
414
411
|
private httpClient;
|
|
415
412
|
private signer;
|
|
416
413
|
private walletClient;
|
|
417
|
-
private bundlerApiKey?;
|
|
418
414
|
private authenticatedUserId;
|
|
419
415
|
private hasActiveSessionKey;
|
|
420
416
|
private environment;
|
|
@@ -519,7 +515,7 @@ declare class ZyfaiSDK {
|
|
|
519
515
|
*/
|
|
520
516
|
deploySafe(userAddress: string, chainId: SupportedChainId): Promise<DeploySafeResponse>;
|
|
521
517
|
/**
|
|
522
|
-
* Create session key with auto-fetched configuration from
|
|
518
|
+
* Create session key with auto-fetched configuration from Zyfai API
|
|
523
519
|
* This is the simplified method that automatically fetches session configuration
|
|
524
520
|
*
|
|
525
521
|
* @param userAddress - User's EOA or Safe address
|
|
@@ -548,7 +544,7 @@ declare class ZyfaiSDK {
|
|
|
548
544
|
*/
|
|
549
545
|
private updateUserProtocols;
|
|
550
546
|
/**
|
|
551
|
-
* Activate session key via
|
|
547
|
+
* Activate session key via Zyfai API
|
|
552
548
|
*/
|
|
553
549
|
private activateSessionKey;
|
|
554
550
|
/**
|
|
@@ -581,7 +577,7 @@ declare class ZyfaiSDK {
|
|
|
581
577
|
depositFunds(userAddress: string, chainId: SupportedChainId, amount: string): Promise<DepositResponse>;
|
|
582
578
|
/**
|
|
583
579
|
* Withdraw funds from Safe smart wallet
|
|
584
|
-
* Initiates a withdrawal request to the
|
|
580
|
+
* Initiates a withdrawal request to the Zyfai API
|
|
585
581
|
* Note: The withdrawal is processed asynchronously, so txHash may not be immediately available
|
|
586
582
|
* Funds are always withdrawn to the Safe owner's address (userAddress)
|
|
587
583
|
*
|
|
@@ -653,7 +649,7 @@ declare class ZyfaiSDK {
|
|
|
653
649
|
*/
|
|
654
650
|
getUserDetails(): Promise<UserDetailsResponse>;
|
|
655
651
|
/**
|
|
656
|
-
* Get total value locked (TVL) across all
|
|
652
|
+
* Get total value locked (TVL) across all Zyfai accounts
|
|
657
653
|
*
|
|
658
654
|
* @returns Total TVL in USD and breakdown by chain
|
|
659
655
|
*
|
|
@@ -665,7 +661,7 @@ declare class ZyfaiSDK {
|
|
|
665
661
|
*/
|
|
666
662
|
getTVL(): Promise<TVLResponse>;
|
|
667
663
|
/**
|
|
668
|
-
* Get total volume across all
|
|
664
|
+
* Get total volume across all Zyfai accounts
|
|
669
665
|
*
|
|
670
666
|
* @returns Total volume in USD
|
|
671
667
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Chain, PublicClient } from 'viem';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Zyfai SDK Types
|
|
5
5
|
*/
|
|
6
6
|
type Address = `0x${string}`;
|
|
7
7
|
type Hex = `0x${string}`;
|
|
@@ -14,7 +14,6 @@ interface RpcUrlsConfig {
|
|
|
14
14
|
interface SDKConfig {
|
|
15
15
|
apiKey: string;
|
|
16
16
|
environment?: Environment;
|
|
17
|
-
bundlerApiKey?: string;
|
|
18
17
|
rpcUrls?: RpcUrlsConfig;
|
|
19
18
|
}
|
|
20
19
|
interface DeploySafeResponse {
|
|
@@ -22,8 +21,6 @@ interface DeploySafeResponse {
|
|
|
22
21
|
safeAddress: Address;
|
|
23
22
|
txHash: string;
|
|
24
23
|
status: "deployed" | "failed";
|
|
25
|
-
/** True if the Safe was already deployed (no new deployment needed) */
|
|
26
|
-
alreadyDeployed?: boolean;
|
|
27
24
|
}
|
|
28
25
|
/** @internal */
|
|
29
26
|
interface UpdateUserProfileRequest {
|
|
@@ -407,14 +404,13 @@ declare const isSupportedChain: (chainId: number) => chainId is SupportedChainId
|
|
|
407
404
|
declare const getSupportedChainIds: () => SupportedChainId[];
|
|
408
405
|
|
|
409
406
|
/**
|
|
410
|
-
*
|
|
407
|
+
* Zyfai SDK Main Class
|
|
411
408
|
*/
|
|
412
409
|
|
|
413
410
|
declare class ZyfaiSDK {
|
|
414
411
|
private httpClient;
|
|
415
412
|
private signer;
|
|
416
413
|
private walletClient;
|
|
417
|
-
private bundlerApiKey?;
|
|
418
414
|
private authenticatedUserId;
|
|
419
415
|
private hasActiveSessionKey;
|
|
420
416
|
private environment;
|
|
@@ -519,7 +515,7 @@ declare class ZyfaiSDK {
|
|
|
519
515
|
*/
|
|
520
516
|
deploySafe(userAddress: string, chainId: SupportedChainId): Promise<DeploySafeResponse>;
|
|
521
517
|
/**
|
|
522
|
-
* Create session key with auto-fetched configuration from
|
|
518
|
+
* Create session key with auto-fetched configuration from Zyfai API
|
|
523
519
|
* This is the simplified method that automatically fetches session configuration
|
|
524
520
|
*
|
|
525
521
|
* @param userAddress - User's EOA or Safe address
|
|
@@ -548,7 +544,7 @@ declare class ZyfaiSDK {
|
|
|
548
544
|
*/
|
|
549
545
|
private updateUserProtocols;
|
|
550
546
|
/**
|
|
551
|
-
* Activate session key via
|
|
547
|
+
* Activate session key via Zyfai API
|
|
552
548
|
*/
|
|
553
549
|
private activateSessionKey;
|
|
554
550
|
/**
|
|
@@ -581,7 +577,7 @@ declare class ZyfaiSDK {
|
|
|
581
577
|
depositFunds(userAddress: string, chainId: SupportedChainId, amount: string): Promise<DepositResponse>;
|
|
582
578
|
/**
|
|
583
579
|
* Withdraw funds from Safe smart wallet
|
|
584
|
-
* Initiates a withdrawal request to the
|
|
580
|
+
* Initiates a withdrawal request to the Zyfai API
|
|
585
581
|
* Note: The withdrawal is processed asynchronously, so txHash may not be immediately available
|
|
586
582
|
* Funds are always withdrawn to the Safe owner's address (userAddress)
|
|
587
583
|
*
|
|
@@ -653,7 +649,7 @@ declare class ZyfaiSDK {
|
|
|
653
649
|
*/
|
|
654
650
|
getUserDetails(): Promise<UserDetailsResponse>;
|
|
655
651
|
/**
|
|
656
|
-
* Get total value locked (TVL) across all
|
|
652
|
+
* Get total value locked (TVL) across all Zyfai accounts
|
|
657
653
|
*
|
|
658
654
|
* @returns Total TVL in USD and breakdown by chain
|
|
659
655
|
*
|
|
@@ -665,7 +661,7 @@ declare class ZyfaiSDK {
|
|
|
665
661
|
*/
|
|
666
662
|
getTVL(): Promise<TVLResponse>;
|
|
667
663
|
/**
|
|
668
|
-
* Get total volume across all
|
|
664
|
+
* Get total volume across all Zyfai accounts
|
|
669
665
|
*
|
|
670
666
|
* @returns Total volume in USD
|
|
671
667
|
*
|
package/dist/index.js
CHANGED
|
@@ -61,6 +61,8 @@ var ENDPOINTS = {
|
|
|
61
61
|
USER_ME: "/users/me",
|
|
62
62
|
USER_WITHDRAW: "/users/withdraw",
|
|
63
63
|
PARTIAL_WITHDRAW: "/users/partial-withdraw",
|
|
64
|
+
// Safe Deployment (single endpoint)
|
|
65
|
+
SAFE_DEPLOY: "/users/safe-deploy",
|
|
64
66
|
// Session Keys
|
|
65
67
|
SESSION_KEYS_CONFIG: "/session-keys/config",
|
|
66
68
|
SESSION_KEYS_ADD: "/session-keys/add",
|
|
@@ -433,120 +435,18 @@ var isSupportedChain = (chainId) => {
|
|
|
433
435
|
var getSupportedChainIds = () => {
|
|
434
436
|
return Object.keys(CHAINS).map(Number);
|
|
435
437
|
};
|
|
436
|
-
var getBundlerUrl = (chainId, bundlerApiKey, bundlerProvider = "pimlico") => {
|
|
437
|
-
if (!bundlerApiKey) {
|
|
438
|
-
throw new Error("Bundler API key is required for Safe deployment");
|
|
439
|
-
}
|
|
440
|
-
switch (bundlerProvider) {
|
|
441
|
-
case "pimlico":
|
|
442
|
-
return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${bundlerApiKey}`;
|
|
443
|
-
case "custom":
|
|
444
|
-
return bundlerApiKey;
|
|
445
|
-
default:
|
|
446
|
-
throw new Error(`Unsupported bundler provider: ${bundlerProvider}`);
|
|
447
|
-
}
|
|
448
|
-
};
|
|
449
438
|
|
|
450
439
|
// src/utils/safe-account.ts
|
|
451
440
|
var import_module_sdk = require("@rhinestone/module-sdk");
|
|
452
|
-
var import_permissionless = require("permissionless");
|
|
453
|
-
var import_erc7579 = require("permissionless/actions/erc7579");
|
|
454
|
-
var import_pimlico = require("permissionless/clients/pimlico");
|
|
455
441
|
var import_accounts = require("permissionless/accounts");
|
|
456
442
|
var import_viem3 = require("viem");
|
|
457
443
|
var import_account_abstraction = require("viem/account-abstraction");
|
|
458
|
-
var import_actions = require("permissionless/actions");
|
|
459
|
-
var import_account_abstraction2 = require("viem/account-abstraction");
|
|
460
444
|
var SAFE_7579_ADDRESS = "0x7579EE8307284F293B1927136486880611F20002";
|
|
461
445
|
var ERC7579_LAUNCHPAD_ADDRESS = "0x7579011aB74c46090561ea277Ba79D510c6C00ff";
|
|
462
446
|
var ACCOUNT_SALTS = {
|
|
463
447
|
staging: "zyfai-staging",
|
|
464
448
|
production: "zyfai"
|
|
465
449
|
};
|
|
466
|
-
var MODULE_TYPE_IDS = {
|
|
467
|
-
validator: 1n,
|
|
468
|
-
executor: 2n,
|
|
469
|
-
fallback: 3n,
|
|
470
|
-
hook: 4n
|
|
471
|
-
};
|
|
472
|
-
var SMART_SESSIONS_FALLBACK = {
|
|
473
|
-
module: "0x12cae64c42f362e7d5a847c2d33388373f629177",
|
|
474
|
-
address: "0x12cae64c42f362e7d5a847c2d33388373f629177",
|
|
475
|
-
type: "fallback",
|
|
476
|
-
selector: (0, import_viem3.encodeAbiParameters)(
|
|
477
|
-
[{ name: "functionSignature", type: "bytes4" }],
|
|
478
|
-
["0x84b0196e"]
|
|
479
|
-
),
|
|
480
|
-
initData: "0x84b0196e00000000000000000000000000000000000000000000000000000000fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
|
|
481
|
-
};
|
|
482
|
-
var INTENT_EXECUTOR = {
|
|
483
|
-
address: "0x00000000005aD9ce1f5035FD62CA96CEf16AdAAF",
|
|
484
|
-
type: "executor",
|
|
485
|
-
initData: "0x"
|
|
486
|
-
};
|
|
487
|
-
var PROXY_EXECUTOR = {
|
|
488
|
-
address: "0xF659d30D4EB88B06A909F20839D8959Bd77d8790",
|
|
489
|
-
type: "executor",
|
|
490
|
-
initData: "0x"
|
|
491
|
-
};
|
|
492
|
-
var getModulesToInstall = (chainId) => {
|
|
493
|
-
const smartSessions = (0, import_module_sdk.getSmartSessionsValidator)({});
|
|
494
|
-
const accountLockerHook = (0, import_module_sdk.getAccountLockerHook)({ isOmniMode: true });
|
|
495
|
-
const accountLockerSourceExecutor = (0, import_module_sdk.getAccountLockerSourceExecutor)();
|
|
496
|
-
const accountLockerTargetExecutor = (0, import_module_sdk.getAccountLockerTargetExecutor)();
|
|
497
|
-
if (chainId === 9745) {
|
|
498
|
-
return [
|
|
499
|
-
smartSessions,
|
|
500
|
-
SMART_SESSIONS_FALLBACK,
|
|
501
|
-
INTENT_EXECUTOR,
|
|
502
|
-
PROXY_EXECUTOR
|
|
503
|
-
];
|
|
504
|
-
}
|
|
505
|
-
return [
|
|
506
|
-
smartSessions,
|
|
507
|
-
{
|
|
508
|
-
...accountLockerHook,
|
|
509
|
-
type: "executor"
|
|
510
|
-
},
|
|
511
|
-
accountLockerSourceExecutor,
|
|
512
|
-
accountLockerTargetExecutor,
|
|
513
|
-
SMART_SESSIONS_FALLBACK,
|
|
514
|
-
INTENT_EXECUTOR,
|
|
515
|
-
PROXY_EXECUTOR
|
|
516
|
-
];
|
|
517
|
-
};
|
|
518
|
-
var getInstallModuleCallData = (module2) => {
|
|
519
|
-
return (0, import_viem3.encodeFunctionData)({
|
|
520
|
-
abi: [
|
|
521
|
-
{
|
|
522
|
-
type: "function",
|
|
523
|
-
name: "installModule",
|
|
524
|
-
inputs: [
|
|
525
|
-
{
|
|
526
|
-
type: "uint256",
|
|
527
|
-
name: "moduleTypeId"
|
|
528
|
-
},
|
|
529
|
-
{
|
|
530
|
-
type: "address",
|
|
531
|
-
name: "module"
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
type: "bytes",
|
|
535
|
-
name: "initData"
|
|
536
|
-
}
|
|
537
|
-
],
|
|
538
|
-
outputs: [],
|
|
539
|
-
stateMutability: "nonpayable"
|
|
540
|
-
}
|
|
541
|
-
],
|
|
542
|
-
functionName: "installModule",
|
|
543
|
-
args: [
|
|
544
|
-
MODULE_TYPE_IDS[module2.type],
|
|
545
|
-
module2.address,
|
|
546
|
-
module2.initData || "0x"
|
|
547
|
-
]
|
|
548
|
-
});
|
|
549
|
-
};
|
|
550
450
|
var getSafeAccount = async (config) => {
|
|
551
451
|
const {
|
|
552
452
|
owner,
|
|
@@ -579,10 +479,13 @@ var getSafeAccount = async (config) => {
|
|
|
579
479
|
threshold: 1
|
|
580
480
|
});
|
|
581
481
|
const saltHex = (0, import_viem3.fromHex)((0, import_viem3.toHex)(effectiveSalt), "bigint");
|
|
482
|
+
const tempOwner = {
|
|
483
|
+
address: formattedEffectiveAddress,
|
|
484
|
+
type: "json-rpc"
|
|
485
|
+
};
|
|
582
486
|
const safeAccount = await (0, import_accounts.toSafeSmartAccount)({
|
|
583
487
|
client: publicClient,
|
|
584
|
-
owners: [
|
|
585
|
-
// Pass the owner object with address and signMessage capability
|
|
488
|
+
owners: [tempOwner],
|
|
586
489
|
version: "1.4.1",
|
|
587
490
|
entryPoint: {
|
|
588
491
|
address: import_account_abstraction.entryPoint07Address,
|
|
@@ -652,100 +555,41 @@ var getAccountType = async (address, publicClient) => {
|
|
|
652
555
|
return "Unknown";
|
|
653
556
|
}
|
|
654
557
|
};
|
|
655
|
-
var getSmartAccountClient = async (config) => {
|
|
656
|
-
const { chain, bundlerUrl } = config;
|
|
657
|
-
const safeAccount = await getSafeAccount(config);
|
|
658
|
-
const bundlerClient = (0, import_pimlico.createPimlicoClient)({
|
|
659
|
-
transport: (0, import_viem3.http)(bundlerUrl),
|
|
660
|
-
entryPoint: {
|
|
661
|
-
address: import_account_abstraction.entryPoint07Address,
|
|
662
|
-
version: "0.7"
|
|
663
|
-
}
|
|
664
|
-
});
|
|
665
|
-
const smartAccountClient = (0, import_permissionless.createSmartAccountClient)({
|
|
666
|
-
account: safeAccount,
|
|
667
|
-
chain,
|
|
668
|
-
bundlerTransport: (0, import_viem3.http)(bundlerUrl),
|
|
669
|
-
paymaster: bundlerClient,
|
|
670
|
-
userOperation: {
|
|
671
|
-
estimateFeesPerGas: async () => {
|
|
672
|
-
return (await bundlerClient.getUserOperationGasPrice()).fast;
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}).extend((0, import_erc7579.erc7579Actions)());
|
|
676
|
-
return smartAccountClient;
|
|
677
|
-
};
|
|
678
558
|
var deploySafeAccount = async (config) => {
|
|
679
559
|
try {
|
|
680
|
-
const { owner,
|
|
560
|
+
const { owner, httpClient, chainId } = config;
|
|
681
561
|
if (!owner || !owner.account) {
|
|
682
562
|
throw new Error(
|
|
683
563
|
"Wallet not connected. Please connect your wallet first."
|
|
684
564
|
);
|
|
685
565
|
}
|
|
686
|
-
const
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
}
|
|
694
|
-
const modulesToInstall = getModulesToInstall(chainId);
|
|
695
|
-
const installCalls = modulesToInstall.map((module2) => ({
|
|
696
|
-
to: safeAddress,
|
|
697
|
-
data: getInstallModuleCallData(module2)
|
|
698
|
-
}));
|
|
699
|
-
const smartAccountClient = await getSmartAccountClient(config);
|
|
700
|
-
const safeAccount = await getSafeAccount(config);
|
|
701
|
-
const ownableValidator = (0, import_module_sdk.getOwnableValidator)({
|
|
702
|
-
owners: [owner.account.address],
|
|
703
|
-
threshold: 1
|
|
704
|
-
});
|
|
705
|
-
const nonce = await (0, import_actions.getAccountNonce)(publicClient, {
|
|
706
|
-
address: safeAddress,
|
|
707
|
-
entryPointAddress: import_account_abstraction.entryPoint07Address,
|
|
708
|
-
key: BigInt(
|
|
709
|
-
(0, import_viem3.pad)(ownableValidator.address, {
|
|
710
|
-
dir: "right",
|
|
711
|
-
size: 24
|
|
712
|
-
}) || 0
|
|
713
|
-
)
|
|
714
|
-
});
|
|
715
|
-
const userOperation = await smartAccountClient.prepareUserOperation({
|
|
716
|
-
account: safeAccount,
|
|
717
|
-
calls: installCalls,
|
|
718
|
-
nonce
|
|
719
|
-
});
|
|
720
|
-
const userOpHashToSign = (0, import_account_abstraction2.getUserOperationHash)({
|
|
721
|
-
chainId,
|
|
722
|
-
entryPointAddress: import_account_abstraction.entryPoint07Address,
|
|
723
|
-
entryPointVersion: "0.7",
|
|
724
|
-
userOperation
|
|
725
|
-
});
|
|
726
|
-
if (!owner.account) {
|
|
727
|
-
throw new Error("Owner account is required for signing");
|
|
566
|
+
const prepareResponse = await httpClient.post(
|
|
567
|
+
`${ENDPOINTS.SAFE_DEPLOY}?chainId=${chainId}`
|
|
568
|
+
);
|
|
569
|
+
if (!prepareResponse.userOpHashToSign) {
|
|
570
|
+
throw new Error(
|
|
571
|
+
"Backend did not return userOpHashToSign. Response: " + JSON.stringify(prepareResponse)
|
|
572
|
+
);
|
|
728
573
|
}
|
|
729
|
-
|
|
574
|
+
const userOpHashToSign = prepareResponse.userOpHashToSign;
|
|
575
|
+
const userOpSignature = await owner.signMessage({
|
|
730
576
|
account: owner.account,
|
|
731
577
|
message: { raw: userOpHashToSign }
|
|
732
578
|
});
|
|
733
|
-
const
|
|
734
|
-
|
|
579
|
+
const deployResponse = await httpClient.post(
|
|
580
|
+
`${ENDPOINTS.SAFE_DEPLOY}?chainId=${chainId}`,
|
|
581
|
+
{ userOpSignature }
|
|
735
582
|
);
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
return {
|
|
741
|
-
safeAddress,
|
|
742
|
-
txHash: transaction.receipt.transactionHash,
|
|
743
|
-
isDeployed: true
|
|
744
|
-
};
|
|
745
|
-
} catch (error) {
|
|
746
|
-
console.error("Transaction failed:", error);
|
|
747
|
-
throw new Error("Failed to execute transaction");
|
|
583
|
+
if (!deployResponse.success) {
|
|
584
|
+
throw new Error(
|
|
585
|
+
`Safe deployment failed: ${JSON.stringify(deployResponse)}`
|
|
586
|
+
);
|
|
748
587
|
}
|
|
588
|
+
return {
|
|
589
|
+
safeAddress: deployResponse.safeAddress || "0x",
|
|
590
|
+
txHash: deployResponse.txHash,
|
|
591
|
+
isDeployed: true
|
|
592
|
+
};
|
|
749
593
|
} catch (error) {
|
|
750
594
|
throw new Error(
|
|
751
595
|
`Failed to deploy Safe account: ${error.message}`
|
|
@@ -799,24 +643,20 @@ var signSessionKey = async (config, sessions, allPublicClients, signingParams) =
|
|
|
799
643
|
// src/core/ZyfaiSDK.ts
|
|
800
644
|
var import_siwe = require("siwe");
|
|
801
645
|
var ZyfaiSDK = class {
|
|
802
|
-
// Optional custom RPC URLs per chain
|
|
803
646
|
constructor(config) {
|
|
804
647
|
this.signer = null;
|
|
805
648
|
this.walletClient = null;
|
|
806
649
|
this.authenticatedUserId = null;
|
|
807
|
-
// If non-null, user is authenticated
|
|
808
650
|
this.hasActiveSessionKey = false;
|
|
809
651
|
this.currentProvider = null;
|
|
810
|
-
// Store reference to current provider for event handling
|
|
811
652
|
this.currentChainId = null;
|
|
812
653
|
const sdkConfig = typeof config === "string" ? { apiKey: config } : config;
|
|
813
|
-
const { apiKey, environment,
|
|
654
|
+
const { apiKey, environment, rpcUrls } = sdkConfig;
|
|
814
655
|
if (!apiKey) {
|
|
815
656
|
throw new Error("API key is required");
|
|
816
657
|
}
|
|
817
658
|
this.environment = environment || "production";
|
|
818
659
|
this.httpClient = new HttpClient(apiKey, this.environment);
|
|
819
|
-
this.bundlerApiKey = bundlerApiKey;
|
|
820
660
|
this.rpcUrls = rpcUrls;
|
|
821
661
|
}
|
|
822
662
|
/**
|
|
@@ -1193,11 +1033,7 @@ var ZyfaiSDK = class {
|
|
|
1193
1033
|
if (!isSupportedChain(chainId)) {
|
|
1194
1034
|
throw new Error(`Unsupported chain ID: ${chainId}`);
|
|
1195
1035
|
}
|
|
1196
|
-
|
|
1197
|
-
throw new Error(
|
|
1198
|
-
"Bundler API key is required for Safe deployment. Please provide bundlerApiKey in SDK configuration."
|
|
1199
|
-
);
|
|
1200
|
-
}
|
|
1036
|
+
await this.authenticateUser();
|
|
1201
1037
|
const walletClient = this.getWalletClient(chainId);
|
|
1202
1038
|
const chainConfig = getChainConfig(chainId, this.rpcUrls);
|
|
1203
1039
|
const safeAddress = await getDeterministicSafeAddress({
|
|
@@ -1211,45 +1047,34 @@ var ZyfaiSDK = class {
|
|
|
1211
1047
|
safeAddress,
|
|
1212
1048
|
chainConfig.publicClient
|
|
1213
1049
|
);
|
|
1050
|
+
if (!alreadyDeployed) {
|
|
1051
|
+
const accountType = await getAccountType(
|
|
1052
|
+
userAddress,
|
|
1053
|
+
chainConfig.publicClient
|
|
1054
|
+
);
|
|
1055
|
+
if (accountType !== "EOA") {
|
|
1056
|
+
throw new Error(
|
|
1057
|
+
`Address ${userAddress} is not an EOA. Only EOA addresses can deploy Safe smart wallets.`
|
|
1058
|
+
);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1214
1061
|
if (alreadyDeployed) {
|
|
1215
1062
|
return {
|
|
1216
1063
|
success: true,
|
|
1217
1064
|
safeAddress,
|
|
1218
1065
|
txHash: "0x0",
|
|
1219
|
-
status: "deployed"
|
|
1220
|
-
alreadyDeployed: true
|
|
1066
|
+
status: "deployed"
|
|
1221
1067
|
};
|
|
1222
1068
|
}
|
|
1223
|
-
const accountType = await getAccountType(
|
|
1224
|
-
userAddress,
|
|
1225
|
-
chainConfig.publicClient
|
|
1226
|
-
);
|
|
1227
|
-
if (accountType !== "EOA") {
|
|
1228
|
-
throw new Error(
|
|
1229
|
-
`Address ${userAddress} is not an EOA. Only EOA addresses can deploy Safe smart wallets.`
|
|
1230
|
-
);
|
|
1231
|
-
}
|
|
1232
|
-
const bundlerUrl = getBundlerUrl(chainId, this.bundlerApiKey);
|
|
1233
1069
|
const deploymentResult = await deploySafeAccount({
|
|
1234
1070
|
owner: walletClient,
|
|
1235
1071
|
safeOwnerAddress: userAddress,
|
|
1236
1072
|
chain: chainConfig.chain,
|
|
1237
1073
|
publicClient: chainConfig.publicClient,
|
|
1238
|
-
bundlerUrl,
|
|
1239
1074
|
environment: this.environment,
|
|
1240
|
-
chainId
|
|
1075
|
+
chainId,
|
|
1076
|
+
httpClient: this.httpClient
|
|
1241
1077
|
});
|
|
1242
|
-
try {
|
|
1243
|
-
await this.updateUserProfile({
|
|
1244
|
-
smartWallet: deploymentResult.safeAddress,
|
|
1245
|
-
chains: [chainId]
|
|
1246
|
-
});
|
|
1247
|
-
} catch (updateError) {
|
|
1248
|
-
console.warn(
|
|
1249
|
-
"Failed to update user profile after Safe deployment:",
|
|
1250
|
-
updateError.message
|
|
1251
|
-
);
|
|
1252
|
-
}
|
|
1253
1078
|
try {
|
|
1254
1079
|
await this.initializeUser(deploymentResult.safeAddress, chainId);
|
|
1255
1080
|
} catch (initError) {
|
|
@@ -1270,7 +1095,7 @@ var ZyfaiSDK = class {
|
|
|
1270
1095
|
}
|
|
1271
1096
|
}
|
|
1272
1097
|
/**
|
|
1273
|
-
* Create session key with auto-fetched configuration from
|
|
1098
|
+
* Create session key with auto-fetched configuration from Zyfai API
|
|
1274
1099
|
* This is the simplified method that automatically fetches session configuration
|
|
1275
1100
|
*
|
|
1276
1101
|
* @param userAddress - User's EOA or Safe address
|
|
@@ -1441,7 +1266,7 @@ var ZyfaiSDK = class {
|
|
|
1441
1266
|
}
|
|
1442
1267
|
}
|
|
1443
1268
|
/**
|
|
1444
|
-
* Activate session key via
|
|
1269
|
+
* Activate session key via Zyfai API
|
|
1445
1270
|
*/
|
|
1446
1271
|
async activateSessionKey(signer, signature, sessionNonces) {
|
|
1447
1272
|
const nonces = this.normalizeSessionNonces(sessionNonces);
|
|
@@ -1552,7 +1377,7 @@ var ZyfaiSDK = class {
|
|
|
1552
1377
|
}
|
|
1553
1378
|
/**
|
|
1554
1379
|
* Withdraw funds from Safe smart wallet
|
|
1555
|
-
* Initiates a withdrawal request to the
|
|
1380
|
+
* Initiates a withdrawal request to the Zyfai API
|
|
1556
1381
|
* Note: The withdrawal is processed asynchronously, so txHash may not be immediately available
|
|
1557
1382
|
* Funds are always withdrawn to the Safe owner's address (userAddress)
|
|
1558
1383
|
*
|
|
@@ -1773,7 +1598,7 @@ var ZyfaiSDK = class {
|
|
|
1773
1598
|
// TVL & Volume Methods
|
|
1774
1599
|
// ============================================================================
|
|
1775
1600
|
/**
|
|
1776
|
-
* Get total value locked (TVL) across all
|
|
1601
|
+
* Get total value locked (TVL) across all Zyfai accounts
|
|
1777
1602
|
*
|
|
1778
1603
|
* @returns Total TVL in USD and breakdown by chain
|
|
1779
1604
|
*
|
|
@@ -1804,7 +1629,7 @@ var ZyfaiSDK = class {
|
|
|
1804
1629
|
}
|
|
1805
1630
|
}
|
|
1806
1631
|
/**
|
|
1807
|
-
* Get total volume across all
|
|
1632
|
+
* Get total volume across all Zyfai accounts
|
|
1808
1633
|
*
|
|
1809
1634
|
* @returns Total volume in USD
|
|
1810
1635
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -20,6 +20,8 @@ var ENDPOINTS = {
|
|
|
20
20
|
USER_ME: "/users/me",
|
|
21
21
|
USER_WITHDRAW: "/users/withdraw",
|
|
22
22
|
PARTIAL_WITHDRAW: "/users/partial-withdraw",
|
|
23
|
+
// Safe Deployment (single endpoint)
|
|
24
|
+
SAFE_DEPLOY: "/users/safe-deploy",
|
|
23
25
|
// Session Keys
|
|
24
26
|
SESSION_KEYS_CONFIG: "/session-keys/config",
|
|
25
27
|
SESSION_KEYS_ADD: "/session-keys/add",
|
|
@@ -320,7 +322,7 @@ import { privateKeyToAccount } from "viem/accounts";
|
|
|
320
322
|
import {
|
|
321
323
|
createWalletClient,
|
|
322
324
|
custom,
|
|
323
|
-
http as
|
|
325
|
+
http as http2,
|
|
324
326
|
getAddress as getAddress2
|
|
325
327
|
} from "viem";
|
|
326
328
|
|
|
@@ -397,19 +399,6 @@ var isSupportedChain = (chainId) => {
|
|
|
397
399
|
var getSupportedChainIds = () => {
|
|
398
400
|
return Object.keys(CHAINS).map(Number);
|
|
399
401
|
};
|
|
400
|
-
var getBundlerUrl = (chainId, bundlerApiKey, bundlerProvider = "pimlico") => {
|
|
401
|
-
if (!bundlerApiKey) {
|
|
402
|
-
throw new Error("Bundler API key is required for Safe deployment");
|
|
403
|
-
}
|
|
404
|
-
switch (bundlerProvider) {
|
|
405
|
-
case "pimlico":
|
|
406
|
-
return `https://api.pimlico.io/v2/${chainId}/rpc?apikey=${bundlerApiKey}`;
|
|
407
|
-
case "custom":
|
|
408
|
-
return bundlerApiKey;
|
|
409
|
-
default:
|
|
410
|
-
throw new Error(`Unsupported bundler provider: ${bundlerProvider}`);
|
|
411
|
-
}
|
|
412
|
-
};
|
|
413
402
|
|
|
414
403
|
// src/utils/safe-account.ts
|
|
415
404
|
import {
|
|
@@ -418,120 +407,23 @@ import {
|
|
|
418
407
|
getAccount,
|
|
419
408
|
getEnableSessionDetails,
|
|
420
409
|
getPermissionId,
|
|
421
|
-
getSessionNonce
|
|
422
|
-
getSmartSessionsValidator,
|
|
423
|
-
getAccountLockerHook,
|
|
424
|
-
getAccountLockerSourceExecutor,
|
|
425
|
-
getAccountLockerTargetExecutor
|
|
410
|
+
getSessionNonce
|
|
426
411
|
} from "@rhinestone/module-sdk";
|
|
427
|
-
import { createSmartAccountClient } from "permissionless";
|
|
428
|
-
import { erc7579Actions } from "permissionless/actions/erc7579";
|
|
429
|
-
import { createPimlicoClient } from "permissionless/clients/pimlico";
|
|
430
412
|
import { toSafeSmartAccount } from "permissionless/accounts";
|
|
431
413
|
import {
|
|
432
|
-
http as http2,
|
|
433
414
|
getAddress,
|
|
434
|
-
encodeFunctionData,
|
|
435
415
|
fromHex,
|
|
436
|
-
toHex
|
|
437
|
-
encodeAbiParameters,
|
|
438
|
-
pad
|
|
416
|
+
toHex
|
|
439
417
|
} from "viem";
|
|
440
418
|
import {
|
|
441
419
|
entryPoint07Address
|
|
442
420
|
} from "viem/account-abstraction";
|
|
443
|
-
import { getAccountNonce } from "permissionless/actions";
|
|
444
|
-
import { getUserOperationHash } from "viem/account-abstraction";
|
|
445
421
|
var SAFE_7579_ADDRESS = "0x7579EE8307284F293B1927136486880611F20002";
|
|
446
422
|
var ERC7579_LAUNCHPAD_ADDRESS = "0x7579011aB74c46090561ea277Ba79D510c6C00ff";
|
|
447
423
|
var ACCOUNT_SALTS = {
|
|
448
424
|
staging: "zyfai-staging",
|
|
449
425
|
production: "zyfai"
|
|
450
426
|
};
|
|
451
|
-
var MODULE_TYPE_IDS = {
|
|
452
|
-
validator: 1n,
|
|
453
|
-
executor: 2n,
|
|
454
|
-
fallback: 3n,
|
|
455
|
-
hook: 4n
|
|
456
|
-
};
|
|
457
|
-
var SMART_SESSIONS_FALLBACK = {
|
|
458
|
-
module: "0x12cae64c42f362e7d5a847c2d33388373f629177",
|
|
459
|
-
address: "0x12cae64c42f362e7d5a847c2d33388373f629177",
|
|
460
|
-
type: "fallback",
|
|
461
|
-
selector: encodeAbiParameters(
|
|
462
|
-
[{ name: "functionSignature", type: "bytes4" }],
|
|
463
|
-
["0x84b0196e"]
|
|
464
|
-
),
|
|
465
|
-
initData: "0x84b0196e00000000000000000000000000000000000000000000000000000000fe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
|
|
466
|
-
};
|
|
467
|
-
var INTENT_EXECUTOR = {
|
|
468
|
-
address: "0x00000000005aD9ce1f5035FD62CA96CEf16AdAAF",
|
|
469
|
-
type: "executor",
|
|
470
|
-
initData: "0x"
|
|
471
|
-
};
|
|
472
|
-
var PROXY_EXECUTOR = {
|
|
473
|
-
address: "0xF659d30D4EB88B06A909F20839D8959Bd77d8790",
|
|
474
|
-
type: "executor",
|
|
475
|
-
initData: "0x"
|
|
476
|
-
};
|
|
477
|
-
var getModulesToInstall = (chainId) => {
|
|
478
|
-
const smartSessions = getSmartSessionsValidator({});
|
|
479
|
-
const accountLockerHook = getAccountLockerHook({ isOmniMode: true });
|
|
480
|
-
const accountLockerSourceExecutor = getAccountLockerSourceExecutor();
|
|
481
|
-
const accountLockerTargetExecutor = getAccountLockerTargetExecutor();
|
|
482
|
-
if (chainId === 9745) {
|
|
483
|
-
return [
|
|
484
|
-
smartSessions,
|
|
485
|
-
SMART_SESSIONS_FALLBACK,
|
|
486
|
-
INTENT_EXECUTOR,
|
|
487
|
-
PROXY_EXECUTOR
|
|
488
|
-
];
|
|
489
|
-
}
|
|
490
|
-
return [
|
|
491
|
-
smartSessions,
|
|
492
|
-
{
|
|
493
|
-
...accountLockerHook,
|
|
494
|
-
type: "executor"
|
|
495
|
-
},
|
|
496
|
-
accountLockerSourceExecutor,
|
|
497
|
-
accountLockerTargetExecutor,
|
|
498
|
-
SMART_SESSIONS_FALLBACK,
|
|
499
|
-
INTENT_EXECUTOR,
|
|
500
|
-
PROXY_EXECUTOR
|
|
501
|
-
];
|
|
502
|
-
};
|
|
503
|
-
var getInstallModuleCallData = (module) => {
|
|
504
|
-
return encodeFunctionData({
|
|
505
|
-
abi: [
|
|
506
|
-
{
|
|
507
|
-
type: "function",
|
|
508
|
-
name: "installModule",
|
|
509
|
-
inputs: [
|
|
510
|
-
{
|
|
511
|
-
type: "uint256",
|
|
512
|
-
name: "moduleTypeId"
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
type: "address",
|
|
516
|
-
name: "module"
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
type: "bytes",
|
|
520
|
-
name: "initData"
|
|
521
|
-
}
|
|
522
|
-
],
|
|
523
|
-
outputs: [],
|
|
524
|
-
stateMutability: "nonpayable"
|
|
525
|
-
}
|
|
526
|
-
],
|
|
527
|
-
functionName: "installModule",
|
|
528
|
-
args: [
|
|
529
|
-
MODULE_TYPE_IDS[module.type],
|
|
530
|
-
module.address,
|
|
531
|
-
module.initData || "0x"
|
|
532
|
-
]
|
|
533
|
-
});
|
|
534
|
-
};
|
|
535
427
|
var getSafeAccount = async (config) => {
|
|
536
428
|
const {
|
|
537
429
|
owner,
|
|
@@ -564,10 +456,13 @@ var getSafeAccount = async (config) => {
|
|
|
564
456
|
threshold: 1
|
|
565
457
|
});
|
|
566
458
|
const saltHex = fromHex(toHex(effectiveSalt), "bigint");
|
|
459
|
+
const tempOwner = {
|
|
460
|
+
address: formattedEffectiveAddress,
|
|
461
|
+
type: "json-rpc"
|
|
462
|
+
};
|
|
567
463
|
const safeAccount = await toSafeSmartAccount({
|
|
568
464
|
client: publicClient,
|
|
569
|
-
owners: [
|
|
570
|
-
// Pass the owner object with address and signMessage capability
|
|
465
|
+
owners: [tempOwner],
|
|
571
466
|
version: "1.4.1",
|
|
572
467
|
entryPoint: {
|
|
573
468
|
address: entryPoint07Address,
|
|
@@ -637,100 +532,41 @@ var getAccountType = async (address, publicClient) => {
|
|
|
637
532
|
return "Unknown";
|
|
638
533
|
}
|
|
639
534
|
};
|
|
640
|
-
var getSmartAccountClient = async (config) => {
|
|
641
|
-
const { chain, bundlerUrl } = config;
|
|
642
|
-
const safeAccount = await getSafeAccount(config);
|
|
643
|
-
const bundlerClient = createPimlicoClient({
|
|
644
|
-
transport: http2(bundlerUrl),
|
|
645
|
-
entryPoint: {
|
|
646
|
-
address: entryPoint07Address,
|
|
647
|
-
version: "0.7"
|
|
648
|
-
}
|
|
649
|
-
});
|
|
650
|
-
const smartAccountClient = createSmartAccountClient({
|
|
651
|
-
account: safeAccount,
|
|
652
|
-
chain,
|
|
653
|
-
bundlerTransport: http2(bundlerUrl),
|
|
654
|
-
paymaster: bundlerClient,
|
|
655
|
-
userOperation: {
|
|
656
|
-
estimateFeesPerGas: async () => {
|
|
657
|
-
return (await bundlerClient.getUserOperationGasPrice()).fast;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
}).extend(erc7579Actions());
|
|
661
|
-
return smartAccountClient;
|
|
662
|
-
};
|
|
663
535
|
var deploySafeAccount = async (config) => {
|
|
664
536
|
try {
|
|
665
|
-
const { owner,
|
|
537
|
+
const { owner, httpClient, chainId } = config;
|
|
666
538
|
if (!owner || !owner.account) {
|
|
667
539
|
throw new Error(
|
|
668
540
|
"Wallet not connected. Please connect your wallet first."
|
|
669
541
|
);
|
|
670
542
|
}
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
}
|
|
679
|
-
const modulesToInstall = getModulesToInstall(chainId);
|
|
680
|
-
const installCalls = modulesToInstall.map((module) => ({
|
|
681
|
-
to: safeAddress,
|
|
682
|
-
data: getInstallModuleCallData(module)
|
|
683
|
-
}));
|
|
684
|
-
const smartAccountClient = await getSmartAccountClient(config);
|
|
685
|
-
const safeAccount = await getSafeAccount(config);
|
|
686
|
-
const ownableValidator = getOwnableValidator({
|
|
687
|
-
owners: [owner.account.address],
|
|
688
|
-
threshold: 1
|
|
689
|
-
});
|
|
690
|
-
const nonce = await getAccountNonce(publicClient, {
|
|
691
|
-
address: safeAddress,
|
|
692
|
-
entryPointAddress: entryPoint07Address,
|
|
693
|
-
key: BigInt(
|
|
694
|
-
pad(ownableValidator.address, {
|
|
695
|
-
dir: "right",
|
|
696
|
-
size: 24
|
|
697
|
-
}) || 0
|
|
698
|
-
)
|
|
699
|
-
});
|
|
700
|
-
const userOperation = await smartAccountClient.prepareUserOperation({
|
|
701
|
-
account: safeAccount,
|
|
702
|
-
calls: installCalls,
|
|
703
|
-
nonce
|
|
704
|
-
});
|
|
705
|
-
const userOpHashToSign = getUserOperationHash({
|
|
706
|
-
chainId,
|
|
707
|
-
entryPointAddress: entryPoint07Address,
|
|
708
|
-
entryPointVersion: "0.7",
|
|
709
|
-
userOperation
|
|
710
|
-
});
|
|
711
|
-
if (!owner.account) {
|
|
712
|
-
throw new Error("Owner account is required for signing");
|
|
543
|
+
const prepareResponse = await httpClient.post(
|
|
544
|
+
`${ENDPOINTS.SAFE_DEPLOY}?chainId=${chainId}`
|
|
545
|
+
);
|
|
546
|
+
if (!prepareResponse.userOpHashToSign) {
|
|
547
|
+
throw new Error(
|
|
548
|
+
"Backend did not return userOpHashToSign. Response: " + JSON.stringify(prepareResponse)
|
|
549
|
+
);
|
|
713
550
|
}
|
|
714
|
-
|
|
551
|
+
const userOpHashToSign = prepareResponse.userOpHashToSign;
|
|
552
|
+
const userOpSignature = await owner.signMessage({
|
|
715
553
|
account: owner.account,
|
|
716
554
|
message: { raw: userOpHashToSign }
|
|
717
555
|
});
|
|
718
|
-
const
|
|
719
|
-
|
|
556
|
+
const deployResponse = await httpClient.post(
|
|
557
|
+
`${ENDPOINTS.SAFE_DEPLOY}?chainId=${chainId}`,
|
|
558
|
+
{ userOpSignature }
|
|
720
559
|
);
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
return {
|
|
726
|
-
safeAddress,
|
|
727
|
-
txHash: transaction.receipt.transactionHash,
|
|
728
|
-
isDeployed: true
|
|
729
|
-
};
|
|
730
|
-
} catch (error) {
|
|
731
|
-
console.error("Transaction failed:", error);
|
|
732
|
-
throw new Error("Failed to execute transaction");
|
|
560
|
+
if (!deployResponse.success) {
|
|
561
|
+
throw new Error(
|
|
562
|
+
`Safe deployment failed: ${JSON.stringify(deployResponse)}`
|
|
563
|
+
);
|
|
733
564
|
}
|
|
565
|
+
return {
|
|
566
|
+
safeAddress: deployResponse.safeAddress || "0x",
|
|
567
|
+
txHash: deployResponse.txHash,
|
|
568
|
+
isDeployed: true
|
|
569
|
+
};
|
|
734
570
|
} catch (error) {
|
|
735
571
|
throw new Error(
|
|
736
572
|
`Failed to deploy Safe account: ${error.message}`
|
|
@@ -784,24 +620,20 @@ var signSessionKey = async (config, sessions, allPublicClients, signingParams) =
|
|
|
784
620
|
// src/core/ZyfaiSDK.ts
|
|
785
621
|
import { SiweMessage } from "siwe";
|
|
786
622
|
var ZyfaiSDK = class {
|
|
787
|
-
// Optional custom RPC URLs per chain
|
|
788
623
|
constructor(config) {
|
|
789
624
|
this.signer = null;
|
|
790
625
|
this.walletClient = null;
|
|
791
626
|
this.authenticatedUserId = null;
|
|
792
|
-
// If non-null, user is authenticated
|
|
793
627
|
this.hasActiveSessionKey = false;
|
|
794
628
|
this.currentProvider = null;
|
|
795
|
-
// Store reference to current provider for event handling
|
|
796
629
|
this.currentChainId = null;
|
|
797
630
|
const sdkConfig = typeof config === "string" ? { apiKey: config } : config;
|
|
798
|
-
const { apiKey, environment,
|
|
631
|
+
const { apiKey, environment, rpcUrls } = sdkConfig;
|
|
799
632
|
if (!apiKey) {
|
|
800
633
|
throw new Error("API key is required");
|
|
801
634
|
}
|
|
802
635
|
this.environment = environment || "production";
|
|
803
636
|
this.httpClient = new HttpClient(apiKey, this.environment);
|
|
804
|
-
this.bundlerApiKey = bundlerApiKey;
|
|
805
637
|
this.rpcUrls = rpcUrls;
|
|
806
638
|
}
|
|
807
639
|
/**
|
|
@@ -1021,7 +853,7 @@ var ZyfaiSDK = class {
|
|
|
1021
853
|
this.walletClient = createWalletClient({
|
|
1022
854
|
account: this.signer,
|
|
1023
855
|
chain: chainConfig.chain,
|
|
1024
|
-
transport:
|
|
856
|
+
transport: http2(chainConfig.rpcUrl)
|
|
1025
857
|
});
|
|
1026
858
|
connectedAddress = this.signer.address;
|
|
1027
859
|
this.currentProvider = null;
|
|
@@ -1107,7 +939,7 @@ var ZyfaiSDK = class {
|
|
|
1107
939
|
return createWalletClient({
|
|
1108
940
|
account: this.signer,
|
|
1109
941
|
chain: targetChainConfig.chain,
|
|
1110
|
-
transport:
|
|
942
|
+
transport: http2(targetChainConfig.rpcUrl)
|
|
1111
943
|
});
|
|
1112
944
|
} else {
|
|
1113
945
|
if (!this.walletClient) {
|
|
@@ -1178,11 +1010,7 @@ var ZyfaiSDK = class {
|
|
|
1178
1010
|
if (!isSupportedChain(chainId)) {
|
|
1179
1011
|
throw new Error(`Unsupported chain ID: ${chainId}`);
|
|
1180
1012
|
}
|
|
1181
|
-
|
|
1182
|
-
throw new Error(
|
|
1183
|
-
"Bundler API key is required for Safe deployment. Please provide bundlerApiKey in SDK configuration."
|
|
1184
|
-
);
|
|
1185
|
-
}
|
|
1013
|
+
await this.authenticateUser();
|
|
1186
1014
|
const walletClient = this.getWalletClient(chainId);
|
|
1187
1015
|
const chainConfig = getChainConfig(chainId, this.rpcUrls);
|
|
1188
1016
|
const safeAddress = await getDeterministicSafeAddress({
|
|
@@ -1196,45 +1024,34 @@ var ZyfaiSDK = class {
|
|
|
1196
1024
|
safeAddress,
|
|
1197
1025
|
chainConfig.publicClient
|
|
1198
1026
|
);
|
|
1027
|
+
if (!alreadyDeployed) {
|
|
1028
|
+
const accountType = await getAccountType(
|
|
1029
|
+
userAddress,
|
|
1030
|
+
chainConfig.publicClient
|
|
1031
|
+
);
|
|
1032
|
+
if (accountType !== "EOA") {
|
|
1033
|
+
throw new Error(
|
|
1034
|
+
`Address ${userAddress} is not an EOA. Only EOA addresses can deploy Safe smart wallets.`
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1199
1038
|
if (alreadyDeployed) {
|
|
1200
1039
|
return {
|
|
1201
1040
|
success: true,
|
|
1202
1041
|
safeAddress,
|
|
1203
1042
|
txHash: "0x0",
|
|
1204
|
-
status: "deployed"
|
|
1205
|
-
alreadyDeployed: true
|
|
1043
|
+
status: "deployed"
|
|
1206
1044
|
};
|
|
1207
1045
|
}
|
|
1208
|
-
const accountType = await getAccountType(
|
|
1209
|
-
userAddress,
|
|
1210
|
-
chainConfig.publicClient
|
|
1211
|
-
);
|
|
1212
|
-
if (accountType !== "EOA") {
|
|
1213
|
-
throw new Error(
|
|
1214
|
-
`Address ${userAddress} is not an EOA. Only EOA addresses can deploy Safe smart wallets.`
|
|
1215
|
-
);
|
|
1216
|
-
}
|
|
1217
|
-
const bundlerUrl = getBundlerUrl(chainId, this.bundlerApiKey);
|
|
1218
1046
|
const deploymentResult = await deploySafeAccount({
|
|
1219
1047
|
owner: walletClient,
|
|
1220
1048
|
safeOwnerAddress: userAddress,
|
|
1221
1049
|
chain: chainConfig.chain,
|
|
1222
1050
|
publicClient: chainConfig.publicClient,
|
|
1223
|
-
bundlerUrl,
|
|
1224
1051
|
environment: this.environment,
|
|
1225
|
-
chainId
|
|
1052
|
+
chainId,
|
|
1053
|
+
httpClient: this.httpClient
|
|
1226
1054
|
});
|
|
1227
|
-
try {
|
|
1228
|
-
await this.updateUserProfile({
|
|
1229
|
-
smartWallet: deploymentResult.safeAddress,
|
|
1230
|
-
chains: [chainId]
|
|
1231
|
-
});
|
|
1232
|
-
} catch (updateError) {
|
|
1233
|
-
console.warn(
|
|
1234
|
-
"Failed to update user profile after Safe deployment:",
|
|
1235
|
-
updateError.message
|
|
1236
|
-
);
|
|
1237
|
-
}
|
|
1238
1055
|
try {
|
|
1239
1056
|
await this.initializeUser(deploymentResult.safeAddress, chainId);
|
|
1240
1057
|
} catch (initError) {
|
|
@@ -1255,7 +1072,7 @@ var ZyfaiSDK = class {
|
|
|
1255
1072
|
}
|
|
1256
1073
|
}
|
|
1257
1074
|
/**
|
|
1258
|
-
* Create session key with auto-fetched configuration from
|
|
1075
|
+
* Create session key with auto-fetched configuration from Zyfai API
|
|
1259
1076
|
* This is the simplified method that automatically fetches session configuration
|
|
1260
1077
|
*
|
|
1261
1078
|
* @param userAddress - User's EOA or Safe address
|
|
@@ -1426,7 +1243,7 @@ var ZyfaiSDK = class {
|
|
|
1426
1243
|
}
|
|
1427
1244
|
}
|
|
1428
1245
|
/**
|
|
1429
|
-
* Activate session key via
|
|
1246
|
+
* Activate session key via Zyfai API
|
|
1430
1247
|
*/
|
|
1431
1248
|
async activateSessionKey(signer, signature, sessionNonces) {
|
|
1432
1249
|
const nonces = this.normalizeSessionNonces(sessionNonces);
|
|
@@ -1537,7 +1354,7 @@ var ZyfaiSDK = class {
|
|
|
1537
1354
|
}
|
|
1538
1355
|
/**
|
|
1539
1356
|
* Withdraw funds from Safe smart wallet
|
|
1540
|
-
* Initiates a withdrawal request to the
|
|
1357
|
+
* Initiates a withdrawal request to the Zyfai API
|
|
1541
1358
|
* Note: The withdrawal is processed asynchronously, so txHash may not be immediately available
|
|
1542
1359
|
* Funds are always withdrawn to the Safe owner's address (userAddress)
|
|
1543
1360
|
*
|
|
@@ -1758,7 +1575,7 @@ var ZyfaiSDK = class {
|
|
|
1758
1575
|
// TVL & Volume Methods
|
|
1759
1576
|
// ============================================================================
|
|
1760
1577
|
/**
|
|
1761
|
-
* Get total value locked (TVL) across all
|
|
1578
|
+
* Get total value locked (TVL) across all Zyfai accounts
|
|
1762
1579
|
*
|
|
1763
1580
|
* @returns Total TVL in USD and breakdown by chain
|
|
1764
1581
|
*
|
|
@@ -1789,7 +1606,7 @@ var ZyfaiSDK = class {
|
|
|
1789
1606
|
}
|
|
1790
1607
|
}
|
|
1791
1608
|
/**
|
|
1792
|
-
* Get total volume across all
|
|
1609
|
+
* Get total volume across all Zyfai accounts
|
|
1793
1610
|
*
|
|
1794
1611
|
* @returns Total volume in USD
|
|
1795
1612
|
*
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zyfai/sdk",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "TypeScript SDK for
|
|
3
|
+
"version": "0.1.28",
|
|
4
|
+
"description": "TypeScript SDK for Zyfai Yield Optimization Engine - Deploy Safe smart wallets, manage session keys, and interact with DeFi protocols",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|