@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 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. Calculates the deterministic Safe address
233
- // 3. Resolves the userId via /users/by-smart-wallet
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
- console.log("Session created:", result.signature);
241
- console.log("Safe address:", result.sessionKeyAddress);
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
- - 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.
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 (Utkir's backend) */
10
+ /** API key for the Execution API */
11
11
  apiKey: string;
12
- /** API key for the Data API (Sunny's backend) - defaults to apiKey if not provided */
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
- sessionKeyAddress: Address;
56
- signature: Hex;
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
- id?: string;
90
- chain?: string;
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?: string;
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<string, number>;
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
- timestamp: string;
174
- type: string;
175
- amount: string;
176
- token?: string;
177
- txHash?: string;
205
+ action?: string;
206
+ date?: string;
207
+ strategy?: string;
208
+ positions?: HistoryPosition[];
178
209
  chainId?: number;
179
- protocol?: string;
180
- pool?: string;
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
- date: string;
204
- earnings: number;
205
- balance?: number;
206
- apy?: number;
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 (Utkir's backend) */
10
+ /** API key for the Execution API */
11
11
  apiKey: string;
12
- /** API key for the Data API (Sunny's backend) - defaults to apiKey if not provided */
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
- sessionKeyAddress: Address;
56
- signature: Hex;
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
- id?: string;
90
- chain?: string;
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?: string;
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<string, number>;
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
- timestamp: string;
174
- type: string;
175
- amount: string;
176
- token?: string;
177
- txHash?: string;
205
+ action?: string;
206
+ date?: string;
207
+ strategy?: string;
208
+ positions?: HistoryPosition[];
178
209
  chainId?: number;
179
- protocol?: string;
180
- pool?: string;
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
- date: string;
204
- earnings: number;
205
- balance?: number;
206
- apy?: number;
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/safes?chainId=${chainId}` : "/opportunities/safes",
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 (Utkir's backend)
103
+ * @param apiKey - API key for Execution API
104
104
  * @param environment - 'staging' or 'production'
105
- * @param dataApiKey - API key for Data API (Sunny's backend) - defaults to apiKey
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 DEFAULT_ACCOUNT_SALT = "zyfai-staging";
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
- accountSalt = DEFAULT_ACCOUNT_SALT
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 actualOwnerAddress = safeOwnerAddress || owner.account.address;
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: [actualOwnerAddress],
437
+ owners: [signerAddress],
429
438
  threshold: 1
430
439
  });
431
- const saltHex = (0, import_viem3.fromHex)((0, import_viem3.toHex)(accountSalt), "bigint");
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
- // Use connected wallet for signing
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, chain } = config;
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
- (session) => (0, import_module_sdk.getSessionNonce)({
581
- client: publicClient,
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: [publicClient],
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 encironment should be removed. Having the same key for staging and production is not ideal, but for now it's fine.
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
- const domain = API_ENDPOINTS[this.environment].split("//")[1];
644
- const uri = API_ENDPOINTS[this.environment];
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
- const walletClient = this.getWalletClient();
923
- const chainConfig = getChainConfig(chainId);
924
- const safeAddress = await getDeterministicSafeAddress({
925
- owner: walletClient,
926
- safeOwnerAddress: userAddress,
927
- chain: chainConfig.chain,
928
- publicClient: chainConfig.publicClient
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: response.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 smartWallets = Array.isArray(response) ? response : response.smartWallets || [response.smartWallet].filter(Boolean);
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
- smartWallets
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/safes?chainId=${chainId}` : "/opportunities/safes",
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 (Utkir's backend)
64
+ * @param apiKey - API key for Execution API
65
65
  * @param environment - 'staging' or 'production'
66
- * @param dataApiKey - API key for Data API (Sunny's backend) - defaults to apiKey
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 DEFAULT_ACCOUNT_SALT = "zyfai-staging";
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
- accountSalt = DEFAULT_ACCOUNT_SALT
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 actualOwnerAddress = safeOwnerAddress || owner.account.address;
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: [actualOwnerAddress],
416
+ owners: [signerAddress],
409
417
  threshold: 1
410
418
  });
411
- const saltHex = fromHex(toHex(accountSalt), "bigint");
419
+ const saltHex = fromHex(toHex(effectiveSalt), "bigint");
412
420
  const safeAccount = await toSafeSmartAccount({
413
421
  client: publicClient,
414
422
  owners: [owner.account],
415
- // Use connected wallet for signing
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, chain } = config;
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) => getSessionNonce({
561
- client: publicClient,
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: [publicClient],
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 encironment should be removed. Having the same key for staging and production is not ideal, but for now it's fine.
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
- const domain = API_ENDPOINTS[this.environment].split("//")[1];
624
- const uri = API_ENDPOINTS[this.environment];
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
- const walletClient = this.getWalletClient();
903
- const chainConfig = getChainConfig(chainId);
904
- const safeAddress = await getDeterministicSafeAddress({
905
- owner: walletClient,
906
- safeOwnerAddress: userAddress,
907
- chain: chainConfig.chain,
908
- publicClient: chainConfig.publicClient
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: response.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 smartWallets = Array.isArray(response) ? response : response.smartWallets || [response.smartWallet].filter(Boolean);
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
- smartWallets
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.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",