@zyfai/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +722 -0
- package/dist/index.d.mts +769 -0
- package/dist/index.d.ts +769 -0
- package/dist/index.js +1890 -0
- package/dist/index.mjs +1869 -0
- package/package.json +83 -0
package/README.md
ADDED
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
# ZyFAI SDK
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@zyfai/sdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
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
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Safe Smart Wallet Deployment**: Deploy Safe wallets with deterministic addresses
|
|
11
|
+
- **Flexible Authentication**: Support for private keys and modern wallet providers
|
|
12
|
+
- **Multi-Chain Support**: Works on Arbitrum, Base, and Plasma
|
|
13
|
+
- **Yield Optimization**: Access to multiple DeFi protocols and strategies
|
|
14
|
+
- **Position Tracking**: Monitor and manage your DeFi positions across chains
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @zyfai/sdk viem
|
|
20
|
+
# or
|
|
21
|
+
yarn add @zyfai/sdk viem
|
|
22
|
+
# or
|
|
23
|
+
pnpm add @zyfai/sdk viem
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Prerequisites
|
|
27
|
+
|
|
28
|
+
1. **Execution API Key**: API key for the Execution API (Safe deployment, transactions, session keys)
|
|
29
|
+
2. **Data API Key** (optional): API key for the Data API (earnings, opportunities, analytics). If not provided, uses the Execution API key.
|
|
30
|
+
3. **Bundler API Key**: Required for Safe deployment. Get it from:
|
|
31
|
+
- [Pimlico](https://www.pimlico.io/) (Recommended)
|
|
32
|
+
|
|
33
|
+
**Get your API keys from [ZyFAI Dashboard](https://app.zyf.ai)**
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
### Initialize the SDK
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { ZyfaiSDK } from "@zyfai/sdk";
|
|
41
|
+
|
|
42
|
+
const sdk = new ZyfaiSDK({
|
|
43
|
+
apiKey: "your-execution-api-key", // Execution API (transactions, Safe deployment)
|
|
44
|
+
dataApiKey: "your-data-api-key", // Data API (analytics, earnings, opportunities)
|
|
45
|
+
bundlerApiKey: "your-bundler-api-key", // Required for Safe deployment
|
|
46
|
+
environment: "production", // or 'staging' (default: 'production')
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Configuration Options:**
|
|
51
|
+
|
|
52
|
+
| Option | Required | Description |
|
|
53
|
+
| --------------- | -------- | ----------------------------------------------------------------------------------------------- |
|
|
54
|
+
| `apiKey` | Yes | API key for Execution API (Safe deployment, transactions, session keys) |
|
|
55
|
+
| `dataApiKey` | No | API key for Data API (earnings, opportunities, analytics). Defaults to `apiKey` if not provided |
|
|
56
|
+
| `bundlerApiKey` | No\* | Pimlico API key for Safe deployment (\*required for `deploySafe`) |
|
|
57
|
+
| `environment` | No | `"production"` or `"staging"` (default: `"production"`) |
|
|
58
|
+
|
|
59
|
+
**API Endpoints by Environment:**
|
|
60
|
+
|
|
61
|
+
| Environment | Execution API | Data API |
|
|
62
|
+
| ------------ | ---------------------------- | --------------------------------- |
|
|
63
|
+
| `production` | `https://api.zyf.ai` | `https://defi-api.zyf.ai` |
|
|
64
|
+
| `staging` | `https://staging-api.zyf.ai` | `https://staging-defi-api.zyf.ai` |
|
|
65
|
+
|
|
66
|
+
### Connect Account
|
|
67
|
+
|
|
68
|
+
The SDK accepts either a private key or a modern wallet provider:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// Option 1: With private key (chainId required)
|
|
72
|
+
await sdk.connectAccount("0x...", 42161);
|
|
73
|
+
|
|
74
|
+
// Option 2: With wallet provider (chainId optional - uses provider's chain)
|
|
75
|
+
const provider = await connector.getProvider();
|
|
76
|
+
await sdk.connectAccount(provider); // SDK detects chain from provider
|
|
77
|
+
|
|
78
|
+
// Option 3: With EIP-1193 provider
|
|
79
|
+
const provider = window.ethereum; // Client passes this from their frontend
|
|
80
|
+
await sdk.connectAccount(provider); // Automatically uses provider's current chain
|
|
81
|
+
|
|
82
|
+
// Now call methods with explicit user addresses
|
|
83
|
+
const userAddress = "0xUser...";
|
|
84
|
+
await sdk.deploySafe(userAddress, 42161);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Note:** When using a wallet provider, the SDK automatically detects the chain from the provider. You can optionally specify `chainId` to override.
|
|
88
|
+
|
|
89
|
+
## Core Features
|
|
90
|
+
|
|
91
|
+
### 1. Deploy Safe Smart Wallet
|
|
92
|
+
|
|
93
|
+
Deploy a Safe smart wallet:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
const userAddress = "0xUser..."; // User's EOA address
|
|
97
|
+
|
|
98
|
+
// Get the deterministic Safe address (before deployment)
|
|
99
|
+
const walletInfo = await sdk.getSmartWalletAddress(userAddress, 42161);
|
|
100
|
+
console.log("Safe Address:", walletInfo.address);
|
|
101
|
+
console.log("Is Deployed:", walletInfo.isDeployed);
|
|
102
|
+
|
|
103
|
+
// Deploy the Safe
|
|
104
|
+
const result = await sdk.deploySafe(userAddress, 42161);
|
|
105
|
+
|
|
106
|
+
if (result.success) {
|
|
107
|
+
console.log("Safe Address:", result.safeAddress);
|
|
108
|
+
console.log("Status:", result.status); // 'deployed' | 'failed'
|
|
109
|
+
console.log("Transaction Hash:", result.txHash);
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### 2. Multi-Chain Support
|
|
114
|
+
|
|
115
|
+
The SDK supports the following chains:
|
|
116
|
+
|
|
117
|
+
| Chain | Chain ID | Status |
|
|
118
|
+
| -------- | -------- | ------ |
|
|
119
|
+
| Arbitrum | 42161 | ✅ |
|
|
120
|
+
| Base | 8453 | ✅ |
|
|
121
|
+
| Plasma | 9745 | ✅ |
|
|
122
|
+
|
|
123
|
+
Example with different chains:
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { getSupportedChainIds, isSupportedChain } from "@zyfai/sdk";
|
|
127
|
+
|
|
128
|
+
// Get all supported chains
|
|
129
|
+
const chains = getSupportedChainIds();
|
|
130
|
+
console.log("Supported chains:", chains);
|
|
131
|
+
|
|
132
|
+
// Check if a chain is supported
|
|
133
|
+
if (isSupportedChain(42161)) {
|
|
134
|
+
const userAddress = "0xUser...";
|
|
135
|
+
const result = await sdk.deploySafe(userAddress, 42161); // Arbitrum
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## API Reference
|
|
140
|
+
|
|
141
|
+
### `ZyfaiSDK`
|
|
142
|
+
|
|
143
|
+
#### Constructor
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
new ZyfaiSDK(config: SDKConfig | string)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Parameters:**
|
|
150
|
+
|
|
151
|
+
- `config`: Configuration object or API key string
|
|
152
|
+
- `apiKey` (string): Your ZyFAI API key
|
|
153
|
+
- `environment` ('production' | 'staging', optional): API environment (default: 'production')
|
|
154
|
+
- `bundlerApiKey` (string, optional): Bundler API key for Safe deployment (required for deploySafe)
|
|
155
|
+
|
|
156
|
+
#### Methods
|
|
157
|
+
|
|
158
|
+
##### `connectAccount(account: string | any, chainId?: SupportedChainId): Promise<Address>`
|
|
159
|
+
|
|
160
|
+
Connect account for signing transactions. Accepts either a private key string or a modern wallet provider.
|
|
161
|
+
|
|
162
|
+
**Parameters:**
|
|
163
|
+
|
|
164
|
+
- `account`: Private key string or wallet provider object (EIP-1193 provider, viem WalletClient, etc.)
|
|
165
|
+
- `chainId`: Target chain ID
|
|
166
|
+
- **Required** for private key
|
|
167
|
+
- **Optional** for wallet providers (auto-detects from provider)
|
|
168
|
+
- Default: 42161 (Arbitrum)
|
|
169
|
+
|
|
170
|
+
**Returns:** Connected wallet address
|
|
171
|
+
|
|
172
|
+
**Examples:**
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
// With private key (chainId required)
|
|
176
|
+
await sdk.connectAccount("0x...", 42161);
|
|
177
|
+
|
|
178
|
+
// With wallet provider (chainId optional)
|
|
179
|
+
const provider = await connector.getProvider();
|
|
180
|
+
await sdk.connectAccount(provider); // Uses provider's current chain
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
##### `getSmartWalletAddress(userAddress: string, chainId: SupportedChainId): Promise<SmartWalletResponse>`
|
|
184
|
+
|
|
185
|
+
Get the Smart Wallet (Safe) address for a user.
|
|
186
|
+
|
|
187
|
+
**Parameters:**
|
|
188
|
+
|
|
189
|
+
- `userAddress`: User's EOA address
|
|
190
|
+
- `chainId`: Target chain ID
|
|
191
|
+
|
|
192
|
+
**Returns:**
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
{
|
|
196
|
+
address: Address; // Safe address
|
|
197
|
+
isDeployed: boolean; // Whether the Safe is deployed
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
##### `deploySafe(userAddress: string, chainId: SupportedChainId): Promise<DeploySafeResponse>`
|
|
202
|
+
|
|
203
|
+
Deploy a Safe smart wallet for a user.
|
|
204
|
+
|
|
205
|
+
**Parameters:**
|
|
206
|
+
|
|
207
|
+
- `userAddress`: User's EOA address
|
|
208
|
+
- `chainId`: Target chain ID
|
|
209
|
+
|
|
210
|
+
**Returns:**
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
{
|
|
214
|
+
success: boolean;
|
|
215
|
+
safeAddress: Address;
|
|
216
|
+
txHash: string;
|
|
217
|
+
status: "deployed" | "failed";
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### 3. Session Keys
|
|
222
|
+
|
|
223
|
+
Session keys enable delegated transaction execution without exposing the main private key.
|
|
224
|
+
|
|
225
|
+
#### Simple Usage (Recommended)
|
|
226
|
+
|
|
227
|
+
The SDK automatically fetches optimal session configuration from ZyFAI API:
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// SDK automatically:
|
|
231
|
+
// 1. Authenticates via SIWE (creates user record if needed)
|
|
232
|
+
// 2. Calculates the deterministic Safe address
|
|
233
|
+
// 3. Resolves the userId via /users/by-smart-wallet
|
|
234
|
+
// 4. Retrieves personalized config via /session-keys/config
|
|
235
|
+
// 5. Signs the session key
|
|
236
|
+
// 6. Calls /session-keys/add so the session becomes active immediately
|
|
237
|
+
|
|
238
|
+
const result = await sdk.createSessionKey(userAddress, 42161);
|
|
239
|
+
|
|
240
|
+
console.log("Session created:", result.signature);
|
|
241
|
+
console.log("Safe address:", result.sessionKeyAddress);
|
|
242
|
+
console.log("User ID:", result.userId);
|
|
243
|
+
console.log("Activation ID:", result.sessionActivation?.id);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Important**:
|
|
247
|
+
|
|
248
|
+
- `createSessionKey` requires SIWE authentication (prompts wallet signature on first call)
|
|
249
|
+
- The user record must have `smartWallet` and `chainId` set (automatically handled after calling `deploySafe` or `updateUserProfile`)
|
|
250
|
+
- The SDK now auto-calls `/users/by-smart-wallet`, `/session-keys/config`, and `/session-keys/add`, so the returned payload already includes the `userId` and the activation record (`sessionActivation`)—no additional API calls are required on your side.
|
|
251
|
+
|
|
252
|
+
### 4. Deposit Funds
|
|
253
|
+
|
|
254
|
+
Transfer tokens to your Safe smart wallet:
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
// Deposit 100 USDC (6 decimals) to Safe on Arbitrum
|
|
258
|
+
const result = await sdk.depositFunds(
|
|
259
|
+
userAddress,
|
|
260
|
+
42161, // Chain ID
|
|
261
|
+
"0xaf88d065e77c8cc2239327c5edb3a432268e5831", // USDC on Arbitrum
|
|
262
|
+
"100000000" // Amount: 100 USDC = 100 * 10^6
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
if (result.success) {
|
|
266
|
+
console.log("Deposit successful!");
|
|
267
|
+
console.log("Transaction Hash:", result.txHash);
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Note:** Amount must be in least decimal units. For USDC (6 decimals): 1 USDC = 1000000
|
|
272
|
+
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.
|
|
273
|
+
|
|
274
|
+
### 5. Withdraw Funds
|
|
275
|
+
|
|
276
|
+
Withdraw funds from your Safe:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
// Full withdrawal
|
|
280
|
+
const result = await sdk.withdrawFunds(userAddress, 42161);
|
|
281
|
+
|
|
282
|
+
// Partial withdrawal of 50 USDC (6 decimals)
|
|
283
|
+
const result = await sdk.withdrawFunds(
|
|
284
|
+
userAddress,
|
|
285
|
+
42161,
|
|
286
|
+
"50000000", // Amount: 50 USDC = 50 * 10^6
|
|
287
|
+
"0xReceiverAddress" // Optional: receiver address
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
if (result.success) {
|
|
291
|
+
console.log("Withdrawal successful!");
|
|
292
|
+
console.log("Transaction Hash:", result.txHash);
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Note:** Amount must be in least decimal units. For USDC (6 decimals): 1 USDC = 1000000
|
|
297
|
+
The SDK authenticates via SIWE before calling the withdrawal endpoints (`/users/withdraw` or `/users/partial-withdraw`) so you don't need to manage tokens manually.
|
|
298
|
+
|
|
299
|
+
### 6. Get Available Protocols
|
|
300
|
+
|
|
301
|
+
Retrieve all available DeFi protocols and pools for a specific chain:
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
const protocols = await sdk.getAvailableProtocols(42161);
|
|
305
|
+
|
|
306
|
+
console.log(`Found ${protocols.protocols.length} protocols`);
|
|
307
|
+
protocols.protocols.forEach((protocol) => {
|
|
308
|
+
console.log(`${protocol.name} (${protocol.type})`);
|
|
309
|
+
console.log(`Chains: ${protocol.chains.join(", ")}`);
|
|
310
|
+
console.log(`Strategies: ${protocol.strategies?.join(", ") ?? "n/a"}`);
|
|
311
|
+
console.log(`Website: ${protocol.website ?? "n/a"}`);
|
|
312
|
+
console.log(`Pools: ${protocol.pools?.length ?? 0}`);
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Note**: This endpoint fetches protocols from `/api/v1/protocols?chainId={chainId}` and returns additional metadata such as `type`, `strategies`, `chains`, `website`, and an optional `imageUrl`.
|
|
317
|
+
|
|
318
|
+
### 7. Monitor Positions
|
|
319
|
+
|
|
320
|
+
Track all active DeFi positions for a user:
|
|
321
|
+
|
|
322
|
+
```typescript
|
|
323
|
+
const positions = await sdk.getPositions(userAddress);
|
|
324
|
+
positions.positions.forEach((bundle) => {
|
|
325
|
+
console.log(`Chain: ${bundle.chain}, Strategy: ${bundle.strategy}`);
|
|
326
|
+
bundle.positions.forEach((slot) => {
|
|
327
|
+
console.log(`Token: ${slot.token_symbol}, Pool: ${slot.pool}`);
|
|
328
|
+
console.log(`Underlying Amount: ${slot.underlyingAmount}`);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
**Note**: This endpoint uses `/api/v1/data/position?walletAddress={address}` (Smart wallet address) and returns bundles with nested slot data. Use each slot's `underlyingAmount` for the canonical token balance.
|
|
334
|
+
|
|
335
|
+
### 8. Analytics & Data Endpoints
|
|
336
|
+
|
|
337
|
+
The SDK provides access to various analytics and data endpoints:
|
|
338
|
+
|
|
339
|
+
#### Get User Details
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
const user = await sdk.getUserDetails();
|
|
343
|
+
console.log("Smart Wallet:", user.user.smartWallet);
|
|
344
|
+
console.log("Active Chains:", user.user.chains);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### Get TVL & Volume
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const tvl = await sdk.getTVL();
|
|
351
|
+
console.log("Total TVL:", tvl.totalTvl);
|
|
352
|
+
|
|
353
|
+
const volume = await sdk.getVolume();
|
|
354
|
+
console.log("Total Volume:", volume.volumeInUSD);
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### Get Active Wallets
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
const wallets = await sdk.getActiveWallets(8453); // Base chain
|
|
361
|
+
console.log("Active wallet count:", wallets.count);
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
#### Get Smart Wallets by EOA
|
|
365
|
+
|
|
366
|
+
```typescript
|
|
367
|
+
const result = await sdk.getSmartWalletsByEOA("0xYourEOA...");
|
|
368
|
+
console.log("Smart wallets:", result.smartWallets);
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
#### Get Transaction History
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
const history = await sdk.getHistory(walletAddress, 8453, {
|
|
375
|
+
limit: 50,
|
|
376
|
+
fromDate: "2024-01-01",
|
|
377
|
+
});
|
|
378
|
+
history.data.forEach((tx) => console.log(tx.type, tx.amount));
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
### 9. Earnings & Performance
|
|
382
|
+
|
|
383
|
+
#### Get Onchain Earnings
|
|
384
|
+
|
|
385
|
+
```typescript
|
|
386
|
+
const earnings = await sdk.getOnchainEarnings(walletAddress);
|
|
387
|
+
console.log("Total Earnings:", earnings.data.totalEarnings);
|
|
388
|
+
console.log("Current Earnings:", earnings.data.currentEarnings);
|
|
389
|
+
console.log("Lifetime Earnings:", earnings.data.lifetimeEarnings);
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
#### Calculate Onchain Earnings (Refresh)
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
const updated = await sdk.calculateOnchainEarnings(walletAddress);
|
|
396
|
+
console.log("Updated earnings:", updated.data.totalEarnings);
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### Get Daily Earnings
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
const daily = await sdk.getDailyEarnings(
|
|
403
|
+
walletAddress,
|
|
404
|
+
"2024-01-01",
|
|
405
|
+
"2024-01-31"
|
|
406
|
+
);
|
|
407
|
+
daily.data.forEach((d) => console.log(d.date, d.earnings));
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
#### Get Daily APY History
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
const apyHistory = await sdk.getDailyApyHistory(walletAddress, "30D");
|
|
414
|
+
console.log("Average Weighted APY:", apyHistory.averageWeightedApy);
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### 10. Opportunities & Strategies
|
|
418
|
+
|
|
419
|
+
#### Get Safe Opportunities (Low Risk)
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
const safeOpps = await sdk.getSafeOpportunities(8453);
|
|
423
|
+
safeOpps.data.forEach((o) => {
|
|
424
|
+
console.log(`${o.protocolName} - ${o.poolName}: ${o.apy}% APY`);
|
|
425
|
+
});
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
#### Get Degen Strategies (High Risk)
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
const degenStrats = await sdk.getDegenStrategies(8453);
|
|
432
|
+
degenStrats.data.forEach((s) => {
|
|
433
|
+
console.log(`${s.protocolName} - ${s.poolName}: ${s.apy}% APY`);
|
|
434
|
+
});
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 11. Rebalancing
|
|
438
|
+
|
|
439
|
+
#### Get Rebalance Info
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
// Get same-chain rebalances
|
|
443
|
+
const rebalances = await sdk.getRebalanceInfo(false);
|
|
444
|
+
console.log("Rebalance events:", rebalances.count);
|
|
445
|
+
|
|
446
|
+
// Get cross-chain rebalances
|
|
447
|
+
const crossChain = await sdk.getRebalanceInfo(true);
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
#### Get Rebalance Frequency
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
const frequency = await sdk.getRebalanceFrequency(walletAddress);
|
|
454
|
+
console.log("Tier:", frequency.tier);
|
|
455
|
+
console.log("Max rebalances/day:", frequency.frequency);
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### 12. Portfolio (Premium)
|
|
459
|
+
|
|
460
|
+
#### Get Debank Portfolio (Multi-chain)
|
|
461
|
+
|
|
462
|
+
```typescript
|
|
463
|
+
const portfolio = await sdk.getDebankPortfolio(walletAddress);
|
|
464
|
+
console.log("Total Value:", portfolio.totalValueUsd);
|
|
465
|
+
Object.entries(portfolio.chains).forEach(([chain, data]) => {
|
|
466
|
+
console.log(`${chain}: $${data.totalValueUsd}`);
|
|
467
|
+
});
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Note**: The Debank portfolio endpoint is a premium feature and may require additional authorization.
|
|
471
|
+
|
|
472
|
+
## Examples
|
|
473
|
+
|
|
474
|
+
All examples are available in the `examples/` directory:
|
|
475
|
+
|
|
476
|
+
### Core Features
|
|
477
|
+
|
|
478
|
+
1. **`end-to-end.ts`** - Complete workflow demonstrating all SDK features
|
|
479
|
+
2. **`basic-usage.ts`** - Simple Safe deployment workflow
|
|
480
|
+
3. **`create-session-key.ts`** - Session key creation + registration
|
|
481
|
+
4. **`deposit.ts`** - Deposit funds to Safe
|
|
482
|
+
5. **`withdraw.ts`** - Withdraw funds from Safe
|
|
483
|
+
6. **`deposit-withdraw.ts`** - Combined fund management examples
|
|
484
|
+
|
|
485
|
+
### Data Retrieval
|
|
486
|
+
|
|
487
|
+
7. **`get-protocols.ts`** - Fetch available protocols for a chain
|
|
488
|
+
8. **`get-positions.ts`** - Get active positions for a wallet
|
|
489
|
+
9. **`get-user-details.ts`** - Get authenticated user details
|
|
490
|
+
10. **`get-tvl-volume.ts`** - Get TVL and trading volume
|
|
491
|
+
11. **`get-active-wallets.ts`** - Get active wallets by chain
|
|
492
|
+
12. **`get-smart-wallets-by-eoa.ts`** - Get smart wallets by EOA
|
|
493
|
+
13. **`get-first-topup.ts`** - Get first deposit information
|
|
494
|
+
14. **`get-history.ts`** - Get transaction history
|
|
495
|
+
|
|
496
|
+
### Analytics & Earnings
|
|
497
|
+
|
|
498
|
+
15. **`get-onchain-earnings.ts`** - Get/calculate onchain earnings
|
|
499
|
+
16. **`get-daily-earnings.ts`** - Get daily earnings breakdown
|
|
500
|
+
17. **`get-apy-history.ts`** - Get daily APY history with weighted averages
|
|
501
|
+
|
|
502
|
+
### Opportunities & Rebalancing
|
|
503
|
+
|
|
504
|
+
18. **`get-opportunities.ts`** - Get safe and degen yield opportunities
|
|
505
|
+
19. **`get-rebalance-info.ts`** - Get rebalance events and frequency tier
|
|
506
|
+
|
|
507
|
+
### Premium Features
|
|
508
|
+
|
|
509
|
+
20. **`get-debank-portfolio.ts`** - Get Debank multi-chain portfolio
|
|
510
|
+
|
|
511
|
+
### Quick Start: Run the End-to-End Example
|
|
512
|
+
|
|
513
|
+
```bash
|
|
514
|
+
# 1. Set up environment variables
|
|
515
|
+
cp .env.example .env
|
|
516
|
+
# Edit .env with your API keys
|
|
517
|
+
|
|
518
|
+
# 2. Build the SDK
|
|
519
|
+
pnpm install
|
|
520
|
+
pnpm build
|
|
521
|
+
|
|
522
|
+
# 3. Run the complete workflow
|
|
523
|
+
pnpm tsx examples/end-to-end.ts
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
## Complete Examples
|
|
527
|
+
|
|
528
|
+
### Example 1: Deploy Safe on Arbitrum
|
|
529
|
+
|
|
530
|
+
```typescript
|
|
531
|
+
import { ZyfaiSDK } from "@zyfai/sdk";
|
|
532
|
+
|
|
533
|
+
async function main() {
|
|
534
|
+
const sdk = new ZyfaiSDK({
|
|
535
|
+
apiKey: process.env.ZYFAI_API_KEY!,
|
|
536
|
+
bundlerApiKey: process.env.BUNDLER_API_KEY!,
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
// Connect account (for signing)
|
|
540
|
+
await sdk.connectAccount(process.env.PRIVATE_KEY!, 42161);
|
|
541
|
+
|
|
542
|
+
const userAddress = "0xUser..."; // User's EOA address
|
|
543
|
+
|
|
544
|
+
// Check if Safe already exists
|
|
545
|
+
const walletInfo = await sdk.getSmartWalletAddress(userAddress, 42161);
|
|
546
|
+
|
|
547
|
+
if (walletInfo.isDeployed) {
|
|
548
|
+
console.log("Safe already deployed at:", walletInfo.address);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Deploy Safe
|
|
553
|
+
const result = await sdk.deploySafe(userAddress, 42161);
|
|
554
|
+
|
|
555
|
+
if (result.success) {
|
|
556
|
+
console.log("✅ Successfully deployed Safe");
|
|
557
|
+
console.log("Address:", result.safeAddress);
|
|
558
|
+
console.log("Tx Hash:", result.txHash);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
main();
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
### Example 2: Browser Integration with React
|
|
566
|
+
|
|
567
|
+
```typescript
|
|
568
|
+
import { ZyfaiSDK } from "@zyfai/sdk";
|
|
569
|
+
import { useState } from "react";
|
|
570
|
+
|
|
571
|
+
function SafeDeployment() {
|
|
572
|
+
const [sdk] = useState(
|
|
573
|
+
() =>
|
|
574
|
+
new ZyfaiSDK({
|
|
575
|
+
apiKey: process.env.ZYFAI_API_KEY!,
|
|
576
|
+
bundlerApiKey: process.env.BUNDLER_API_KEY!,
|
|
577
|
+
})
|
|
578
|
+
);
|
|
579
|
+
|
|
580
|
+
const [userAddress, setUserAddress] = useState<string>("");
|
|
581
|
+
const [safeAddress, setSafeAddress] = useState<string>("");
|
|
582
|
+
const [isDeploying, setIsDeploying] = useState(false);
|
|
583
|
+
|
|
584
|
+
const handleConnect = async (walletProvider: any) => {
|
|
585
|
+
try {
|
|
586
|
+
// Client passes the wallet provider from their frontend
|
|
587
|
+
// e.g., from wagmi: const provider = await connector.getProvider();
|
|
588
|
+
const address = await sdk.connectAccount(walletProvider); // chainId auto-detected
|
|
589
|
+
setUserAddress(address);
|
|
590
|
+
console.log("Connected:", address);
|
|
591
|
+
|
|
592
|
+
// Get Safe address for this user
|
|
593
|
+
const walletInfo = await sdk.getSmartWalletAddress(address, 42161);
|
|
594
|
+
setSafeAddress(walletInfo.address);
|
|
595
|
+
} catch (error) {
|
|
596
|
+
console.error("Connection failed:", error);
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
|
|
600
|
+
const handleDeploy = async () => {
|
|
601
|
+
if (!userAddress) return;
|
|
602
|
+
|
|
603
|
+
setIsDeploying(true);
|
|
604
|
+
try {
|
|
605
|
+
const result = await sdk.deploySafe(userAddress, 42161);
|
|
606
|
+
if (result.success) {
|
|
607
|
+
alert(`Safe deployed at ${result.safeAddress}`);
|
|
608
|
+
}
|
|
609
|
+
} catch (error) {
|
|
610
|
+
console.error("Deployment failed:", error);
|
|
611
|
+
} finally {
|
|
612
|
+
setIsDeploying(false);
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
return (
|
|
617
|
+
<div>
|
|
618
|
+
<button
|
|
619
|
+
onClick={async () => {
|
|
620
|
+
// Client gets provider from their wallet connection library
|
|
621
|
+
const provider = window.ethereum; // or from wagmi, web3-react, etc.
|
|
622
|
+
await handleConnect(provider);
|
|
623
|
+
}}
|
|
624
|
+
>
|
|
625
|
+
Connect Wallet
|
|
626
|
+
</button>
|
|
627
|
+
{userAddress && (
|
|
628
|
+
<>
|
|
629
|
+
<p>Connected: {userAddress}</p>
|
|
630
|
+
<p>Your Safe: {safeAddress}</p>
|
|
631
|
+
<button onClick={handleDeploy} disabled={isDeploying}>
|
|
632
|
+
{isDeploying ? "Deploying..." : "Deploy Safe"}
|
|
633
|
+
</button>
|
|
634
|
+
</>
|
|
635
|
+
)}
|
|
636
|
+
</div>
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
**Important Note:** The SDK doesn't connect to wallets directly. The client integrating the SDK should handle wallet connection on their frontend and pass the provider to `connectAccount()`.
|
|
642
|
+
|
|
643
|
+
## Architecture
|
|
644
|
+
|
|
645
|
+
The SDK is built on top of:
|
|
646
|
+
|
|
647
|
+
- **Viem**: Low-level Ethereum interactions
|
|
648
|
+
- **Axios**: HTTP client for API communication
|
|
649
|
+
|
|
650
|
+
### How Safe Deployment Works
|
|
651
|
+
|
|
652
|
+
1. **Deterministic Address Generation**: Safe addresses are generated deterministically using CREATE2
|
|
653
|
+
2. **Explicit Parameters**: All methods take explicit user addresses - the connected account is only used for signing
|
|
654
|
+
3. **Multi-User Support**: One SDK instance can manage multiple users
|
|
655
|
+
4. **Backend-Friendly**: Perfect for services managing Safe wallets for multiple users
|
|
656
|
+
|
|
657
|
+
## Error Handling
|
|
658
|
+
|
|
659
|
+
```typescript
|
|
660
|
+
try {
|
|
661
|
+
const userAddress = "0xUser...";
|
|
662
|
+
const result = await sdk.deploySafe(userAddress, 42161);
|
|
663
|
+
if (!result.success) {
|
|
664
|
+
console.error("Deployment failed:", result.status);
|
|
665
|
+
}
|
|
666
|
+
} catch (error) {
|
|
667
|
+
if (error instanceof Error) {
|
|
668
|
+
console.error("Error:", error.message);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
## Best Practices
|
|
674
|
+
|
|
675
|
+
1. **Store API Keys Securely**: Never commit API keys to version control
|
|
676
|
+
2. **Use Environment Variables**: Store keys in `.env` files
|
|
677
|
+
3. **Check Deployment Status**: Always check if Safe is already deployed before deploying
|
|
678
|
+
4. **Handle Errors Gracefully**: Implement proper error handling for all SDK methods
|
|
679
|
+
5. **Validate Chain IDs**: Ensure you're using supported chains (Arbitrum, Base, Plasma)
|
|
680
|
+
6. **Use Explicit Parameters**: Always pass explicit `userAddress` and `chainId` to methods
|
|
681
|
+
|
|
682
|
+
## Environment Variables
|
|
683
|
+
|
|
684
|
+
For running the examples, set up the following environment variables:
|
|
685
|
+
|
|
686
|
+
```bash
|
|
687
|
+
# Required: Execution API key (Safe deployment, transactions, session keys)
|
|
688
|
+
ZYFAI_API_KEY=your-execution-api-key
|
|
689
|
+
|
|
690
|
+
# Optional: Data API key (earnings, opportunities, analytics)
|
|
691
|
+
# Falls back to ZYFAI_API_KEY if not provided
|
|
692
|
+
ZYFAI_DATA_API_KEY=your-data-api-key
|
|
693
|
+
|
|
694
|
+
# Required for Safe deployment: Bundler API key (e.g., Pimlico)
|
|
695
|
+
BUNDLER_API_KEY=your-pimlico-api-key
|
|
696
|
+
|
|
697
|
+
# Required for examples: Private key for signing transactions
|
|
698
|
+
# WARNING: Never commit your private key to version control!
|
|
699
|
+
PRIVATE_KEY=0x...
|
|
700
|
+
|
|
701
|
+
# Optional: Chain ID (default: 8453 for Base)
|
|
702
|
+
# Supported: 42161 (Arbitrum), 8453 (Base), 9745 (Plasma)
|
|
703
|
+
CHAIN_ID=8453
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
## Troubleshooting
|
|
707
|
+
|
|
708
|
+
### "No account connected" Error
|
|
709
|
+
|
|
710
|
+
Make sure to call `connectAccount()` before calling other methods that require signing.
|
|
711
|
+
|
|
712
|
+
### "Unsupported chain" Error
|
|
713
|
+
|
|
714
|
+
Check that the chain ID is in the supported chains list: Arbitrum (42161), Base (8453), or Plasma (9745).
|
|
715
|
+
|
|
716
|
+
## Contributing
|
|
717
|
+
|
|
718
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
719
|
+
|
|
720
|
+
## License
|
|
721
|
+
|
|
722
|
+
MIT
|