@zyfai/sdk 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -6
- package/dist/index.d.mts +67 -21
- package/dist/index.d.ts +67 -21
- package/dist/index.js +96 -53
- package/dist/index.mjs +99 -57
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -229,25 +229,31 @@ The SDK automatically fetches optimal session configuration from ZyFAI API:
|
|
|
229
229
|
```typescript
|
|
230
230
|
// SDK automatically:
|
|
231
231
|
// 1. Authenticates via SIWE (creates user record if needed)
|
|
232
|
-
// 2.
|
|
233
|
-
// 3.
|
|
232
|
+
// 2. Checks if user already has an active session key (returns early if so)
|
|
233
|
+
// 3. Calculates the deterministic Safe address
|
|
234
234
|
// 4. Retrieves personalized config via /session-keys/config
|
|
235
235
|
// 5. Signs the session key
|
|
236
236
|
// 6. Calls /session-keys/add so the session becomes active immediately
|
|
237
237
|
|
|
238
238
|
const result = await sdk.createSessionKey(userAddress, 42161);
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
|
|
240
|
+
// Check if session key already existed
|
|
241
|
+
if (result.alreadyActive) {
|
|
242
|
+
console.log("Session key already active:", result.message);
|
|
243
|
+
} else {
|
|
244
|
+
console.log("Session created:", result.signature);
|
|
245
|
+
console.log("Safe address:", result.sessionKeyAddress);
|
|
246
|
+
console.log("Activation ID:", result.sessionActivation?.id);
|
|
247
|
+
}
|
|
242
248
|
console.log("User ID:", result.userId);
|
|
243
|
-
console.log("Activation ID:", result.sessionActivation?.id);
|
|
244
249
|
```
|
|
245
250
|
|
|
246
251
|
**Important**:
|
|
247
252
|
|
|
248
253
|
- `createSessionKey` requires SIWE authentication (prompts wallet signature on first call)
|
|
254
|
+
- The SDK proactively checks if the user already has an active session key (from login response) and returns early without requiring any signature if one exists
|
|
249
255
|
- The user record must have `smartWallet` and `chainId` set (automatically handled after calling `deploySafe` or `updateUserProfile`)
|
|
250
|
-
-
|
|
256
|
+
- When `alreadyActive` is `true`, `sessionKeyAddress` and `signature` are not available in the response
|
|
251
257
|
|
|
252
258
|
### 4. Deposit Funds
|
|
253
259
|
|
|
@@ -713,6 +719,24 @@ Make sure to call `connectAccount()` before calling other methods that require s
|
|
|
713
719
|
|
|
714
720
|
Check that the chain ID is in the supported chains list: Arbitrum (42161), Base (8453), or Plasma (9745).
|
|
715
721
|
|
|
722
|
+
### SIWE Authentication Issues in Browser
|
|
723
|
+
|
|
724
|
+
The SDK automatically detects browser vs Node.js environments for SIWE authentication:
|
|
725
|
+
- **Browser**: Uses `window.location.origin` for the SIWE message domain/uri to match the browser's automatic `Origin` header
|
|
726
|
+
- **Node.js**: Uses the API endpoint URL
|
|
727
|
+
|
|
728
|
+
If you encounter SIWE authentication failures in a browser, ensure:
|
|
729
|
+
1. Your frontend origin is allowed by the API's CORS configuration
|
|
730
|
+
2. You're using the correct `environment` setting (`staging` or `production`)
|
|
731
|
+
|
|
732
|
+
### Session Key Already Exists
|
|
733
|
+
|
|
734
|
+
If `createSessionKey` returns `{ alreadyActive: true }`, the user already has an active session key. This is not an error - the SDK proactively checks before attempting to create a new one.
|
|
735
|
+
|
|
736
|
+
### Data API CORS Errors
|
|
737
|
+
|
|
738
|
+
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.
|
|
739
|
+
|
|
716
740
|
## Contributing
|
|
717
741
|
|
|
718
742
|
Contributions are welcome! Please open an issue or submit a pull request.
|
package/dist/index.d.mts
CHANGED
|
@@ -7,9 +7,9 @@ type Address = `0x${string}`;
|
|
|
7
7
|
type Hex = `0x${string}`;
|
|
8
8
|
type Environment = "staging" | "production";
|
|
9
9
|
interface SDKConfig {
|
|
10
|
-
/** API key for the Execution API
|
|
10
|
+
/** API key for the Execution API */
|
|
11
11
|
apiKey: string;
|
|
12
|
-
/** API key for the Data API
|
|
12
|
+
/** API key for the Data API - defaults to apiKey if not provided */
|
|
13
13
|
dataApiKey?: string;
|
|
14
14
|
/** Environment: 'staging' or 'production' (default: 'production') */
|
|
15
15
|
environment?: Environment;
|
|
@@ -52,11 +52,17 @@ interface AddSessionKeyResponse {
|
|
|
52
52
|
}
|
|
53
53
|
interface SessionKeyResponse {
|
|
54
54
|
success: boolean;
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
/** Session key address (not available when alreadyActive is true) */
|
|
56
|
+
sessionKeyAddress?: Address;
|
|
57
|
+
/** Signature (not available when alreadyActive is true) */
|
|
58
|
+
signature?: Hex;
|
|
57
59
|
sessionNonces?: bigint[];
|
|
58
60
|
userId?: string;
|
|
59
61
|
sessionActivation?: AddSessionKeyResponse;
|
|
62
|
+
/** Message when session key already exists */
|
|
63
|
+
message?: string;
|
|
64
|
+
/** True if a session key was already active for this user */
|
|
65
|
+
alreadyActive?: boolean;
|
|
60
66
|
}
|
|
61
67
|
interface SmartWalletResponse {
|
|
62
68
|
address: Address;
|
|
@@ -86,19 +92,25 @@ interface ProtocolsResponse {
|
|
|
86
92
|
protocols: Protocol[];
|
|
87
93
|
}
|
|
88
94
|
interface Position {
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
user?: string;
|
|
96
|
+
eoa?: Address;
|
|
97
|
+
chains?: number[];
|
|
91
98
|
strategy?: string;
|
|
92
99
|
smartWallet?: Address;
|
|
93
100
|
positions: PositionSlot[];
|
|
94
101
|
hasActiveSessionKey?: boolean;
|
|
95
102
|
hasBalance?: boolean;
|
|
103
|
+
newSessionKeyAvailable?: boolean;
|
|
104
|
+
hasStaleBalance?: string[];
|
|
105
|
+
contracts?: Address[];
|
|
106
|
+
omniAccount?: boolean;
|
|
96
107
|
crosschainStrategy?: boolean;
|
|
97
108
|
}
|
|
98
109
|
interface PositionSlot {
|
|
99
110
|
chain?: string;
|
|
100
111
|
protocol_id?: string;
|
|
101
112
|
protocol_name?: string;
|
|
113
|
+
protocol_icon?: string;
|
|
102
114
|
pool?: string;
|
|
103
115
|
token_id?: string;
|
|
104
116
|
token_symbol?: string;
|
|
@@ -106,12 +118,11 @@ interface PositionSlot {
|
|
|
106
118
|
amount?: string;
|
|
107
119
|
underlyingAmount?: string;
|
|
108
120
|
pool_apy?: number;
|
|
109
|
-
pool_tvl?:
|
|
121
|
+
pool_tvl?: number;
|
|
110
122
|
}
|
|
111
123
|
interface PositionsResponse {
|
|
112
124
|
success: boolean;
|
|
113
125
|
userAddress: string;
|
|
114
|
-
totalValueUsd: number;
|
|
115
126
|
positions: Position[];
|
|
116
127
|
}
|
|
117
128
|
interface UserDetails {
|
|
@@ -136,10 +147,18 @@ interface UserDetailsResponse {
|
|
|
136
147
|
success: boolean;
|
|
137
148
|
user: UserDetails;
|
|
138
149
|
}
|
|
150
|
+
interface TVLBreakdown {
|
|
151
|
+
chain_id: number;
|
|
152
|
+
protocol_id: string | null;
|
|
153
|
+
protocol_name: string | null;
|
|
154
|
+
pool: string | null;
|
|
155
|
+
total_balance: number;
|
|
156
|
+
}
|
|
139
157
|
interface TVLResponse {
|
|
140
158
|
success: boolean;
|
|
141
159
|
totalTvl: number;
|
|
142
|
-
byChain?: Record<
|
|
160
|
+
byChain?: Record<number, number>;
|
|
161
|
+
breakdown?: TVLBreakdown[];
|
|
143
162
|
}
|
|
144
163
|
interface VolumeResponse {
|
|
145
164
|
success: boolean;
|
|
@@ -159,7 +178,9 @@ interface ActiveWalletsResponse {
|
|
|
159
178
|
interface SmartWalletsByEOAResponse {
|
|
160
179
|
success: boolean;
|
|
161
180
|
eoa: string;
|
|
181
|
+
smartWallet: string | null;
|
|
162
182
|
smartWallets: string[];
|
|
183
|
+
chains: number[];
|
|
163
184
|
}
|
|
164
185
|
interface FirstTopupResponse {
|
|
165
186
|
success: boolean;
|
|
@@ -168,16 +189,33 @@ interface FirstTopupResponse {
|
|
|
168
189
|
amount?: string;
|
|
169
190
|
chainId?: number;
|
|
170
191
|
}
|
|
192
|
+
interface HistoryPosition {
|
|
193
|
+
pool?: string;
|
|
194
|
+
amount?: string;
|
|
195
|
+
token_id?: string;
|
|
196
|
+
token_icon?: string;
|
|
197
|
+
amountInUSD?: string;
|
|
198
|
+
protocol_id?: string;
|
|
199
|
+
token_symbol?: string;
|
|
200
|
+
protocol_icon?: string;
|
|
201
|
+
protocol_name?: string;
|
|
202
|
+
}
|
|
171
203
|
interface HistoryEntry {
|
|
172
204
|
id?: string;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
txHash?: string;
|
|
205
|
+
action?: string;
|
|
206
|
+
date?: string;
|
|
207
|
+
strategy?: string;
|
|
208
|
+
positions?: HistoryPosition[];
|
|
178
209
|
chainId?: number;
|
|
179
|
-
|
|
180
|
-
|
|
210
|
+
transactionHash?: string;
|
|
211
|
+
destinationChainId?: number;
|
|
212
|
+
sourceChains?: number[];
|
|
213
|
+
crosschain?: boolean;
|
|
214
|
+
rebalance?: boolean;
|
|
215
|
+
zkProofIpfsHash?: string;
|
|
216
|
+
validationRegistryTxHash?: string;
|
|
217
|
+
validationRegistryChainId?: number;
|
|
218
|
+
validationRegistryAddress?: string;
|
|
181
219
|
}
|
|
182
220
|
interface HistoryResponse {
|
|
183
221
|
success: boolean;
|
|
@@ -200,10 +238,17 @@ interface OnchainEarningsResponse {
|
|
|
200
238
|
data: OnchainEarnings;
|
|
201
239
|
}
|
|
202
240
|
interface DailyEarning {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
241
|
+
wallet_address?: string;
|
|
242
|
+
snapshot_date: string;
|
|
243
|
+
total_current_earnings: number;
|
|
244
|
+
total_lifetime_earnings: number;
|
|
245
|
+
total_unrealized_earnings: number;
|
|
246
|
+
total_earnings: number;
|
|
247
|
+
daily_current_delta: number;
|
|
248
|
+
daily_lifetime_delta: number;
|
|
249
|
+
daily_unrealized_delta: number;
|
|
250
|
+
daily_total_delta: number;
|
|
251
|
+
created_at?: string;
|
|
207
252
|
}
|
|
208
253
|
interface DailyEarningsResponse {
|
|
209
254
|
success: boolean;
|
|
@@ -365,6 +410,7 @@ declare class ZyfaiSDK {
|
|
|
365
410
|
private bundlerApiKey?;
|
|
366
411
|
private isAuthenticated;
|
|
367
412
|
private authenticatedUserId;
|
|
413
|
+
private hasActiveSessionKey;
|
|
368
414
|
private environment;
|
|
369
415
|
constructor(config: SDKConfig | string);
|
|
370
416
|
/**
|
|
@@ -766,4 +812,4 @@ declare class ZyfaiSDK {
|
|
|
766
812
|
getRebalanceFrequency(walletAddress: string): Promise<RebalanceFrequencyResponse>;
|
|
767
813
|
}
|
|
768
814
|
|
|
769
|
-
export { type ActionData, type ActiveWallet, type ActiveWalletsResponse, type Address, type ChainConfig, type ChainPortfolio, type DailyApyEntry, type DailyApyHistoryResponse, type DailyEarning, type DailyEarningsResponse, type DebankPortfolioResponse, type DeploySafeResponse, type DepositResponse, type ERC7739Context, type ERC7739Data, type Environment, type FirstTopupResponse, type Hex, type HistoryEntry, type HistoryResponse, type OnchainEarnings, type OnchainEarningsResponse, type OpportunitiesResponse, type Opportunity, type PolicyData, type Pool, type PortfolioToken, type Position, type PositionSlot, type PositionsResponse, type Protocol, type ProtocolsResponse, type RebalanceFrequencyResponse, type RebalanceInfo, type RebalanceInfoResponse, type SDKConfig, type Session, type SessionKeyResponse, type SmartWalletResponse, type SmartWalletsByEOAResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
|
|
815
|
+
export { type ActionData, type ActiveWallet, type ActiveWalletsResponse, type Address, type ChainConfig, type ChainPortfolio, type DailyApyEntry, type DailyApyHistoryResponse, type DailyEarning, type DailyEarningsResponse, type DebankPortfolioResponse, type DeploySafeResponse, type DepositResponse, type ERC7739Context, type ERC7739Data, type Environment, type FirstTopupResponse, type Hex, type HistoryEntry, type HistoryPosition, type HistoryResponse, type OnchainEarnings, type OnchainEarningsResponse, type OpportunitiesResponse, type Opportunity, type PolicyData, type Pool, type PortfolioToken, type Position, type PositionSlot, type PositionsResponse, type Protocol, type ProtocolsResponse, type RebalanceFrequencyResponse, type RebalanceInfo, type RebalanceInfoResponse, type SDKConfig, type Session, type SessionKeyResponse, type SmartWalletResponse, type SmartWalletsByEOAResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,9 +7,9 @@ type Address = `0x${string}`;
|
|
|
7
7
|
type Hex = `0x${string}`;
|
|
8
8
|
type Environment = "staging" | "production";
|
|
9
9
|
interface SDKConfig {
|
|
10
|
-
/** API key for the Execution API
|
|
10
|
+
/** API key for the Execution API */
|
|
11
11
|
apiKey: string;
|
|
12
|
-
/** API key for the Data API
|
|
12
|
+
/** API key for the Data API - defaults to apiKey if not provided */
|
|
13
13
|
dataApiKey?: string;
|
|
14
14
|
/** Environment: 'staging' or 'production' (default: 'production') */
|
|
15
15
|
environment?: Environment;
|
|
@@ -52,11 +52,17 @@ interface AddSessionKeyResponse {
|
|
|
52
52
|
}
|
|
53
53
|
interface SessionKeyResponse {
|
|
54
54
|
success: boolean;
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
/** Session key address (not available when alreadyActive is true) */
|
|
56
|
+
sessionKeyAddress?: Address;
|
|
57
|
+
/** Signature (not available when alreadyActive is true) */
|
|
58
|
+
signature?: Hex;
|
|
57
59
|
sessionNonces?: bigint[];
|
|
58
60
|
userId?: string;
|
|
59
61
|
sessionActivation?: AddSessionKeyResponse;
|
|
62
|
+
/** Message when session key already exists */
|
|
63
|
+
message?: string;
|
|
64
|
+
/** True if a session key was already active for this user */
|
|
65
|
+
alreadyActive?: boolean;
|
|
60
66
|
}
|
|
61
67
|
interface SmartWalletResponse {
|
|
62
68
|
address: Address;
|
|
@@ -86,19 +92,25 @@ interface ProtocolsResponse {
|
|
|
86
92
|
protocols: Protocol[];
|
|
87
93
|
}
|
|
88
94
|
interface Position {
|
|
89
|
-
|
|
90
|
-
|
|
95
|
+
user?: string;
|
|
96
|
+
eoa?: Address;
|
|
97
|
+
chains?: number[];
|
|
91
98
|
strategy?: string;
|
|
92
99
|
smartWallet?: Address;
|
|
93
100
|
positions: PositionSlot[];
|
|
94
101
|
hasActiveSessionKey?: boolean;
|
|
95
102
|
hasBalance?: boolean;
|
|
103
|
+
newSessionKeyAvailable?: boolean;
|
|
104
|
+
hasStaleBalance?: string[];
|
|
105
|
+
contracts?: Address[];
|
|
106
|
+
omniAccount?: boolean;
|
|
96
107
|
crosschainStrategy?: boolean;
|
|
97
108
|
}
|
|
98
109
|
interface PositionSlot {
|
|
99
110
|
chain?: string;
|
|
100
111
|
protocol_id?: string;
|
|
101
112
|
protocol_name?: string;
|
|
113
|
+
protocol_icon?: string;
|
|
102
114
|
pool?: string;
|
|
103
115
|
token_id?: string;
|
|
104
116
|
token_symbol?: string;
|
|
@@ -106,12 +118,11 @@ interface PositionSlot {
|
|
|
106
118
|
amount?: string;
|
|
107
119
|
underlyingAmount?: string;
|
|
108
120
|
pool_apy?: number;
|
|
109
|
-
pool_tvl?:
|
|
121
|
+
pool_tvl?: number;
|
|
110
122
|
}
|
|
111
123
|
interface PositionsResponse {
|
|
112
124
|
success: boolean;
|
|
113
125
|
userAddress: string;
|
|
114
|
-
totalValueUsd: number;
|
|
115
126
|
positions: Position[];
|
|
116
127
|
}
|
|
117
128
|
interface UserDetails {
|
|
@@ -136,10 +147,18 @@ interface UserDetailsResponse {
|
|
|
136
147
|
success: boolean;
|
|
137
148
|
user: UserDetails;
|
|
138
149
|
}
|
|
150
|
+
interface TVLBreakdown {
|
|
151
|
+
chain_id: number;
|
|
152
|
+
protocol_id: string | null;
|
|
153
|
+
protocol_name: string | null;
|
|
154
|
+
pool: string | null;
|
|
155
|
+
total_balance: number;
|
|
156
|
+
}
|
|
139
157
|
interface TVLResponse {
|
|
140
158
|
success: boolean;
|
|
141
159
|
totalTvl: number;
|
|
142
|
-
byChain?: Record<
|
|
160
|
+
byChain?: Record<number, number>;
|
|
161
|
+
breakdown?: TVLBreakdown[];
|
|
143
162
|
}
|
|
144
163
|
interface VolumeResponse {
|
|
145
164
|
success: boolean;
|
|
@@ -159,7 +178,9 @@ interface ActiveWalletsResponse {
|
|
|
159
178
|
interface SmartWalletsByEOAResponse {
|
|
160
179
|
success: boolean;
|
|
161
180
|
eoa: string;
|
|
181
|
+
smartWallet: string | null;
|
|
162
182
|
smartWallets: string[];
|
|
183
|
+
chains: number[];
|
|
163
184
|
}
|
|
164
185
|
interface FirstTopupResponse {
|
|
165
186
|
success: boolean;
|
|
@@ -168,16 +189,33 @@ interface FirstTopupResponse {
|
|
|
168
189
|
amount?: string;
|
|
169
190
|
chainId?: number;
|
|
170
191
|
}
|
|
192
|
+
interface HistoryPosition {
|
|
193
|
+
pool?: string;
|
|
194
|
+
amount?: string;
|
|
195
|
+
token_id?: string;
|
|
196
|
+
token_icon?: string;
|
|
197
|
+
amountInUSD?: string;
|
|
198
|
+
protocol_id?: string;
|
|
199
|
+
token_symbol?: string;
|
|
200
|
+
protocol_icon?: string;
|
|
201
|
+
protocol_name?: string;
|
|
202
|
+
}
|
|
171
203
|
interface HistoryEntry {
|
|
172
204
|
id?: string;
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
txHash?: string;
|
|
205
|
+
action?: string;
|
|
206
|
+
date?: string;
|
|
207
|
+
strategy?: string;
|
|
208
|
+
positions?: HistoryPosition[];
|
|
178
209
|
chainId?: number;
|
|
179
|
-
|
|
180
|
-
|
|
210
|
+
transactionHash?: string;
|
|
211
|
+
destinationChainId?: number;
|
|
212
|
+
sourceChains?: number[];
|
|
213
|
+
crosschain?: boolean;
|
|
214
|
+
rebalance?: boolean;
|
|
215
|
+
zkProofIpfsHash?: string;
|
|
216
|
+
validationRegistryTxHash?: string;
|
|
217
|
+
validationRegistryChainId?: number;
|
|
218
|
+
validationRegistryAddress?: string;
|
|
181
219
|
}
|
|
182
220
|
interface HistoryResponse {
|
|
183
221
|
success: boolean;
|
|
@@ -200,10 +238,17 @@ interface OnchainEarningsResponse {
|
|
|
200
238
|
data: OnchainEarnings;
|
|
201
239
|
}
|
|
202
240
|
interface DailyEarning {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
241
|
+
wallet_address?: string;
|
|
242
|
+
snapshot_date: string;
|
|
243
|
+
total_current_earnings: number;
|
|
244
|
+
total_lifetime_earnings: number;
|
|
245
|
+
total_unrealized_earnings: number;
|
|
246
|
+
total_earnings: number;
|
|
247
|
+
daily_current_delta: number;
|
|
248
|
+
daily_lifetime_delta: number;
|
|
249
|
+
daily_unrealized_delta: number;
|
|
250
|
+
daily_total_delta: number;
|
|
251
|
+
created_at?: string;
|
|
207
252
|
}
|
|
208
253
|
interface DailyEarningsResponse {
|
|
209
254
|
success: boolean;
|
|
@@ -365,6 +410,7 @@ declare class ZyfaiSDK {
|
|
|
365
410
|
private bundlerApiKey?;
|
|
366
411
|
private isAuthenticated;
|
|
367
412
|
private authenticatedUserId;
|
|
413
|
+
private hasActiveSessionKey;
|
|
368
414
|
private environment;
|
|
369
415
|
constructor(config: SDKConfig | string);
|
|
370
416
|
/**
|
|
@@ -766,4 +812,4 @@ declare class ZyfaiSDK {
|
|
|
766
812
|
getRebalanceFrequency(walletAddress: string): Promise<RebalanceFrequencyResponse>;
|
|
767
813
|
}
|
|
768
814
|
|
|
769
|
-
export { type ActionData, type ActiveWallet, type ActiveWalletsResponse, type Address, type ChainConfig, type ChainPortfolio, type DailyApyEntry, type DailyApyHistoryResponse, type DailyEarning, type DailyEarningsResponse, type DebankPortfolioResponse, type DeploySafeResponse, type DepositResponse, type ERC7739Context, type ERC7739Data, type Environment, type FirstTopupResponse, type Hex, type HistoryEntry, type HistoryResponse, type OnchainEarnings, type OnchainEarningsResponse, type OpportunitiesResponse, type Opportunity, type PolicyData, type Pool, type PortfolioToken, type Position, type PositionSlot, type PositionsResponse, type Protocol, type ProtocolsResponse, type RebalanceFrequencyResponse, type RebalanceInfo, type RebalanceInfoResponse, type SDKConfig, type Session, type SessionKeyResponse, type SmartWalletResponse, type SmartWalletsByEOAResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
|
|
815
|
+
export { type ActionData, type ActiveWallet, type ActiveWalletsResponse, type Address, type ChainConfig, type ChainPortfolio, type DailyApyEntry, type DailyApyHistoryResponse, type DailyEarning, type DailyEarningsResponse, type DebankPortfolioResponse, type DeploySafeResponse, type DepositResponse, type ERC7739Context, type ERC7739Data, type Environment, type FirstTopupResponse, type Hex, type HistoryEntry, type HistoryPosition, type HistoryResponse, type OnchainEarnings, type OnchainEarningsResponse, type OpportunitiesResponse, type Opportunity, type PolicyData, type Pool, type PortfolioToken, type Position, type PositionSlot, type PositionsResponse, type Protocol, type ProtocolsResponse, type RebalanceFrequencyResponse, type RebalanceInfo, type RebalanceInfoResponse, type SDKConfig, type Session, type SessionKeyResponse, type SmartWalletResponse, type SmartWalletsByEOAResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
|
package/dist/index.js
CHANGED
|
@@ -87,7 +87,7 @@ var DATA_ENDPOINTS = {
|
|
|
87
87
|
// Portfolio
|
|
88
88
|
DEBANK_PORTFOLIO_MULTICHAIN: (address) => `/debank/portfolio/multichain/${address}`,
|
|
89
89
|
// Opportunities
|
|
90
|
-
OPPORTUNITIES_SAFE: (chainId) => chainId ? `/opportunities/
|
|
90
|
+
OPPORTUNITIES_SAFE: (chainId) => chainId ? `/opportunities/safe?chainId=${chainId}` : "/opportunities/safe",
|
|
91
91
|
OPPORTUNITIES_DEGEN: (chainId) => chainId ? `/opportunities/degen-strategies?chainId=${chainId}` : "/opportunities/degen-strategies",
|
|
92
92
|
// APY History
|
|
93
93
|
DAILY_APY_HISTORY_WEIGHTED: (walletAddress, days) => `/daily-apy-history/weighted/${walletAddress}${days ? `?days=${days}` : ""}`,
|
|
@@ -100,9 +100,9 @@ var HttpClient = class {
|
|
|
100
100
|
/**
|
|
101
101
|
* Create HTTP client for both Execution API and Data API
|
|
102
102
|
*
|
|
103
|
-
* @param apiKey - API key for Execution API
|
|
103
|
+
* @param apiKey - API key for Execution API
|
|
104
104
|
* @param environment - 'staging' or 'production'
|
|
105
|
-
* @param dataApiKey - API key for Data API
|
|
105
|
+
* @param dataApiKey - API key for Data API - defaults to apiKey
|
|
106
106
|
*/
|
|
107
107
|
constructor(apiKey, environment = "production", dataApiKey) {
|
|
108
108
|
this.authToken = null;
|
|
@@ -116,8 +116,7 @@ var HttpClient = class {
|
|
|
116
116
|
baseURL: `${endpoint}${API_VERSION}`,
|
|
117
117
|
headers: {
|
|
118
118
|
"Content-Type": "application/json",
|
|
119
|
-
"X-API-Key": this.apiKey
|
|
120
|
-
Origin: this.origin
|
|
119
|
+
"X-API-Key": this.apiKey
|
|
121
120
|
},
|
|
122
121
|
timeout: 3e4
|
|
123
122
|
});
|
|
@@ -149,7 +148,6 @@ var HttpClient = class {
|
|
|
149
148
|
this.client.interceptors.request.use(
|
|
150
149
|
(config) => {
|
|
151
150
|
config.headers["X-API-Key"] = this.apiKey;
|
|
152
|
-
config.headers["Origin"] = this.origin;
|
|
153
151
|
if (this.authToken) {
|
|
154
152
|
config.headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
155
153
|
}
|
|
@@ -218,6 +216,9 @@ var HttpClient = class {
|
|
|
218
216
|
this.dataClient.interceptors.request.use(
|
|
219
217
|
(config) => {
|
|
220
218
|
config.headers["X-API-Key"] = this.dataApiKey;
|
|
219
|
+
if (this.authToken) {
|
|
220
|
+
config.headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
221
|
+
}
|
|
221
222
|
return config;
|
|
222
223
|
},
|
|
223
224
|
(error) => Promise.reject(error)
|
|
@@ -404,7 +405,6 @@ var getBundlerUrl = (chainId, bundlerApiKey, bundlerProvider = "pimlico") => {
|
|
|
404
405
|
// src/utils/safe-account.ts
|
|
405
406
|
var import_module_sdk = require("@rhinestone/module-sdk");
|
|
406
407
|
var import_permissionless = require("permissionless");
|
|
407
|
-
var import_actions = require("permissionless/actions");
|
|
408
408
|
var import_erc7579 = require("permissionless/actions/erc7579");
|
|
409
409
|
var import_pimlico = require("permissionless/clients/pimlico");
|
|
410
410
|
var import_accounts = require("permissionless/accounts");
|
|
@@ -412,27 +412,36 @@ var import_viem3 = require("viem");
|
|
|
412
412
|
var import_account_abstraction = require("viem/account-abstraction");
|
|
413
413
|
var SAFE_7579_ADDRESS = "0x7579EE8307284F293B1927136486880611F20002";
|
|
414
414
|
var ERC7579_LAUNCHPAD_ADDRESS = "0x7579011aB74c46090561ea277Ba79D510c6C00ff";
|
|
415
|
-
var
|
|
415
|
+
var ACCOUNT_SALTS = {
|
|
416
|
+
staging: "zyfai-staging",
|
|
417
|
+
production: "zyfai-production"
|
|
418
|
+
};
|
|
416
419
|
var getSafeAccount = async (config) => {
|
|
417
420
|
const {
|
|
418
421
|
owner,
|
|
419
422
|
safeOwnerAddress,
|
|
420
423
|
publicClient,
|
|
421
|
-
|
|
424
|
+
environment = "production"
|
|
422
425
|
} = config;
|
|
426
|
+
const effectiveSalt = ACCOUNT_SALTS[environment];
|
|
423
427
|
if (!owner || !owner.account) {
|
|
424
428
|
throw new Error("Wallet not connected. Please connect your wallet first.");
|
|
425
429
|
}
|
|
426
|
-
const
|
|
430
|
+
const signerAddress = owner.account.address;
|
|
431
|
+
if (safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase()) {
|
|
432
|
+
throw new Error(
|
|
433
|
+
`Connected wallet address (${signerAddress}) must match the Safe owner address (${safeOwnerAddress}). Please connect with the correct wallet.`
|
|
434
|
+
);
|
|
435
|
+
}
|
|
427
436
|
const ownableValidator = (0, import_module_sdk.getOwnableValidator)({
|
|
428
|
-
owners: [
|
|
437
|
+
owners: [signerAddress],
|
|
429
438
|
threshold: 1
|
|
430
439
|
});
|
|
431
|
-
const saltHex = (0, import_viem3.fromHex)((0, import_viem3.toHex)(
|
|
440
|
+
const saltHex = (0, import_viem3.fromHex)((0, import_viem3.toHex)(effectiveSalt), "bigint");
|
|
432
441
|
const safeAccount = await (0, import_accounts.toSafeSmartAccount)({
|
|
433
442
|
client: publicClient,
|
|
434
443
|
owners: [owner.account],
|
|
435
|
-
//
|
|
444
|
+
// Pass the account object with address and signMessage capability
|
|
436
445
|
version: "1.4.1",
|
|
437
446
|
entryPoint: {
|
|
438
447
|
address: import_account_abstraction.entryPoint07Address,
|
|
@@ -565,8 +574,8 @@ var deploySafeAccount = async (config) => {
|
|
|
565
574
|
);
|
|
566
575
|
}
|
|
567
576
|
};
|
|
568
|
-
var signSessionKey = async (config, sessions) => {
|
|
569
|
-
const { owner, publicClient
|
|
577
|
+
var signSessionKey = async (config, sessions, allPublicClients) => {
|
|
578
|
+
const { owner, publicClient } = config;
|
|
570
579
|
if (!owner || !owner.account) {
|
|
571
580
|
throw new Error("Wallet not connected. Please connect your wallet first.");
|
|
572
581
|
}
|
|
@@ -575,21 +584,24 @@ var signSessionKey = async (config, sessions) => {
|
|
|
575
584
|
address: safeAccount.address,
|
|
576
585
|
type: "safe"
|
|
577
586
|
});
|
|
587
|
+
const clients = allPublicClients || [publicClient];
|
|
578
588
|
const sessionNonces = await Promise.all(
|
|
579
|
-
sessions.map(
|
|
580
|
-
|
|
581
|
-
|
|
589
|
+
sessions.map((session) => {
|
|
590
|
+
const sessionChainId = Number(session.chainId);
|
|
591
|
+
const client = clients.find((c) => c.chain?.id === sessionChainId) || publicClient;
|
|
592
|
+
return (0, import_module_sdk.getSessionNonce)({
|
|
593
|
+
client,
|
|
582
594
|
account,
|
|
583
595
|
permissionId: (0, import_module_sdk.getPermissionId)({
|
|
584
596
|
session
|
|
585
597
|
})
|
|
586
|
-
})
|
|
587
|
-
)
|
|
598
|
+
});
|
|
599
|
+
})
|
|
588
600
|
);
|
|
589
601
|
const sessionDetails = await (0, import_module_sdk.getEnableSessionDetails)({
|
|
590
602
|
sessions,
|
|
591
603
|
account,
|
|
592
|
-
clients
|
|
604
|
+
clients,
|
|
593
605
|
permitGenericPolicy: true,
|
|
594
606
|
sessionNonces
|
|
595
607
|
});
|
|
@@ -608,13 +620,14 @@ var signSessionKey = async (config, sessions) => {
|
|
|
608
620
|
// src/core/ZyfaiSDK.ts
|
|
609
621
|
var import_siwe = require("siwe");
|
|
610
622
|
var ZyfaiSDK = class {
|
|
611
|
-
// TODO: The
|
|
623
|
+
// TODO: The environment should be removed. Having the same key for staging and production is not ideal, but for now it's fine.
|
|
612
624
|
constructor(config) {
|
|
613
625
|
this.signer = null;
|
|
614
626
|
this.walletClient = null;
|
|
615
627
|
this.isAuthenticated = false;
|
|
616
|
-
// TODO: Check with Utkir for how long the authentication token is valid for.
|
|
617
628
|
this.authenticatedUserId = null;
|
|
629
|
+
// Stored from login response
|
|
630
|
+
this.hasActiveSessionKey = false;
|
|
618
631
|
const sdkConfig = typeof config === "string" ? { apiKey: config } : config;
|
|
619
632
|
const { apiKey, dataApiKey, environment, bundlerApiKey } = sdkConfig;
|
|
620
633
|
if (!apiKey) {
|
|
@@ -637,11 +650,19 @@ var ZyfaiSDK = class {
|
|
|
637
650
|
return;
|
|
638
651
|
}
|
|
639
652
|
const walletClient = this.getWalletClient();
|
|
640
|
-
const userAddress = walletClient.account.address;
|
|
653
|
+
const userAddress = (0, import_viem4.getAddress)(walletClient.account.address);
|
|
641
654
|
const chainId = walletClient.chain?.id || 8453;
|
|
642
655
|
const challengeResponse = await this.httpClient.post(ENDPOINTS.AUTH_CHALLENGE, {});
|
|
643
|
-
|
|
644
|
-
|
|
656
|
+
let uri;
|
|
657
|
+
let domain;
|
|
658
|
+
const globalWindow = typeof globalThis !== "undefined" ? globalThis.window : void 0;
|
|
659
|
+
if (globalWindow?.location?.origin) {
|
|
660
|
+
uri = globalWindow.location.origin;
|
|
661
|
+
domain = globalWindow.location.host;
|
|
662
|
+
} else {
|
|
663
|
+
uri = API_ENDPOINTS[this.environment];
|
|
664
|
+
domain = API_ENDPOINTS[this.environment].split("//")[1];
|
|
665
|
+
}
|
|
645
666
|
const messageObj = new import_siwe.SiweMessage({
|
|
646
667
|
address: userAddress,
|
|
647
668
|
chainId,
|
|
@@ -662,11 +683,6 @@ var ZyfaiSDK = class {
|
|
|
662
683
|
{
|
|
663
684
|
message: messageObj,
|
|
664
685
|
signature
|
|
665
|
-
},
|
|
666
|
-
{
|
|
667
|
-
headers: {
|
|
668
|
-
Origin: uri
|
|
669
|
-
}
|
|
670
686
|
}
|
|
671
687
|
);
|
|
672
688
|
const authToken = loginResponse.accessToken || loginResponse.token;
|
|
@@ -675,6 +691,7 @@ var ZyfaiSDK = class {
|
|
|
675
691
|
}
|
|
676
692
|
this.httpClient.setAuthToken(authToken);
|
|
677
693
|
this.authenticatedUserId = loginResponse.userId || null;
|
|
694
|
+
this.hasActiveSessionKey = loginResponse.hasActiveSessionKey || false;
|
|
678
695
|
this.isAuthenticated = true;
|
|
679
696
|
} catch (error) {
|
|
680
697
|
throw new Error(
|
|
@@ -824,7 +841,8 @@ var ZyfaiSDK = class {
|
|
|
824
841
|
owner: walletClient,
|
|
825
842
|
safeOwnerAddress: userAddress,
|
|
826
843
|
chain: chainConfig.chain,
|
|
827
|
-
publicClient: chainConfig.publicClient
|
|
844
|
+
publicClient: chainConfig.publicClient,
|
|
845
|
+
environment: this.environment
|
|
828
846
|
});
|
|
829
847
|
const isDeployed = await isSafeDeployed(
|
|
830
848
|
safeAddress,
|
|
@@ -872,7 +890,8 @@ var ZyfaiSDK = class {
|
|
|
872
890
|
safeOwnerAddress: userAddress,
|
|
873
891
|
chain: chainConfig.chain,
|
|
874
892
|
publicClient: chainConfig.publicClient,
|
|
875
|
-
bundlerUrl
|
|
893
|
+
bundlerUrl,
|
|
894
|
+
environment: this.environment
|
|
876
895
|
});
|
|
877
896
|
try {
|
|
878
897
|
await this.updateUserProfile({
|
|
@@ -919,14 +938,14 @@ var ZyfaiSDK = class {
|
|
|
919
938
|
"User ID not available. Please ensure authentication completed successfully."
|
|
920
939
|
);
|
|
921
940
|
}
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
}
|
|
941
|
+
if (this.hasActiveSessionKey) {
|
|
942
|
+
return {
|
|
943
|
+
success: true,
|
|
944
|
+
userId: this.authenticatedUserId,
|
|
945
|
+
message: "Session key already exists and is active",
|
|
946
|
+
alreadyActive: true
|
|
947
|
+
};
|
|
948
|
+
}
|
|
930
949
|
const sessionConfig = await this.httpClient.get(
|
|
931
950
|
ENDPOINTS.SESSION_KEYS_CONFIG
|
|
932
951
|
);
|
|
@@ -942,10 +961,14 @@ var ZyfaiSDK = class {
|
|
|
942
961
|
chainId,
|
|
943
962
|
sessions
|
|
944
963
|
);
|
|
964
|
+
if (!signatureResult.signature) {
|
|
965
|
+
throw new Error("Failed to obtain session key signature");
|
|
966
|
+
}
|
|
945
967
|
const activation = await this.activateSessionKey(
|
|
946
968
|
signatureResult.signature,
|
|
947
969
|
signatureResult.sessionNonces
|
|
948
970
|
);
|
|
971
|
+
this.hasActiveSessionKey = true;
|
|
949
972
|
return {
|
|
950
973
|
...signatureResult,
|
|
951
974
|
userId: this.authenticatedUserId,
|
|
@@ -983,20 +1006,27 @@ var ZyfaiSDK = class {
|
|
|
983
1006
|
`Invalid account type for ${userAddress}. Must be an EOA.`
|
|
984
1007
|
);
|
|
985
1008
|
}
|
|
1009
|
+
const sessionChainIds = [
|
|
1010
|
+
...new Set(sessions.map((s) => Number(s.chainId)))
|
|
1011
|
+
];
|
|
1012
|
+
const allPublicClients = sessionChainIds.filter(isSupportedChain).map((id) => getChainConfig(id).publicClient);
|
|
986
1013
|
const { signature, sessionNonces } = await signSessionKey(
|
|
987
1014
|
{
|
|
988
1015
|
owner: walletClient,
|
|
989
1016
|
safeOwnerAddress: userAddress,
|
|
990
1017
|
chain: chainConfig.chain,
|
|
991
|
-
publicClient: chainConfig.publicClient
|
|
1018
|
+
publicClient: chainConfig.publicClient,
|
|
1019
|
+
environment: this.environment
|
|
992
1020
|
},
|
|
993
|
-
sessions
|
|
1021
|
+
sessions,
|
|
1022
|
+
allPublicClients
|
|
994
1023
|
);
|
|
995
1024
|
const safeAddress = await getDeterministicSafeAddress({
|
|
996
1025
|
owner: walletClient,
|
|
997
1026
|
safeOwnerAddress: userAddress,
|
|
998
1027
|
chain: chainConfig.chain,
|
|
999
|
-
publicClient: chainConfig.publicClient
|
|
1028
|
+
publicClient: chainConfig.publicClient,
|
|
1029
|
+
environment: this.environment
|
|
1000
1030
|
});
|
|
1001
1031
|
return {
|
|
1002
1032
|
success: true,
|
|
@@ -1082,7 +1112,8 @@ var ZyfaiSDK = class {
|
|
|
1082
1112
|
owner: walletClient,
|
|
1083
1113
|
safeOwnerAddress: userAddress,
|
|
1084
1114
|
chain: chainConfig.chain,
|
|
1085
|
-
publicClient: chainConfig.publicClient
|
|
1115
|
+
publicClient: chainConfig.publicClient,
|
|
1116
|
+
environment: this.environment
|
|
1086
1117
|
});
|
|
1087
1118
|
const isDeployed = await isSafeDeployed(
|
|
1088
1119
|
safeAddress,
|
|
@@ -1157,7 +1188,8 @@ var ZyfaiSDK = class {
|
|
|
1157
1188
|
owner: walletClient,
|
|
1158
1189
|
safeOwnerAddress: userAddress,
|
|
1159
1190
|
chain: chainConfig.chain,
|
|
1160
|
-
publicClient: chainConfig.publicClient
|
|
1191
|
+
publicClient: chainConfig.publicClient,
|
|
1192
|
+
environment: this.environment
|
|
1161
1193
|
});
|
|
1162
1194
|
const isDeployed = await isSafeDeployed(
|
|
1163
1195
|
safeAddress,
|
|
@@ -1257,7 +1289,8 @@ var ZyfaiSDK = class {
|
|
|
1257
1289
|
owner: walletClient,
|
|
1258
1290
|
safeOwnerAddress: userAddress,
|
|
1259
1291
|
chain: chainConfig.chain,
|
|
1260
|
-
publicClient: chainConfig.publicClient
|
|
1292
|
+
publicClient: chainConfig.publicClient,
|
|
1293
|
+
environment: this.environment
|
|
1261
1294
|
});
|
|
1262
1295
|
const response = await this.httpClient.get(
|
|
1263
1296
|
ENDPOINTS.DATA_POSITION(safeAddress)
|
|
@@ -1265,8 +1298,6 @@ var ZyfaiSDK = class {
|
|
|
1265
1298
|
return {
|
|
1266
1299
|
success: true,
|
|
1267
1300
|
userAddress,
|
|
1268
|
-
totalValueUsd: 0,
|
|
1269
|
-
// API doesn't return this yet
|
|
1270
1301
|
positions: response ? [response] : []
|
|
1271
1302
|
};
|
|
1272
1303
|
} catch (error) {
|
|
@@ -1338,10 +1369,18 @@ var ZyfaiSDK = class {
|
|
|
1338
1369
|
async getTVL() {
|
|
1339
1370
|
try {
|
|
1340
1371
|
const response = await this.httpClient.get(ENDPOINTS.DATA_TVL);
|
|
1372
|
+
const byChain = {};
|
|
1373
|
+
for (const key of Object.keys(response)) {
|
|
1374
|
+
const numKey = parseInt(key, 10);
|
|
1375
|
+
if (!isNaN(numKey) && typeof response[key] === "number") {
|
|
1376
|
+
byChain[numKey] = response[key];
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1341
1379
|
return {
|
|
1342
1380
|
success: true,
|
|
1343
|
-
totalTvl: response.totalTvl || response.tvl || 0,
|
|
1344
|
-
byChain
|
|
1381
|
+
totalTvl: response.total || response.totalTvl || response.tvl || 0,
|
|
1382
|
+
byChain,
|
|
1383
|
+
breakdown: response.breakdown
|
|
1345
1384
|
};
|
|
1346
1385
|
} catch (error) {
|
|
1347
1386
|
throw new Error(`Failed to get TVL: ${error.message}`);
|
|
@@ -1429,11 +1468,15 @@ var ZyfaiSDK = class {
|
|
|
1429
1468
|
const response = await this.httpClient.get(
|
|
1430
1469
|
ENDPOINTS.DATA_BY_EOA(eoaAddress)
|
|
1431
1470
|
);
|
|
1432
|
-
const
|
|
1471
|
+
const smartWallet = response.agent || response.smartWallet || response.smartWallets?.[0];
|
|
1472
|
+
const smartWallets = smartWallet ? [smartWallet] : [];
|
|
1473
|
+
const chains = response.chains || [];
|
|
1433
1474
|
return {
|
|
1434
1475
|
success: true,
|
|
1435
1476
|
eoa: eoaAddress,
|
|
1436
|
-
|
|
1477
|
+
smartWallet: smartWallet || null,
|
|
1478
|
+
smartWallets,
|
|
1479
|
+
chains
|
|
1437
1480
|
};
|
|
1438
1481
|
} catch (error) {
|
|
1439
1482
|
throw new Error(
|
package/dist/index.mjs
CHANGED
|
@@ -48,7 +48,7 @@ var DATA_ENDPOINTS = {
|
|
|
48
48
|
// Portfolio
|
|
49
49
|
DEBANK_PORTFOLIO_MULTICHAIN: (address) => `/debank/portfolio/multichain/${address}`,
|
|
50
50
|
// Opportunities
|
|
51
|
-
OPPORTUNITIES_SAFE: (chainId) => chainId ? `/opportunities/
|
|
51
|
+
OPPORTUNITIES_SAFE: (chainId) => chainId ? `/opportunities/safe?chainId=${chainId}` : "/opportunities/safe",
|
|
52
52
|
OPPORTUNITIES_DEGEN: (chainId) => chainId ? `/opportunities/degen-strategies?chainId=${chainId}` : "/opportunities/degen-strategies",
|
|
53
53
|
// APY History
|
|
54
54
|
DAILY_APY_HISTORY_WEIGHTED: (walletAddress, days) => `/daily-apy-history/weighted/${walletAddress}${days ? `?days=${days}` : ""}`,
|
|
@@ -61,9 +61,9 @@ var HttpClient = class {
|
|
|
61
61
|
/**
|
|
62
62
|
* Create HTTP client for both Execution API and Data API
|
|
63
63
|
*
|
|
64
|
-
* @param apiKey - API key for Execution API
|
|
64
|
+
* @param apiKey - API key for Execution API
|
|
65
65
|
* @param environment - 'staging' or 'production'
|
|
66
|
-
* @param dataApiKey - API key for Data API
|
|
66
|
+
* @param dataApiKey - API key for Data API - defaults to apiKey
|
|
67
67
|
*/
|
|
68
68
|
constructor(apiKey, environment = "production", dataApiKey) {
|
|
69
69
|
this.authToken = null;
|
|
@@ -77,8 +77,7 @@ var HttpClient = class {
|
|
|
77
77
|
baseURL: `${endpoint}${API_VERSION}`,
|
|
78
78
|
headers: {
|
|
79
79
|
"Content-Type": "application/json",
|
|
80
|
-
"X-API-Key": this.apiKey
|
|
81
|
-
Origin: this.origin
|
|
80
|
+
"X-API-Key": this.apiKey
|
|
82
81
|
},
|
|
83
82
|
timeout: 3e4
|
|
84
83
|
});
|
|
@@ -110,7 +109,6 @@ var HttpClient = class {
|
|
|
110
109
|
this.client.interceptors.request.use(
|
|
111
110
|
(config) => {
|
|
112
111
|
config.headers["X-API-Key"] = this.apiKey;
|
|
113
|
-
config.headers["Origin"] = this.origin;
|
|
114
112
|
if (this.authToken) {
|
|
115
113
|
config.headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
116
114
|
}
|
|
@@ -179,6 +177,9 @@ var HttpClient = class {
|
|
|
179
177
|
this.dataClient.interceptors.request.use(
|
|
180
178
|
(config) => {
|
|
181
179
|
config.headers["X-API-Key"] = this.dataApiKey;
|
|
180
|
+
if (this.authToken) {
|
|
181
|
+
config.headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
182
|
+
}
|
|
182
183
|
return config;
|
|
183
184
|
},
|
|
184
185
|
(error) => Promise.reject(error)
|
|
@@ -293,7 +294,8 @@ import { privateKeyToAccount } from "viem/accounts";
|
|
|
293
294
|
import {
|
|
294
295
|
createWalletClient,
|
|
295
296
|
custom,
|
|
296
|
-
http as http3
|
|
297
|
+
http as http3,
|
|
298
|
+
getAddress
|
|
297
299
|
} from "viem";
|
|
298
300
|
|
|
299
301
|
// src/config/chains.ts
|
|
@@ -376,43 +378,49 @@ import {
|
|
|
376
378
|
getSessionNonce
|
|
377
379
|
} from "@rhinestone/module-sdk";
|
|
378
380
|
import { createSmartAccountClient } from "permissionless";
|
|
379
|
-
import { getAccountNonce } from "permissionless/actions";
|
|
380
381
|
import { erc7579Actions } from "permissionless/actions/erc7579";
|
|
381
382
|
import { createPimlicoClient } from "permissionless/clients/pimlico";
|
|
382
383
|
import { toSafeSmartAccount } from "permissionless/accounts";
|
|
383
384
|
import {
|
|
384
385
|
http as http2,
|
|
385
386
|
fromHex,
|
|
386
|
-
pad,
|
|
387
387
|
toHex
|
|
388
388
|
} from "viem";
|
|
389
389
|
import {
|
|
390
|
-
entryPoint07Address
|
|
391
|
-
getUserOperationHash
|
|
390
|
+
entryPoint07Address
|
|
392
391
|
} from "viem/account-abstraction";
|
|
393
392
|
var SAFE_7579_ADDRESS = "0x7579EE8307284F293B1927136486880611F20002";
|
|
394
393
|
var ERC7579_LAUNCHPAD_ADDRESS = "0x7579011aB74c46090561ea277Ba79D510c6C00ff";
|
|
395
|
-
var
|
|
394
|
+
var ACCOUNT_SALTS = {
|
|
395
|
+
staging: "zyfai-staging",
|
|
396
|
+
production: "zyfai-production"
|
|
397
|
+
};
|
|
396
398
|
var getSafeAccount = async (config) => {
|
|
397
399
|
const {
|
|
398
400
|
owner,
|
|
399
401
|
safeOwnerAddress,
|
|
400
402
|
publicClient,
|
|
401
|
-
|
|
403
|
+
environment = "production"
|
|
402
404
|
} = config;
|
|
405
|
+
const effectiveSalt = ACCOUNT_SALTS[environment];
|
|
403
406
|
if (!owner || !owner.account) {
|
|
404
407
|
throw new Error("Wallet not connected. Please connect your wallet first.");
|
|
405
408
|
}
|
|
406
|
-
const
|
|
409
|
+
const signerAddress = owner.account.address;
|
|
410
|
+
if (safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase()) {
|
|
411
|
+
throw new Error(
|
|
412
|
+
`Connected wallet address (${signerAddress}) must match the Safe owner address (${safeOwnerAddress}). Please connect with the correct wallet.`
|
|
413
|
+
);
|
|
414
|
+
}
|
|
407
415
|
const ownableValidator = getOwnableValidator({
|
|
408
|
-
owners: [
|
|
416
|
+
owners: [signerAddress],
|
|
409
417
|
threshold: 1
|
|
410
418
|
});
|
|
411
|
-
const saltHex = fromHex(toHex(
|
|
419
|
+
const saltHex = fromHex(toHex(effectiveSalt), "bigint");
|
|
412
420
|
const safeAccount = await toSafeSmartAccount({
|
|
413
421
|
client: publicClient,
|
|
414
422
|
owners: [owner.account],
|
|
415
|
-
//
|
|
423
|
+
// Pass the account object with address and signMessage capability
|
|
416
424
|
version: "1.4.1",
|
|
417
425
|
entryPoint: {
|
|
418
426
|
address: entryPoint07Address,
|
|
@@ -545,8 +553,8 @@ var deploySafeAccount = async (config) => {
|
|
|
545
553
|
);
|
|
546
554
|
}
|
|
547
555
|
};
|
|
548
|
-
var signSessionKey = async (config, sessions) => {
|
|
549
|
-
const { owner, publicClient
|
|
556
|
+
var signSessionKey = async (config, sessions, allPublicClients) => {
|
|
557
|
+
const { owner, publicClient } = config;
|
|
550
558
|
if (!owner || !owner.account) {
|
|
551
559
|
throw new Error("Wallet not connected. Please connect your wallet first.");
|
|
552
560
|
}
|
|
@@ -555,21 +563,24 @@ var signSessionKey = async (config, sessions) => {
|
|
|
555
563
|
address: safeAccount.address,
|
|
556
564
|
type: "safe"
|
|
557
565
|
});
|
|
566
|
+
const clients = allPublicClients || [publicClient];
|
|
558
567
|
const sessionNonces = await Promise.all(
|
|
559
|
-
sessions.map(
|
|
560
|
-
(session)
|
|
561
|
-
|
|
568
|
+
sessions.map((session) => {
|
|
569
|
+
const sessionChainId = Number(session.chainId);
|
|
570
|
+
const client = clients.find((c) => c.chain?.id === sessionChainId) || publicClient;
|
|
571
|
+
return getSessionNonce({
|
|
572
|
+
client,
|
|
562
573
|
account,
|
|
563
574
|
permissionId: getPermissionId({
|
|
564
575
|
session
|
|
565
576
|
})
|
|
566
|
-
})
|
|
567
|
-
)
|
|
577
|
+
});
|
|
578
|
+
})
|
|
568
579
|
);
|
|
569
580
|
const sessionDetails = await getEnableSessionDetails({
|
|
570
581
|
sessions,
|
|
571
582
|
account,
|
|
572
|
-
clients
|
|
583
|
+
clients,
|
|
573
584
|
permitGenericPolicy: true,
|
|
574
585
|
sessionNonces
|
|
575
586
|
});
|
|
@@ -588,13 +599,14 @@ var signSessionKey = async (config, sessions) => {
|
|
|
588
599
|
// src/core/ZyfaiSDK.ts
|
|
589
600
|
import { SiweMessage } from "siwe";
|
|
590
601
|
var ZyfaiSDK = class {
|
|
591
|
-
// TODO: The
|
|
602
|
+
// TODO: The environment should be removed. Having the same key for staging and production is not ideal, but for now it's fine.
|
|
592
603
|
constructor(config) {
|
|
593
604
|
this.signer = null;
|
|
594
605
|
this.walletClient = null;
|
|
595
606
|
this.isAuthenticated = false;
|
|
596
|
-
// TODO: Check with Utkir for how long the authentication token is valid for.
|
|
597
607
|
this.authenticatedUserId = null;
|
|
608
|
+
// Stored from login response
|
|
609
|
+
this.hasActiveSessionKey = false;
|
|
598
610
|
const sdkConfig = typeof config === "string" ? { apiKey: config } : config;
|
|
599
611
|
const { apiKey, dataApiKey, environment, bundlerApiKey } = sdkConfig;
|
|
600
612
|
if (!apiKey) {
|
|
@@ -617,11 +629,19 @@ var ZyfaiSDK = class {
|
|
|
617
629
|
return;
|
|
618
630
|
}
|
|
619
631
|
const walletClient = this.getWalletClient();
|
|
620
|
-
const userAddress = walletClient.account.address;
|
|
632
|
+
const userAddress = getAddress(walletClient.account.address);
|
|
621
633
|
const chainId = walletClient.chain?.id || 8453;
|
|
622
634
|
const challengeResponse = await this.httpClient.post(ENDPOINTS.AUTH_CHALLENGE, {});
|
|
623
|
-
|
|
624
|
-
|
|
635
|
+
let uri;
|
|
636
|
+
let domain;
|
|
637
|
+
const globalWindow = typeof globalThis !== "undefined" ? globalThis.window : void 0;
|
|
638
|
+
if (globalWindow?.location?.origin) {
|
|
639
|
+
uri = globalWindow.location.origin;
|
|
640
|
+
domain = globalWindow.location.host;
|
|
641
|
+
} else {
|
|
642
|
+
uri = API_ENDPOINTS[this.environment];
|
|
643
|
+
domain = API_ENDPOINTS[this.environment].split("//")[1];
|
|
644
|
+
}
|
|
625
645
|
const messageObj = new SiweMessage({
|
|
626
646
|
address: userAddress,
|
|
627
647
|
chainId,
|
|
@@ -642,11 +662,6 @@ var ZyfaiSDK = class {
|
|
|
642
662
|
{
|
|
643
663
|
message: messageObj,
|
|
644
664
|
signature
|
|
645
|
-
},
|
|
646
|
-
{
|
|
647
|
-
headers: {
|
|
648
|
-
Origin: uri
|
|
649
|
-
}
|
|
650
665
|
}
|
|
651
666
|
);
|
|
652
667
|
const authToken = loginResponse.accessToken || loginResponse.token;
|
|
@@ -655,6 +670,7 @@ var ZyfaiSDK = class {
|
|
|
655
670
|
}
|
|
656
671
|
this.httpClient.setAuthToken(authToken);
|
|
657
672
|
this.authenticatedUserId = loginResponse.userId || null;
|
|
673
|
+
this.hasActiveSessionKey = loginResponse.hasActiveSessionKey || false;
|
|
658
674
|
this.isAuthenticated = true;
|
|
659
675
|
} catch (error) {
|
|
660
676
|
throw new Error(
|
|
@@ -804,7 +820,8 @@ var ZyfaiSDK = class {
|
|
|
804
820
|
owner: walletClient,
|
|
805
821
|
safeOwnerAddress: userAddress,
|
|
806
822
|
chain: chainConfig.chain,
|
|
807
|
-
publicClient: chainConfig.publicClient
|
|
823
|
+
publicClient: chainConfig.publicClient,
|
|
824
|
+
environment: this.environment
|
|
808
825
|
});
|
|
809
826
|
const isDeployed = await isSafeDeployed(
|
|
810
827
|
safeAddress,
|
|
@@ -852,7 +869,8 @@ var ZyfaiSDK = class {
|
|
|
852
869
|
safeOwnerAddress: userAddress,
|
|
853
870
|
chain: chainConfig.chain,
|
|
854
871
|
publicClient: chainConfig.publicClient,
|
|
855
|
-
bundlerUrl
|
|
872
|
+
bundlerUrl,
|
|
873
|
+
environment: this.environment
|
|
856
874
|
});
|
|
857
875
|
try {
|
|
858
876
|
await this.updateUserProfile({
|
|
@@ -899,14 +917,14 @@ var ZyfaiSDK = class {
|
|
|
899
917
|
"User ID not available. Please ensure authentication completed successfully."
|
|
900
918
|
);
|
|
901
919
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
}
|
|
920
|
+
if (this.hasActiveSessionKey) {
|
|
921
|
+
return {
|
|
922
|
+
success: true,
|
|
923
|
+
userId: this.authenticatedUserId,
|
|
924
|
+
message: "Session key already exists and is active",
|
|
925
|
+
alreadyActive: true
|
|
926
|
+
};
|
|
927
|
+
}
|
|
910
928
|
const sessionConfig = await this.httpClient.get(
|
|
911
929
|
ENDPOINTS.SESSION_KEYS_CONFIG
|
|
912
930
|
);
|
|
@@ -922,10 +940,14 @@ var ZyfaiSDK = class {
|
|
|
922
940
|
chainId,
|
|
923
941
|
sessions
|
|
924
942
|
);
|
|
943
|
+
if (!signatureResult.signature) {
|
|
944
|
+
throw new Error("Failed to obtain session key signature");
|
|
945
|
+
}
|
|
925
946
|
const activation = await this.activateSessionKey(
|
|
926
947
|
signatureResult.signature,
|
|
927
948
|
signatureResult.sessionNonces
|
|
928
949
|
);
|
|
950
|
+
this.hasActiveSessionKey = true;
|
|
929
951
|
return {
|
|
930
952
|
...signatureResult,
|
|
931
953
|
userId: this.authenticatedUserId,
|
|
@@ -963,20 +985,27 @@ var ZyfaiSDK = class {
|
|
|
963
985
|
`Invalid account type for ${userAddress}. Must be an EOA.`
|
|
964
986
|
);
|
|
965
987
|
}
|
|
988
|
+
const sessionChainIds = [
|
|
989
|
+
...new Set(sessions.map((s) => Number(s.chainId)))
|
|
990
|
+
];
|
|
991
|
+
const allPublicClients = sessionChainIds.filter(isSupportedChain).map((id) => getChainConfig(id).publicClient);
|
|
966
992
|
const { signature, sessionNonces } = await signSessionKey(
|
|
967
993
|
{
|
|
968
994
|
owner: walletClient,
|
|
969
995
|
safeOwnerAddress: userAddress,
|
|
970
996
|
chain: chainConfig.chain,
|
|
971
|
-
publicClient: chainConfig.publicClient
|
|
997
|
+
publicClient: chainConfig.publicClient,
|
|
998
|
+
environment: this.environment
|
|
972
999
|
},
|
|
973
|
-
sessions
|
|
1000
|
+
sessions,
|
|
1001
|
+
allPublicClients
|
|
974
1002
|
);
|
|
975
1003
|
const safeAddress = await getDeterministicSafeAddress({
|
|
976
1004
|
owner: walletClient,
|
|
977
1005
|
safeOwnerAddress: userAddress,
|
|
978
1006
|
chain: chainConfig.chain,
|
|
979
|
-
publicClient: chainConfig.publicClient
|
|
1007
|
+
publicClient: chainConfig.publicClient,
|
|
1008
|
+
environment: this.environment
|
|
980
1009
|
});
|
|
981
1010
|
return {
|
|
982
1011
|
success: true,
|
|
@@ -1062,7 +1091,8 @@ var ZyfaiSDK = class {
|
|
|
1062
1091
|
owner: walletClient,
|
|
1063
1092
|
safeOwnerAddress: userAddress,
|
|
1064
1093
|
chain: chainConfig.chain,
|
|
1065
|
-
publicClient: chainConfig.publicClient
|
|
1094
|
+
publicClient: chainConfig.publicClient,
|
|
1095
|
+
environment: this.environment
|
|
1066
1096
|
});
|
|
1067
1097
|
const isDeployed = await isSafeDeployed(
|
|
1068
1098
|
safeAddress,
|
|
@@ -1137,7 +1167,8 @@ var ZyfaiSDK = class {
|
|
|
1137
1167
|
owner: walletClient,
|
|
1138
1168
|
safeOwnerAddress: userAddress,
|
|
1139
1169
|
chain: chainConfig.chain,
|
|
1140
|
-
publicClient: chainConfig.publicClient
|
|
1170
|
+
publicClient: chainConfig.publicClient,
|
|
1171
|
+
environment: this.environment
|
|
1141
1172
|
});
|
|
1142
1173
|
const isDeployed = await isSafeDeployed(
|
|
1143
1174
|
safeAddress,
|
|
@@ -1237,7 +1268,8 @@ var ZyfaiSDK = class {
|
|
|
1237
1268
|
owner: walletClient,
|
|
1238
1269
|
safeOwnerAddress: userAddress,
|
|
1239
1270
|
chain: chainConfig.chain,
|
|
1240
|
-
publicClient: chainConfig.publicClient
|
|
1271
|
+
publicClient: chainConfig.publicClient,
|
|
1272
|
+
environment: this.environment
|
|
1241
1273
|
});
|
|
1242
1274
|
const response = await this.httpClient.get(
|
|
1243
1275
|
ENDPOINTS.DATA_POSITION(safeAddress)
|
|
@@ -1245,8 +1277,6 @@ var ZyfaiSDK = class {
|
|
|
1245
1277
|
return {
|
|
1246
1278
|
success: true,
|
|
1247
1279
|
userAddress,
|
|
1248
|
-
totalValueUsd: 0,
|
|
1249
|
-
// API doesn't return this yet
|
|
1250
1280
|
positions: response ? [response] : []
|
|
1251
1281
|
};
|
|
1252
1282
|
} catch (error) {
|
|
@@ -1318,10 +1348,18 @@ var ZyfaiSDK = class {
|
|
|
1318
1348
|
async getTVL() {
|
|
1319
1349
|
try {
|
|
1320
1350
|
const response = await this.httpClient.get(ENDPOINTS.DATA_TVL);
|
|
1351
|
+
const byChain = {};
|
|
1352
|
+
for (const key of Object.keys(response)) {
|
|
1353
|
+
const numKey = parseInt(key, 10);
|
|
1354
|
+
if (!isNaN(numKey) && typeof response[key] === "number") {
|
|
1355
|
+
byChain[numKey] = response[key];
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1321
1358
|
return {
|
|
1322
1359
|
success: true,
|
|
1323
|
-
totalTvl: response.totalTvl || response.tvl || 0,
|
|
1324
|
-
byChain
|
|
1360
|
+
totalTvl: response.total || response.totalTvl || response.tvl || 0,
|
|
1361
|
+
byChain,
|
|
1362
|
+
breakdown: response.breakdown
|
|
1325
1363
|
};
|
|
1326
1364
|
} catch (error) {
|
|
1327
1365
|
throw new Error(`Failed to get TVL: ${error.message}`);
|
|
@@ -1409,11 +1447,15 @@ var ZyfaiSDK = class {
|
|
|
1409
1447
|
const response = await this.httpClient.get(
|
|
1410
1448
|
ENDPOINTS.DATA_BY_EOA(eoaAddress)
|
|
1411
1449
|
);
|
|
1412
|
-
const
|
|
1450
|
+
const smartWallet = response.agent || response.smartWallet || response.smartWallets?.[0];
|
|
1451
|
+
const smartWallets = smartWallet ? [smartWallet] : [];
|
|
1452
|
+
const chains = response.chains || [];
|
|
1413
1453
|
return {
|
|
1414
1454
|
success: true,
|
|
1415
1455
|
eoa: eoaAddress,
|
|
1416
|
-
|
|
1456
|
+
smartWallet: smartWallet || null,
|
|
1457
|
+
smartWallets,
|
|
1458
|
+
chains
|
|
1417
1459
|
};
|
|
1418
1460
|
} catch (error) {
|
|
1419
1461
|
throw new Error(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zyfai/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
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",
|