@zyfai/sdk 0.1.7 → 0.1.9

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
@@ -85,6 +85,7 @@ await sdk.deploySafe(userAddress, 42161);
85
85
  ```
86
86
 
87
87
  **Note:**
88
+
88
89
  - When using a wallet provider, the SDK automatically detects the chain from the provider. You can optionally specify `chainId` to override.
89
90
  - The SDK automatically performs SIWE authentication when connecting, so you don't need to call any additional authentication methods.
90
91
 
@@ -99,6 +100,7 @@ console.log("Account disconnected and authentication cleared");
99
100
  ```
100
101
 
101
102
  This method:
103
+
102
104
  - Clears the wallet connection
103
105
  - Resets authentication state
104
106
  - Clears the JWT token
@@ -124,7 +126,7 @@ const result = await sdk.deploySafe(userAddress, 42161);
124
126
  if (result.success) {
125
127
  console.log("Safe Address:", result.safeAddress);
126
128
  console.log("Status:", result.status); // 'deployed' | 'failed'
127
-
129
+
128
130
  if (result.alreadyDeployed) {
129
131
  console.log("Safe was already deployed - no action needed");
130
132
  } else {
@@ -195,6 +197,7 @@ Connect account for signing transactions and authenticate via SIWE. Accepts eith
195
197
  **Returns:** Connected wallet address
196
198
 
197
199
  **Automatic Actions:**
200
+
198
201
  - Connects the wallet
199
202
  - Authenticates via SIWE (Sign-In with Ethereum)
200
203
  - Stores JWT token for authenticated endpoints
@@ -217,6 +220,7 @@ Disconnect account and clear all authentication state.
217
220
  **Returns:** Promise that resolves when disconnection is complete
218
221
 
219
222
  **Actions:**
223
+
220
224
  - Clears wallet connection
221
225
  - Resets authentication state
222
226
  - Clears JWT token
@@ -267,6 +271,25 @@ Deploy a Safe smart wallet for a user.
267
271
  }
268
272
  ```
269
273
 
274
+ ##### `addWalletToSdk(walletAddress: string): Promise<AddWalletToSdkResponse>`
275
+
276
+ Add a wallet address to the SDK API key's allowedWallets list. This endpoint requires SDK API key authentication (API key starting with "zyfai\_").
277
+
278
+ **Parameters:**
279
+
280
+ - `walletAddress`: Wallet address to add to the allowed list
281
+
282
+ **Returns:**
283
+
284
+ ```typescript
285
+ {
286
+ success: boolean;
287
+ message: string; // Status message
288
+ }
289
+ ```
290
+
291
+ **Note**: This method is only available when using an SDK API key (starts with "zyfai\_"). Regular API keys cannot use this endpoint.
292
+
270
293
  ### 3. Session Keys
271
294
 
272
295
  Session keys enable delegated transaction execution without exposing the main private key.
@@ -354,6 +377,7 @@ if (result.success) {
354
377
  ```
355
378
 
356
379
  **Important Notes:**
380
+
357
381
  - Amount must be in least decimal units. For USDC (6 decimals): 1 USDC = 1000000
358
382
  - The SDK authenticates via SIWE before calling the withdrawal endpoints
359
383
  - Withdrawals are processed asynchronously - the `txHash` may not be immediately available
@@ -519,7 +543,20 @@ console.log("Tier:", frequency.tier);
519
543
  console.log("Max rebalances/day:", frequency.frequency);
520
544
  ```
521
545
 
522
- ### 12. Portfolio (Premium)
546
+ ### 12. SDK API Key Management
547
+
548
+ #### Add Wallet to SDK API Key
549
+
550
+ Add a wallet address to the SDK API key's allowedWallets list. This endpoint requires SDK API key authentication (API key starting with "zyfai\_").
551
+
552
+ ```typescript
553
+ const result = await sdk.addWalletToSdk("0x1234...");
554
+ console.log(result.message); // "Wallet successfully added to allowed list"
555
+ ```
556
+
557
+ **Note**: This method is only available when using an SDK API key (starts with "zyfai\_"). Regular API keys cannot use this endpoint.
558
+
559
+ ### 13. Portfolio (Premium)
523
560
 
524
561
  #### Get Debank Portfolio (Multi-chain)
525
562
 
@@ -781,10 +818,12 @@ Check that the chain ID is in the supported chains list: Arbitrum (42161), Base
781
818
  ### SIWE Authentication Issues in Browser
782
819
 
783
820
  The SDK automatically performs SIWE authentication when you call `connectAccount()`. The SDK automatically detects browser vs Node.js environments:
821
+
784
822
  - **Browser**: Uses `window.location.origin` for the SIWE message domain/uri to match the browser's automatic `Origin` header
785
823
  - **Node.js**: Uses the API endpoint URL
786
824
 
787
825
  If you encounter SIWE authentication failures in a browser, ensure:
826
+
788
827
  1. Your frontend origin is allowed by the API's CORS configuration
789
828
  2. You're using the correct `environment` setting (`staging` or `production`)
790
829
  3. The user approves the SIWE signature request in their wallet
@@ -796,6 +835,7 @@ If `createSessionKey` returns `{ alreadyActive: true }`, the user already has an
796
835
  ### Withdrawal Transaction Hash Not Available
797
836
 
798
837
  If `withdrawFunds` returns without a `txHash`, the withdrawal is being processed asynchronously by the backend. You can:
838
+
799
839
  1. Check the `message` field for status information
800
840
  2. Use `getHistory()` to track when the withdrawal transaction is processed
801
841
  3. The transaction will appear in the history once it's been executed
package/dist/index.d.mts CHANGED
@@ -352,6 +352,10 @@ interface WithdrawResponse {
352
352
  receiver: string;
353
353
  status: "pending" | "confirmed" | "failed";
354
354
  }
355
+ interface AddWalletToSdkResponse {
356
+ success: boolean;
357
+ message: string;
358
+ }
355
359
  interface PolicyData {
356
360
  policy: Address;
357
361
  initData: Hex;
@@ -437,6 +441,21 @@ declare class ZyfaiSDK {
437
441
  * ```
438
442
  */
439
443
  updateUserProfile(request: UpdateUserProfileRequest): Promise<UpdateUserProfileResponse>;
444
+ /**
445
+ * Initialize user after Safe deployment
446
+ * This method is automatically called after deploySafe to initialize user state
447
+ *
448
+ * @param smartWallet - Safe smart wallet address
449
+ * @param chainId - Target chain ID
450
+ * @returns Initialization response
451
+ *
452
+ * @example
453
+ * ```typescript
454
+ * await sdk.initializeUser("0x1396730...", 8453);
455
+ * ```
456
+ * @internal
457
+ */
458
+ private initializeUser;
440
459
  /**
441
460
  * Handle account changes from wallet provider
442
461
  * Resets authentication state when wallet is switched
@@ -515,6 +534,14 @@ declare class ZyfaiSDK {
515
534
  * @private
516
535
  */
517
536
  private signSessionKey;
537
+ /**
538
+ * Update user protocols with available protocols from the chain
539
+ * This method is automatically called before activating session key
540
+ *
541
+ * @param chainId - Target chain ID
542
+ * @internal
543
+ */
544
+ private updateUserProtocols;
518
545
  /**
519
546
  * Activate session key via ZyFAI API
520
547
  */
@@ -829,6 +856,21 @@ declare class ZyfaiSDK {
829
856
  * ```
830
857
  */
831
858
  getRebalanceFrequency(walletAddress: string): Promise<RebalanceFrequencyResponse>;
859
+ /**
860
+ * Add wallet to SDK API key allowedWallets list
861
+ * Adds a wallet address to the SDK API key's allowedWallets list.
862
+ * This endpoint requires SDK API key authentication (API key starting with "zyfai_").
863
+ *
864
+ * @param walletAddress - Wallet address to add to the allowed list
865
+ * @returns Response indicating success and status message
866
+ *
867
+ * @example
868
+ * ```typescript
869
+ * const result = await sdk.addWalletToSdk("0x1234...");
870
+ * console.log(result.message); // "Wallet successfully added to allowed list"
871
+ * ```
872
+ */
873
+ addWalletToSdk(walletAddress: string): Promise<AddWalletToSdkResponse>;
832
874
  }
833
875
 
834
- 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 SmartWalletByEOAResponse, type SmartWalletResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
876
+ export { type ActionData, type ActiveWallet, type ActiveWalletsResponse, type AddWalletToSdkResponse, 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 SmartWalletByEOAResponse, type SmartWalletResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
package/dist/index.d.ts CHANGED
@@ -352,6 +352,10 @@ interface WithdrawResponse {
352
352
  receiver: string;
353
353
  status: "pending" | "confirmed" | "failed";
354
354
  }
355
+ interface AddWalletToSdkResponse {
356
+ success: boolean;
357
+ message: string;
358
+ }
355
359
  interface PolicyData {
356
360
  policy: Address;
357
361
  initData: Hex;
@@ -437,6 +441,21 @@ declare class ZyfaiSDK {
437
441
  * ```
438
442
  */
439
443
  updateUserProfile(request: UpdateUserProfileRequest): Promise<UpdateUserProfileResponse>;
444
+ /**
445
+ * Initialize user after Safe deployment
446
+ * This method is automatically called after deploySafe to initialize user state
447
+ *
448
+ * @param smartWallet - Safe smart wallet address
449
+ * @param chainId - Target chain ID
450
+ * @returns Initialization response
451
+ *
452
+ * @example
453
+ * ```typescript
454
+ * await sdk.initializeUser("0x1396730...", 8453);
455
+ * ```
456
+ * @internal
457
+ */
458
+ private initializeUser;
440
459
  /**
441
460
  * Handle account changes from wallet provider
442
461
  * Resets authentication state when wallet is switched
@@ -515,6 +534,14 @@ declare class ZyfaiSDK {
515
534
  * @private
516
535
  */
517
536
  private signSessionKey;
537
+ /**
538
+ * Update user protocols with available protocols from the chain
539
+ * This method is automatically called before activating session key
540
+ *
541
+ * @param chainId - Target chain ID
542
+ * @internal
543
+ */
544
+ private updateUserProtocols;
518
545
  /**
519
546
  * Activate session key via ZyFAI API
520
547
  */
@@ -829,6 +856,21 @@ declare class ZyfaiSDK {
829
856
  * ```
830
857
  */
831
858
  getRebalanceFrequency(walletAddress: string): Promise<RebalanceFrequencyResponse>;
859
+ /**
860
+ * Add wallet to SDK API key allowedWallets list
861
+ * Adds a wallet address to the SDK API key's allowedWallets list.
862
+ * This endpoint requires SDK API key authentication (API key starting with "zyfai_").
863
+ *
864
+ * @param walletAddress - Wallet address to add to the allowed list
865
+ * @returns Response indicating success and status message
866
+ *
867
+ * @example
868
+ * ```typescript
869
+ * const result = await sdk.addWalletToSdk("0x1234...");
870
+ * console.log(result.message); // "Wallet successfully added to allowed list"
871
+ * ```
872
+ */
873
+ addWalletToSdk(walletAddress: string): Promise<AddWalletToSdkResponse>;
832
874
  }
833
875
 
834
- 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 SmartWalletByEOAResponse, type SmartWalletResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
876
+ export { type ActionData, type ActiveWallet, type ActiveWalletsResponse, type AddWalletToSdkResponse, 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 SmartWalletByEOAResponse, type SmartWalletResponse, type SupportedChainId, type TVLResponse, type UserDetails, type UserDetailsResponse, type VolumeResponse, type WithdrawResponse, ZyfaiSDK, getChainConfig, getSupportedChainIds, isSupportedChain };
package/dist/index.js CHANGED
@@ -57,8 +57,10 @@ var ENDPOINTS = {
57
57
  AUTH_CHALLENGE: "/auth/challenge",
58
58
  // User
59
59
  USER_ME: "/users/me",
60
+ USER_INITIALIZE: "/users/initialize",
60
61
  USER_WITHDRAW: "/users/withdraw",
61
62
  PARTIAL_WITHDRAW: "/users/partial-withdraw",
63
+ USER_ADD_WALLET_TO_SDK: "/users/add-wallet-to-sdk",
62
64
  // Session Keys
63
65
  SESSION_KEYS_CONFIG: "/session-keys/config",
64
66
  SESSION_KEYS_ADD: "/session-keys/add",
@@ -428,13 +430,23 @@ var getSafeAccount = async (config) => {
428
430
  throw new Error("Wallet not connected. Please connect your wallet first.");
429
431
  }
430
432
  const signerAddress = owner.account.address;
431
- if (safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase()) {
433
+ if (!signerAddress) {
434
+ throw new Error("Owner account address is required");
435
+ }
436
+ const effectiveOwnerAddress = safeOwnerAddress || signerAddress;
437
+ if (!effectiveOwnerAddress) {
438
+ throw new Error("Address is required");
439
+ }
440
+ const formattedEffectiveAddress = (0, import_viem3.getAddress)(effectiveOwnerAddress);
441
+ const isReadOnly = safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase();
442
+ if (!isReadOnly && safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase()) {
432
443
  throw new Error(
433
444
  `Connected wallet address (${signerAddress}) must match the Safe owner address (${safeOwnerAddress}). Please connect with the correct wallet.`
434
445
  );
435
446
  }
436
447
  const ownableValidator = (0, import_module_sdk.getOwnableValidator)({
437
- owners: [signerAddress],
448
+ owners: [formattedEffectiveAddress],
449
+ // Use formatted effective owner address for validator
438
450
  threshold: 1
439
451
  });
440
452
  const saltHex = (0, import_viem3.fromHex)((0, import_viem3.toHex)(effectiveSalt), "bigint");
@@ -733,6 +745,41 @@ var ZyfaiSDK = class {
733
745
  );
734
746
  }
735
747
  }
748
+ /**
749
+ * Initialize user after Safe deployment
750
+ * This method is automatically called after deploySafe to initialize user state
751
+ *
752
+ * @param smartWallet - Safe smart wallet address
753
+ * @param chainId - Target chain ID
754
+ * @returns Initialization response
755
+ *
756
+ * @example
757
+ * ```typescript
758
+ * await sdk.initializeUser("0x1396730...", 8453);
759
+ * ```
760
+ * @internal
761
+ */
762
+ async initializeUser(smartWallet, chainId) {
763
+ try {
764
+ await this.authenticateUser();
765
+ const response = await this.httpClient.post(
766
+ ENDPOINTS.USER_INITIALIZE,
767
+ {
768
+ smartWallet,
769
+ chainId
770
+ }
771
+ );
772
+ return {
773
+ success: true,
774
+ userId: response.userId || response.id,
775
+ smartWallet: response.smartWallet,
776
+ chainId: response.chainId,
777
+ message: response.message
778
+ };
779
+ } catch (error) {
780
+ throw new Error(`Failed to initialize user: ${error.message}`);
781
+ }
782
+ }
736
783
  /**
737
784
  * Handle account changes from wallet provider
738
785
  * Resets authentication state when wallet is switched
@@ -912,8 +959,22 @@ var ZyfaiSDK = class {
912
959
  if (!isSupportedChain(chainId)) {
913
960
  throw new Error(`Unsupported chain ID: ${chainId}`);
914
961
  }
915
- const walletClient = this.getWalletClient();
916
962
  const chainConfig = getChainConfig(chainId);
963
+ try {
964
+ const smartWalletInfo = await this.getSmartWalletByEOA(userAddress);
965
+ if (smartWalletInfo.smartWallet) {
966
+ const isDeployed2 = await isSafeDeployed(
967
+ smartWalletInfo.smartWallet,
968
+ chainConfig.publicClient
969
+ );
970
+ return {
971
+ address: smartWalletInfo.smartWallet,
972
+ isDeployed: isDeployed2
973
+ };
974
+ }
975
+ } catch {
976
+ }
977
+ const walletClient = this.getWalletClient(chainId);
917
978
  const safeAddress = await getDeterministicSafeAddress({
918
979
  owner: walletClient,
919
980
  safeOwnerAddress: userAddress,
@@ -1001,6 +1062,14 @@ var ZyfaiSDK = class {
1001
1062
  updateError.message
1002
1063
  );
1003
1064
  }
1065
+ try {
1066
+ await this.initializeUser(deploymentResult.safeAddress, chainId);
1067
+ } catch (initError) {
1068
+ console.warn(
1069
+ "Failed to initialize user after Safe deployment:",
1070
+ initError.message
1071
+ );
1072
+ }
1004
1073
  return {
1005
1074
  success: true,
1006
1075
  safeAddress: deploymentResult.safeAddress,
@@ -1061,6 +1130,7 @@ var ZyfaiSDK = class {
1061
1130
  if (!signatureResult.signature) {
1062
1131
  throw new Error("Failed to obtain session key signature");
1063
1132
  }
1133
+ await this.updateUserProtocols(chainId);
1064
1134
  const activation = await this.activateSessionKey(
1065
1135
  signatureResult.signature,
1066
1136
  signatureResult.sessionNonces
@@ -1136,6 +1206,30 @@ var ZyfaiSDK = class {
1136
1206
  );
1137
1207
  }
1138
1208
  }
1209
+ /**
1210
+ * Update user protocols with available protocols from the chain
1211
+ * This method is automatically called before activating session key
1212
+ *
1213
+ * @param chainId - Target chain ID
1214
+ * @internal
1215
+ */
1216
+ async updateUserProtocols(chainId) {
1217
+ try {
1218
+ const protocolsResponse = await this.getAvailableProtocols(chainId);
1219
+ if (!protocolsResponse.protocols || protocolsResponse.protocols.length === 0) {
1220
+ console.warn(`No protocols available for chain ${chainId}`);
1221
+ return;
1222
+ }
1223
+ const protocolIds = protocolsResponse.protocols.map((p) => p.id);
1224
+ await this.updateUserProfile({
1225
+ protocols: protocolIds
1226
+ });
1227
+ } catch (error) {
1228
+ console.warn(
1229
+ `Failed to update user protocols: ${error.message}`
1230
+ );
1231
+ }
1232
+ }
1139
1233
  /**
1140
1234
  * Activate session key via ZyFAI API
1141
1235
  */
@@ -1280,15 +1374,32 @@ var ZyfaiSDK = class {
1280
1374
  if (!isSupportedChain(chainId)) {
1281
1375
  throw new Error(`Unsupported chain ID: ${chainId}`);
1282
1376
  }
1283
- const walletClient = this.getWalletClient();
1284
1377
  const chainConfig = getChainConfig(chainId);
1285
- const safeAddress = await getDeterministicSafeAddress({
1286
- owner: walletClient,
1287
- safeOwnerAddress: userAddress,
1288
- chain: chainConfig.chain,
1289
- publicClient: chainConfig.publicClient,
1290
- environment: this.environment
1291
- });
1378
+ let safeAddress;
1379
+ try {
1380
+ const smartWalletInfo = await this.getSmartWalletByEOA(userAddress);
1381
+ if (smartWalletInfo.smartWallet) {
1382
+ safeAddress = smartWalletInfo.smartWallet;
1383
+ } else {
1384
+ const walletClient = this.getWalletClient();
1385
+ safeAddress = await getDeterministicSafeAddress({
1386
+ owner: walletClient,
1387
+ safeOwnerAddress: userAddress,
1388
+ chain: chainConfig.chain,
1389
+ publicClient: chainConfig.publicClient,
1390
+ environment: this.environment
1391
+ });
1392
+ }
1393
+ } catch {
1394
+ const walletClient = this.getWalletClient();
1395
+ safeAddress = await getDeterministicSafeAddress({
1396
+ owner: walletClient,
1397
+ safeOwnerAddress: userAddress,
1398
+ chain: chainConfig.chain,
1399
+ publicClient: chainConfig.publicClient,
1400
+ environment: this.environment
1401
+ });
1402
+ }
1292
1403
  const isDeployed = await isSafeDeployed(
1293
1404
  safeAddress,
1294
1405
  chainConfig.publicClient
@@ -1384,17 +1495,16 @@ var ZyfaiSDK = class {
1384
1495
  if (chainId && !isSupportedChain(chainId)) {
1385
1496
  throw new Error(`Unsupported chain ID: ${chainId}`);
1386
1497
  }
1387
- const walletClient = this.getWalletClient(chainId);
1388
- const chainConfig = getChainConfig(chainId ?? 8453);
1389
- const safeAddress = await getDeterministicSafeAddress({
1390
- owner: walletClient,
1391
- safeOwnerAddress: userAddress,
1392
- chain: chainConfig.chain,
1393
- publicClient: chainConfig.publicClient,
1394
- environment: this.environment
1395
- });
1498
+ const smartWalletInfo = await this.getSmartWalletByEOA(userAddress);
1499
+ if (!smartWalletInfo.smartWallet) {
1500
+ return {
1501
+ success: true,
1502
+ userAddress,
1503
+ positions: []
1504
+ };
1505
+ }
1396
1506
  const response = await this.httpClient.get(
1397
- ENDPOINTS.DATA_POSITION(safeAddress)
1507
+ ENDPOINTS.DATA_POSITION(smartWalletInfo.smartWallet)
1398
1508
  );
1399
1509
  return {
1400
1510
  success: true,
@@ -2022,6 +2132,49 @@ var ZyfaiSDK = class {
2022
2132
  );
2023
2133
  }
2024
2134
  }
2135
+ // ============================================================================
2136
+ // SDK API Key Management
2137
+ // ============================================================================
2138
+ /**
2139
+ * Add wallet to SDK API key allowedWallets list
2140
+ * Adds a wallet address to the SDK API key's allowedWallets list.
2141
+ * This endpoint requires SDK API key authentication (API key starting with "zyfai_").
2142
+ *
2143
+ * @param walletAddress - Wallet address to add to the allowed list
2144
+ * @returns Response indicating success and status message
2145
+ *
2146
+ * @example
2147
+ * ```typescript
2148
+ * const result = await sdk.addWalletToSdk("0x1234...");
2149
+ * console.log(result.message); // "Wallet successfully added to allowed list"
2150
+ * ```
2151
+ */
2152
+ async addWalletToSdk(walletAddress) {
2153
+ try {
2154
+ if (!walletAddress) {
2155
+ throw new Error("Wallet address is required");
2156
+ }
2157
+ try {
2158
+ (0, import_viem4.getAddress)(walletAddress);
2159
+ } catch {
2160
+ throw new Error("Invalid wallet address format");
2161
+ }
2162
+ const response = await this.httpClient.post(
2163
+ ENDPOINTS.USER_ADD_WALLET_TO_SDK,
2164
+ {
2165
+ walletAddress
2166
+ }
2167
+ );
2168
+ return {
2169
+ success: response.success ?? true,
2170
+ message: response.message || "Wallet added successfully"
2171
+ };
2172
+ } catch (error) {
2173
+ throw new Error(
2174
+ `Failed to add wallet to SDK: ${error.message}`
2175
+ );
2176
+ }
2177
+ }
2025
2178
  };
2026
2179
  // Annotate the CommonJS export names for ESM import in node:
2027
2180
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -18,8 +18,10 @@ var ENDPOINTS = {
18
18
  AUTH_CHALLENGE: "/auth/challenge",
19
19
  // User
20
20
  USER_ME: "/users/me",
21
+ USER_INITIALIZE: "/users/initialize",
21
22
  USER_WITHDRAW: "/users/withdraw",
22
23
  PARTIAL_WITHDRAW: "/users/partial-withdraw",
24
+ USER_ADD_WALLET_TO_SDK: "/users/add-wallet-to-sdk",
23
25
  // Session Keys
24
26
  SESSION_KEYS_CONFIG: "/session-keys/config",
25
27
  SESSION_KEYS_ADD: "/session-keys/add",
@@ -295,7 +297,7 @@ import {
295
297
  createWalletClient,
296
298
  custom,
297
299
  http as http3,
298
- getAddress
300
+ getAddress as getAddress2
299
301
  } from "viem";
300
302
 
301
303
  // src/config/chains.ts
@@ -383,6 +385,7 @@ import { createPimlicoClient } from "permissionless/clients/pimlico";
383
385
  import { toSafeSmartAccount } from "permissionless/accounts";
384
386
  import {
385
387
  http as http2,
388
+ getAddress,
386
389
  fromHex,
387
390
  toHex
388
391
  } from "viem";
@@ -407,13 +410,23 @@ var getSafeAccount = async (config) => {
407
410
  throw new Error("Wallet not connected. Please connect your wallet first.");
408
411
  }
409
412
  const signerAddress = owner.account.address;
410
- if (safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase()) {
413
+ if (!signerAddress) {
414
+ throw new Error("Owner account address is required");
415
+ }
416
+ const effectiveOwnerAddress = safeOwnerAddress || signerAddress;
417
+ if (!effectiveOwnerAddress) {
418
+ throw new Error("Address is required");
419
+ }
420
+ const formattedEffectiveAddress = getAddress(effectiveOwnerAddress);
421
+ const isReadOnly = safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase();
422
+ if (!isReadOnly && safeOwnerAddress && safeOwnerAddress.toLowerCase() !== signerAddress.toLowerCase()) {
411
423
  throw new Error(
412
424
  `Connected wallet address (${signerAddress}) must match the Safe owner address (${safeOwnerAddress}). Please connect with the correct wallet.`
413
425
  );
414
426
  }
415
427
  const ownableValidator = getOwnableValidator({
416
- owners: [signerAddress],
428
+ owners: [formattedEffectiveAddress],
429
+ // Use formatted effective owner address for validator
417
430
  threshold: 1
418
431
  });
419
432
  const saltHex = fromHex(toHex(effectiveSalt), "bigint");
@@ -630,7 +643,7 @@ var ZyfaiSDK = class {
630
643
  return;
631
644
  }
632
645
  const walletClient = this.getWalletClient();
633
- const userAddress = getAddress(walletClient.account.address);
646
+ const userAddress = getAddress2(walletClient.account.address);
634
647
  const chainId = walletClient.chain?.id || 8453;
635
648
  const challengeResponse = await this.httpClient.post(ENDPOINTS.AUTH_CHALLENGE, {});
636
649
  let uri;
@@ -712,6 +725,41 @@ var ZyfaiSDK = class {
712
725
  );
713
726
  }
714
727
  }
728
+ /**
729
+ * Initialize user after Safe deployment
730
+ * This method is automatically called after deploySafe to initialize user state
731
+ *
732
+ * @param smartWallet - Safe smart wallet address
733
+ * @param chainId - Target chain ID
734
+ * @returns Initialization response
735
+ *
736
+ * @example
737
+ * ```typescript
738
+ * await sdk.initializeUser("0x1396730...", 8453);
739
+ * ```
740
+ * @internal
741
+ */
742
+ async initializeUser(smartWallet, chainId) {
743
+ try {
744
+ await this.authenticateUser();
745
+ const response = await this.httpClient.post(
746
+ ENDPOINTS.USER_INITIALIZE,
747
+ {
748
+ smartWallet,
749
+ chainId
750
+ }
751
+ );
752
+ return {
753
+ success: true,
754
+ userId: response.userId || response.id,
755
+ smartWallet: response.smartWallet,
756
+ chainId: response.chainId,
757
+ message: response.message
758
+ };
759
+ } catch (error) {
760
+ throw new Error(`Failed to initialize user: ${error.message}`);
761
+ }
762
+ }
715
763
  /**
716
764
  * Handle account changes from wallet provider
717
765
  * Resets authentication state when wallet is switched
@@ -891,8 +939,22 @@ var ZyfaiSDK = class {
891
939
  if (!isSupportedChain(chainId)) {
892
940
  throw new Error(`Unsupported chain ID: ${chainId}`);
893
941
  }
894
- const walletClient = this.getWalletClient();
895
942
  const chainConfig = getChainConfig(chainId);
943
+ try {
944
+ const smartWalletInfo = await this.getSmartWalletByEOA(userAddress);
945
+ if (smartWalletInfo.smartWallet) {
946
+ const isDeployed2 = await isSafeDeployed(
947
+ smartWalletInfo.smartWallet,
948
+ chainConfig.publicClient
949
+ );
950
+ return {
951
+ address: smartWalletInfo.smartWallet,
952
+ isDeployed: isDeployed2
953
+ };
954
+ }
955
+ } catch {
956
+ }
957
+ const walletClient = this.getWalletClient(chainId);
896
958
  const safeAddress = await getDeterministicSafeAddress({
897
959
  owner: walletClient,
898
960
  safeOwnerAddress: userAddress,
@@ -980,6 +1042,14 @@ var ZyfaiSDK = class {
980
1042
  updateError.message
981
1043
  );
982
1044
  }
1045
+ try {
1046
+ await this.initializeUser(deploymentResult.safeAddress, chainId);
1047
+ } catch (initError) {
1048
+ console.warn(
1049
+ "Failed to initialize user after Safe deployment:",
1050
+ initError.message
1051
+ );
1052
+ }
983
1053
  return {
984
1054
  success: true,
985
1055
  safeAddress: deploymentResult.safeAddress,
@@ -1040,6 +1110,7 @@ var ZyfaiSDK = class {
1040
1110
  if (!signatureResult.signature) {
1041
1111
  throw new Error("Failed to obtain session key signature");
1042
1112
  }
1113
+ await this.updateUserProtocols(chainId);
1043
1114
  const activation = await this.activateSessionKey(
1044
1115
  signatureResult.signature,
1045
1116
  signatureResult.sessionNonces
@@ -1115,6 +1186,30 @@ var ZyfaiSDK = class {
1115
1186
  );
1116
1187
  }
1117
1188
  }
1189
+ /**
1190
+ * Update user protocols with available protocols from the chain
1191
+ * This method is automatically called before activating session key
1192
+ *
1193
+ * @param chainId - Target chain ID
1194
+ * @internal
1195
+ */
1196
+ async updateUserProtocols(chainId) {
1197
+ try {
1198
+ const protocolsResponse = await this.getAvailableProtocols(chainId);
1199
+ if (!protocolsResponse.protocols || protocolsResponse.protocols.length === 0) {
1200
+ console.warn(`No protocols available for chain ${chainId}`);
1201
+ return;
1202
+ }
1203
+ const protocolIds = protocolsResponse.protocols.map((p) => p.id);
1204
+ await this.updateUserProfile({
1205
+ protocols: protocolIds
1206
+ });
1207
+ } catch (error) {
1208
+ console.warn(
1209
+ `Failed to update user protocols: ${error.message}`
1210
+ );
1211
+ }
1212
+ }
1118
1213
  /**
1119
1214
  * Activate session key via ZyFAI API
1120
1215
  */
@@ -1259,15 +1354,32 @@ var ZyfaiSDK = class {
1259
1354
  if (!isSupportedChain(chainId)) {
1260
1355
  throw new Error(`Unsupported chain ID: ${chainId}`);
1261
1356
  }
1262
- const walletClient = this.getWalletClient();
1263
1357
  const chainConfig = getChainConfig(chainId);
1264
- const safeAddress = await getDeterministicSafeAddress({
1265
- owner: walletClient,
1266
- safeOwnerAddress: userAddress,
1267
- chain: chainConfig.chain,
1268
- publicClient: chainConfig.publicClient,
1269
- environment: this.environment
1270
- });
1358
+ let safeAddress;
1359
+ try {
1360
+ const smartWalletInfo = await this.getSmartWalletByEOA(userAddress);
1361
+ if (smartWalletInfo.smartWallet) {
1362
+ safeAddress = smartWalletInfo.smartWallet;
1363
+ } else {
1364
+ const walletClient = this.getWalletClient();
1365
+ safeAddress = await getDeterministicSafeAddress({
1366
+ owner: walletClient,
1367
+ safeOwnerAddress: userAddress,
1368
+ chain: chainConfig.chain,
1369
+ publicClient: chainConfig.publicClient,
1370
+ environment: this.environment
1371
+ });
1372
+ }
1373
+ } catch {
1374
+ const walletClient = this.getWalletClient();
1375
+ safeAddress = await getDeterministicSafeAddress({
1376
+ owner: walletClient,
1377
+ safeOwnerAddress: userAddress,
1378
+ chain: chainConfig.chain,
1379
+ publicClient: chainConfig.publicClient,
1380
+ environment: this.environment
1381
+ });
1382
+ }
1271
1383
  const isDeployed = await isSafeDeployed(
1272
1384
  safeAddress,
1273
1385
  chainConfig.publicClient
@@ -1363,17 +1475,16 @@ var ZyfaiSDK = class {
1363
1475
  if (chainId && !isSupportedChain(chainId)) {
1364
1476
  throw new Error(`Unsupported chain ID: ${chainId}`);
1365
1477
  }
1366
- const walletClient = this.getWalletClient(chainId);
1367
- const chainConfig = getChainConfig(chainId ?? 8453);
1368
- const safeAddress = await getDeterministicSafeAddress({
1369
- owner: walletClient,
1370
- safeOwnerAddress: userAddress,
1371
- chain: chainConfig.chain,
1372
- publicClient: chainConfig.publicClient,
1373
- environment: this.environment
1374
- });
1478
+ const smartWalletInfo = await this.getSmartWalletByEOA(userAddress);
1479
+ if (!smartWalletInfo.smartWallet) {
1480
+ return {
1481
+ success: true,
1482
+ userAddress,
1483
+ positions: []
1484
+ };
1485
+ }
1375
1486
  const response = await this.httpClient.get(
1376
- ENDPOINTS.DATA_POSITION(safeAddress)
1487
+ ENDPOINTS.DATA_POSITION(smartWalletInfo.smartWallet)
1377
1488
  );
1378
1489
  return {
1379
1490
  success: true,
@@ -2001,6 +2112,49 @@ var ZyfaiSDK = class {
2001
2112
  );
2002
2113
  }
2003
2114
  }
2115
+ // ============================================================================
2116
+ // SDK API Key Management
2117
+ // ============================================================================
2118
+ /**
2119
+ * Add wallet to SDK API key allowedWallets list
2120
+ * Adds a wallet address to the SDK API key's allowedWallets list.
2121
+ * This endpoint requires SDK API key authentication (API key starting with "zyfai_").
2122
+ *
2123
+ * @param walletAddress - Wallet address to add to the allowed list
2124
+ * @returns Response indicating success and status message
2125
+ *
2126
+ * @example
2127
+ * ```typescript
2128
+ * const result = await sdk.addWalletToSdk("0x1234...");
2129
+ * console.log(result.message); // "Wallet successfully added to allowed list"
2130
+ * ```
2131
+ */
2132
+ async addWalletToSdk(walletAddress) {
2133
+ try {
2134
+ if (!walletAddress) {
2135
+ throw new Error("Wallet address is required");
2136
+ }
2137
+ try {
2138
+ getAddress2(walletAddress);
2139
+ } catch {
2140
+ throw new Error("Invalid wallet address format");
2141
+ }
2142
+ const response = await this.httpClient.post(
2143
+ ENDPOINTS.USER_ADD_WALLET_TO_SDK,
2144
+ {
2145
+ walletAddress
2146
+ }
2147
+ );
2148
+ return {
2149
+ success: response.success ?? true,
2150
+ message: response.message || "Wallet added successfully"
2151
+ };
2152
+ } catch (error) {
2153
+ throw new Error(
2154
+ `Failed to add wallet to SDK: ${error.message}`
2155
+ );
2156
+ }
2157
+ }
2004
2158
  };
2005
2159
  export {
2006
2160
  ZyfaiSDK,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zyfai/sdk",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
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",