@zyfai/sdk 0.2.26 → 0.2.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -24,6 +24,7 @@ var ENDPOINTS = {
24
24
  PROTOCOLS: (chainId) => chainId ? `/protocols?chainId=${chainId}` : "/protocols",
25
25
  // Data (v1)
26
26
  DATA_POSITION: (walletAddress) => `/data/position?walletAddress=${walletAddress}`,
27
+ DATA_PORTFOLIO: (walletAddress) => `/data/wallet-portfolio?walletAddress=${walletAddress}`,
27
28
  DATA_HISTORY: (walletAddress, chainId) => `/data/history?walletAddress=${walletAddress}&chainId=${chainId}`,
28
29
  DATA_TVL: "/data/usd-tvl",
29
30
  DATA_VOLUME: (assetType) => `/data/volume?assetType=${assetType}`,
@@ -164,7 +165,7 @@ var HttpClient = class {
164
165
  case 429:
165
166
  throw new Error("Rate limit exceeded. Please try again later.");
166
167
  case 500:
167
- throw new Error("Internal server error. Please try again later.");
168
+ throw new Error(data?.message || data?.error || "Internal server error. Please try again later.");
168
169
  default:
169
170
  throw new Error(data.message || "An error occurred");
170
171
  }
@@ -348,6 +349,89 @@ var IDENTITY_REGISTRY_ABI = parseAbi([
348
349
  "function register(string tokenUri, (string key, bytes value)[] metadata) external returns (uint256 agentId)"
349
350
  ]);
350
351
  var IDENTITY_REGISTRY_ADDRESS = "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432";
352
+ var VAULT_ABI = [
353
+ {
354
+ name: "deposit",
355
+ type: "function",
356
+ stateMutability: "nonpayable",
357
+ inputs: [
358
+ { name: "assets", type: "uint256" },
359
+ { name: "receiver", type: "address" }
360
+ ],
361
+ outputs: [{ name: "shares", type: "uint256" }]
362
+ },
363
+ {
364
+ name: "requestRedeem",
365
+ type: "function",
366
+ stateMutability: "nonpayable",
367
+ inputs: [
368
+ { name: "shares", type: "uint256" },
369
+ { name: "controller", type: "address" },
370
+ { name: "owner", type: "address" }
371
+ ],
372
+ outputs: [{ name: "requestId", type: "uint256" }]
373
+ },
374
+ {
375
+ name: "claim",
376
+ type: "function",
377
+ stateMutability: "nonpayable",
378
+ inputs: [{ name: "withdrawKey", type: "bytes32" }],
379
+ outputs: [{ name: "assets", type: "uint256" }]
380
+ },
381
+ {
382
+ name: "getWithdrawKey",
383
+ type: "function",
384
+ stateMutability: "view",
385
+ inputs: [
386
+ { name: "user", type: "address" },
387
+ { name: "nonce", type: "uint256" }
388
+ ],
389
+ outputs: [{ name: "", type: "bytes32" }]
390
+ },
391
+ {
392
+ name: "nonces",
393
+ type: "function",
394
+ stateMutability: "view",
395
+ inputs: [{ name: "user", type: "address" }],
396
+ outputs: [{ name: "", type: "uint256" }]
397
+ },
398
+ {
399
+ name: "isClaimable",
400
+ type: "function",
401
+ stateMutability: "view",
402
+ inputs: [{ name: "withdrawKey", type: "bytes32" }],
403
+ outputs: [{ name: "", type: "bool" }]
404
+ },
405
+ {
406
+ name: "isClaimed",
407
+ type: "function",
408
+ stateMutability: "view",
409
+ inputs: [{ name: "withdrawKey", type: "bytes32" }],
410
+ outputs: [{ name: "", type: "bool" }]
411
+ },
412
+ {
413
+ name: "maxRequestRedeem",
414
+ type: "function",
415
+ stateMutability: "view",
416
+ inputs: [{ name: "owner", type: "address" }],
417
+ outputs: [{ name: "", type: "uint256" }]
418
+ },
419
+ {
420
+ name: "balanceOf",
421
+ type: "function",
422
+ stateMutability: "view",
423
+ inputs: [{ name: "account", type: "address" }],
424
+ outputs: [{ name: "", type: "uint256" }]
425
+ },
426
+ {
427
+ name: "symbol",
428
+ type: "function",
429
+ stateMutability: "view",
430
+ inputs: [],
431
+ outputs: [{ name: "", type: "string" }]
432
+ }
433
+ ];
434
+ var VAULT_ADDRESS = "0xD580071c47d4a667858B5FafAb85BC9C609beC5D";
351
435
 
352
436
  // src/core/ZyfaiSDK.ts
353
437
  import { privateKeyToAccount } from "viem/accounts";
@@ -747,6 +831,13 @@ function convertStrategyToPublic(obj) {
747
831
  return result;
748
832
  }
749
833
  }
834
+ function removeUnusedFields(obj) {
835
+ const result = { ...obj };
836
+ if ("hasStaleBalance" in result) {
837
+ delete result.hasStaleBalance;
838
+ }
839
+ return result;
840
+ }
750
841
  function convertAssetInternally(asset) {
751
842
  if (asset === "USDC") {
752
843
  return "usdc";
@@ -1378,6 +1469,7 @@ var _ZyfaiSDK = class _ZyfaiSDK {
1378
1469
  * @param userAddress - User's EOA address (the connected EOA, not the smart wallet address)
1379
1470
  * @param chainId - Target chain ID
1380
1471
  * @param strategy - Optional strategy selection: "conservative" (default) or "aggressive"
1472
+ * @param createSessionKey - If true, automatically creates a session key after deployment (default: false)
1381
1473
  * @returns Deployment response with Safe address and transaction hash
1382
1474
  *
1383
1475
  * @example
@@ -1387,9 +1479,12 @@ var _ZyfaiSDK = class _ZyfaiSDK {
1387
1479
  *
1388
1480
  * // Deploy with aggressive strategy
1389
1481
  * await sdk.deploySafe(userAddress, 8453, "aggressive");
1482
+ *
1483
+ * // Deploy and automatically create session key
1484
+ * await sdk.deploySafe(userAddress, 8453, "conservative", true);
1390
1485
  * ```
1391
1486
  */
1392
- async deploySafe(userAddress, chainId, strategy) {
1487
+ async deploySafe(userAddress, chainId, strategy, createSessionKey) {
1393
1488
  try {
1394
1489
  if (!userAddress) {
1395
1490
  throw new Error("User address is required");
@@ -1421,11 +1516,24 @@ var _ZyfaiSDK = class _ZyfaiSDK {
1421
1516
  }
1422
1517
  }
1423
1518
  if (alreadyDeployed) {
1519
+ let sessionKeyCreated2 = false;
1520
+ if (createSessionKey) {
1521
+ try {
1522
+ await this.createSessionKey(userAddress, chainId);
1523
+ sessionKeyCreated2 = true;
1524
+ } catch (sessionKeyError) {
1525
+ console.warn(
1526
+ "Failed to create session key:",
1527
+ sessionKeyError.message
1528
+ );
1529
+ }
1530
+ }
1424
1531
  return {
1425
1532
  success: true,
1426
1533
  safeAddress,
1427
1534
  txHash: "0x0",
1428
- status: "deployed"
1535
+ status: "deployed",
1536
+ sessionKeyCreated: sessionKeyCreated2
1429
1537
  };
1430
1538
  }
1431
1539
  const internalStrategy = strategy ? toInternalStrategy(strategy) : "safe_strategy";
@@ -1447,11 +1555,24 @@ var _ZyfaiSDK = class _ZyfaiSDK {
1447
1555
  initError.message
1448
1556
  );
1449
1557
  }
1558
+ let sessionKeyCreated = false;
1559
+ if (createSessionKey) {
1560
+ try {
1561
+ await this.createSessionKey(userAddress, chainId);
1562
+ sessionKeyCreated = true;
1563
+ } catch (sessionKeyError) {
1564
+ console.warn(
1565
+ "Failed to create session key after Safe deployment:",
1566
+ sessionKeyError.message
1567
+ );
1568
+ }
1569
+ }
1450
1570
  return {
1451
1571
  success: true,
1452
1572
  safeAddress: deploymentResult.safeAddress,
1453
1573
  txHash: deploymentResult.txHash || "0x0",
1454
- status: "deployed"
1574
+ status: "deployed",
1575
+ sessionKeyCreated
1455
1576
  };
1456
1577
  } catch (error) {
1457
1578
  console.error("Safe deployment failed:", error);
@@ -1979,6 +2100,49 @@ var _ZyfaiSDK = class _ZyfaiSDK {
1979
2100
  throw new Error(`Failed to get positions: ${error.message}`);
1980
2101
  }
1981
2102
  }
2103
+ /**
2104
+ * Get all active positions and portfolio for a user
2105
+ *
2106
+ * @param userAddress - User's EOA address
2107
+ * @param chainId - Optional: Filter by specific chain ID
2108
+ * @returns User's positions across all protocols
2109
+ *
2110
+ * @example
2111
+ * ```typescript
2112
+ * // Get all positions across all chains
2113
+ * const positions = await sdk.getPositions(userAddress);
2114
+ *
2115
+ * // Get positions on a specific chain
2116
+ * const basePositions = await sdk.getPositions(userAddress, 8453);
2117
+ * ```
2118
+ */
2119
+ async getPortfolio(userAddress) {
2120
+ try {
2121
+ if (!userAddress) {
2122
+ throw new Error("User address is required");
2123
+ }
2124
+ const smartWalletInfo = await this.getSmartWalletByEOA(userAddress);
2125
+ if (!smartWalletInfo.smartWallet) {
2126
+ return {
2127
+ success: true,
2128
+ userAddress,
2129
+ portfolio: {}
2130
+ };
2131
+ }
2132
+ console.log("Getting portfolio for", smartWalletInfo.smartWallet);
2133
+ const response = await this.httpClient.get(
2134
+ ENDPOINTS.DATA_PORTFOLIO(smartWalletInfo.smartWallet)
2135
+ );
2136
+ const convertedResponse = removeUnusedFields(response);
2137
+ return {
2138
+ success: true,
2139
+ userAddress,
2140
+ portfolio: convertedResponse
2141
+ };
2142
+ } catch (error) {
2143
+ throw new Error(`Failed to get positions: ${error.message}`);
2144
+ }
2145
+ }
1982
2146
  // ============================================================================
1983
2147
  // User Details Methods
1984
2148
  // ============================================================================
@@ -2297,9 +2461,6 @@ var _ZyfaiSDK = class _ZyfaiSDK {
2297
2461
  data: {
2298
2462
  walletAddress,
2299
2463
  totalEarningsByToken: response.total_earnings_by_token || {},
2300
- lifetimeEarningsByToken: response.lifetime_earnings_by_token || {},
2301
- currentEarningsByChain: response.current_earnings_by_chain || {},
2302
- unrealizedEarnings: response.unrealized_earnings || {},
2303
2464
  lastCheckTimestamp: response.last_check_timestamp,
2304
2465
  lastLogDate: response.last_log_date
2305
2466
  }
@@ -2338,9 +2499,6 @@ var _ZyfaiSDK = class _ZyfaiSDK {
2338
2499
  data: {
2339
2500
  walletAddress,
2340
2501
  totalEarningsByToken: data.total_earnings_by_token || {},
2341
- lifetimeEarningsByToken: data.lifetime_earnings_by_token || {},
2342
- currentEarningsByChain: data.current_earnings_by_chain || {},
2343
- unrealizedEarnings: data.unrealized_earnings || {},
2344
2502
  lastCheckTimestamp: data.last_check_timestamp,
2345
2503
  lastLogDate: data.last_log_date
2346
2504
  }
@@ -2373,10 +2531,17 @@ var _ZyfaiSDK = class _ZyfaiSDK {
2373
2531
  const response = await this.httpClient.dataGet(
2374
2532
  DATA_ENDPOINTS.DAILY_EARNINGS(walletAddress, startDate, endDate)
2375
2533
  );
2534
+ const filteredData = (response.data || []).map((entry) => ({
2535
+ wallet_address: entry.wallet_address,
2536
+ snapshot_date: entry.snapshot_date,
2537
+ total_earnings_by_token: entry.total_earnings_by_token,
2538
+ daily_total_delta_by_token: entry.daily_total_delta_by_token,
2539
+ created_at: entry.created_at
2540
+ }));
2376
2541
  return {
2377
2542
  success: true,
2378
2543
  walletAddress,
2379
- data: response.data || [],
2544
+ data: filteredData,
2380
2545
  count: response.count || 0,
2381
2546
  filters: {
2382
2547
  startDate: startDate || null,
@@ -2981,6 +3146,338 @@ var _ZyfaiSDK = class _ZyfaiSDK {
2981
3146
  );
2982
3147
  }
2983
3148
  }
3149
+ // ============================================
3150
+ // Vault Methods (Base only)
3151
+ // ============================================
3152
+ /**
3153
+ * Deposit assets into the Zyfai Vault
3154
+ * Currently only supports USDC on Base chain
3155
+ *
3156
+ * @param amount - Amount to deposit (in human readable format, e.g., "100" for 100 USDC)
3157
+ * @param asset - Asset to deposit (default: "USDC")
3158
+ * @returns Deposit transaction result
3159
+ *
3160
+ * @example
3161
+ * ```typescript
3162
+ * const result = await sdk.vaultDeposit("100", "USDC");
3163
+ * console.log("Deposited:", result.txHash);
3164
+ * ```
3165
+ */
3166
+ async vaultDeposit(amount, asset = "USDC", chainId = 8453) {
3167
+ if (!this.walletClient?.account) {
3168
+ throw new Error("Wallet not connected. Call connectAccount first.");
3169
+ }
3170
+ const userAddress = this.walletClient.account.address;
3171
+ const chainConfig = getChainConfig(chainId, this.rpcUrls);
3172
+ const tokenAddress = getDefaultTokenAddress(chainId, asset);
3173
+ const decimals = 6;
3174
+ const parsedAmount = BigInt(Math.floor(parseFloat(amount) * 10 ** decimals));
3175
+ try {
3176
+ const allowance = await chainConfig.publicClient.readContract({
3177
+ address: tokenAddress,
3178
+ abi: ERC20_ABI,
3179
+ functionName: "allowance",
3180
+ args: [userAddress, VAULT_ADDRESS]
3181
+ });
3182
+ if (allowance < parsedAmount) {
3183
+ const approveTx = await this.walletClient.writeContract({
3184
+ address: tokenAddress,
3185
+ abi: ERC20_ABI,
3186
+ functionName: "approve",
3187
+ args: [VAULT_ADDRESS, parsedAmount],
3188
+ chain: chainConfig.chain,
3189
+ account: this.walletClient.account
3190
+ });
3191
+ await chainConfig.publicClient.waitForTransactionReceipt({
3192
+ hash: approveTx
3193
+ });
3194
+ }
3195
+ const depositTx = await this.walletClient.writeContract({
3196
+ address: VAULT_ADDRESS,
3197
+ abi: VAULT_ABI,
3198
+ functionName: "deposit",
3199
+ args: [parsedAmount, userAddress],
3200
+ chain: chainConfig.chain,
3201
+ account: this.walletClient.account
3202
+ });
3203
+ const receipt = await chainConfig.publicClient.waitForTransactionReceipt({
3204
+ hash: depositTx
3205
+ });
3206
+ if (receipt.status !== "success") {
3207
+ throw new Error("Vault deposit transaction failed");
3208
+ }
3209
+ return {
3210
+ success: true,
3211
+ txHash: depositTx,
3212
+ amount,
3213
+ asset,
3214
+ vaultAddress: VAULT_ADDRESS
3215
+ };
3216
+ } catch (error) {
3217
+ throw new Error(`Vault deposit failed: ${error.message}`);
3218
+ }
3219
+ }
3220
+ /**
3221
+ * Request withdrawal from the Zyfai Vault
3222
+ * Withdrawals are async - use getVaultWithdrawStatus and vaultClaim after
3223
+ *
3224
+ * @param shares - Amount of shares to redeem (optional, defaults to all shares)
3225
+ * @returns Withdraw request result with withdrawKey
3226
+ *
3227
+ * @example
3228
+ * ```typescript
3229
+ * const result = await sdk.vaultWithdraw();
3230
+ * console.log("Withdraw key:", result.withdrawKey);
3231
+ * // Later, check status and claim
3232
+ * ```
3233
+ */
3234
+ async vaultWithdraw(shares, chainId = 8453) {
3235
+ if (!this.walletClient?.account) {
3236
+ throw new Error("Wallet not connected. Call connectAccount first.");
3237
+ }
3238
+ const userAddress = this.walletClient.account.address;
3239
+ const chainConfig = getChainConfig(chainId, this.rpcUrls);
3240
+ try {
3241
+ let sharesToRedeem;
3242
+ if (shares) {
3243
+ sharesToRedeem = BigInt(shares);
3244
+ } else {
3245
+ const maxShares = await chainConfig.publicClient.readContract({
3246
+ address: VAULT_ADDRESS,
3247
+ abi: VAULT_ABI,
3248
+ functionName: "maxRequestRedeem",
3249
+ args: [userAddress]
3250
+ });
3251
+ if (maxShares === 0n) {
3252
+ throw new Error("No shares available to redeem or withdrawals are paused");
3253
+ }
3254
+ sharesToRedeem = maxShares;
3255
+ }
3256
+ const redeemTx = await this.walletClient.writeContract({
3257
+ address: VAULT_ADDRESS,
3258
+ abi: VAULT_ABI,
3259
+ functionName: "requestRedeem",
3260
+ args: [sharesToRedeem, userAddress, userAddress],
3261
+ chain: chainConfig.chain,
3262
+ account: this.walletClient.account
3263
+ });
3264
+ await chainConfig.publicClient.waitForTransactionReceipt({
3265
+ hash: redeemTx
3266
+ });
3267
+ const nonceResult = await chainConfig.publicClient.readContract({
3268
+ address: VAULT_ADDRESS,
3269
+ abi: VAULT_ABI,
3270
+ functionName: "nonces",
3271
+ args: [userAddress]
3272
+ });
3273
+ const nonce = BigInt(nonceResult);
3274
+ if (nonce === 0n) {
3275
+ throw new Error("Nonce is 0 after requestRedeem - unexpected state");
3276
+ }
3277
+ const withdrawKey = await chainConfig.publicClient.readContract({
3278
+ address: VAULT_ADDRESS,
3279
+ abi: VAULT_ABI,
3280
+ functionName: "getWithdrawKey",
3281
+ args: [userAddress, nonce - 1n]
3282
+ });
3283
+ const isClaimable = await chainConfig.publicClient.readContract({
3284
+ address: VAULT_ADDRESS,
3285
+ abi: VAULT_ABI,
3286
+ functionName: "isClaimable",
3287
+ args: [withdrawKey]
3288
+ });
3289
+ return {
3290
+ success: true,
3291
+ txHash: redeemTx,
3292
+ withdrawKey,
3293
+ status: isClaimable ? "claimable" : "pending"
3294
+ };
3295
+ } catch (error) {
3296
+ throw new Error(`Vault withdraw request failed: ${error.message}`);
3297
+ }
3298
+ }
3299
+ /**
3300
+ * Get the status of a pending withdrawal
3301
+ *
3302
+ * @param withdrawKey - The withdraw key to check (optional, gets latest if not provided)
3303
+ * @returns Withdraw status
3304
+ *
3305
+ * @example
3306
+ * ```typescript
3307
+ * const status = await sdk.getVaultWithdrawStatus();
3308
+ * if (status.isClaimable) {
3309
+ * await sdk.vaultClaim(status.withdrawKey);
3310
+ * }
3311
+ * ```
3312
+ */
3313
+ async getVaultWithdrawStatus(withdrawKey, chainId = 8453) {
3314
+ if (!this.walletClient?.account) {
3315
+ throw new Error("Wallet not connected. Call connectAccount first.");
3316
+ }
3317
+ const userAddress = this.walletClient.account.address;
3318
+ const chainConfig = getChainConfig(chainId, this.rpcUrls);
3319
+ try {
3320
+ const nonceResult = await chainConfig.publicClient.readContract({
3321
+ address: VAULT_ADDRESS,
3322
+ abi: VAULT_ABI,
3323
+ functionName: "nonces",
3324
+ args: [userAddress]
3325
+ });
3326
+ const nonce = BigInt(nonceResult);
3327
+ if (nonce === 0n) {
3328
+ return {
3329
+ success: true,
3330
+ withdrawKey: null,
3331
+ isClaimable: false,
3332
+ isPending: false,
3333
+ nonce: 0n
3334
+ };
3335
+ }
3336
+ let keyToCheck = withdrawKey;
3337
+ if (!keyToCheck) {
3338
+ keyToCheck = await chainConfig.publicClient.readContract({
3339
+ address: VAULT_ADDRESS,
3340
+ abi: VAULT_ABI,
3341
+ functionName: "getWithdrawKey",
3342
+ args: [userAddress, nonce - 1n]
3343
+ });
3344
+ }
3345
+ const [isClaimable, isClaimed] = await Promise.all([
3346
+ chainConfig.publicClient.readContract({
3347
+ address: VAULT_ADDRESS,
3348
+ abi: VAULT_ABI,
3349
+ functionName: "isClaimable",
3350
+ args: [keyToCheck]
3351
+ }),
3352
+ chainConfig.publicClient.readContract({
3353
+ address: VAULT_ADDRESS,
3354
+ abi: VAULT_ABI,
3355
+ functionName: "isClaimed",
3356
+ args: [keyToCheck]
3357
+ })
3358
+ ]);
3359
+ if (isClaimed) {
3360
+ return {
3361
+ success: true,
3362
+ withdrawKey: null,
3363
+ isClaimable: false,
3364
+ isPending: false,
3365
+ nonce
3366
+ };
3367
+ }
3368
+ return {
3369
+ success: true,
3370
+ withdrawKey: keyToCheck,
3371
+ isClaimable,
3372
+ isPending: !isClaimable,
3373
+ nonce
3374
+ };
3375
+ } catch (error) {
3376
+ throw new Error(`Failed to get withdraw status: ${error.message}`);
3377
+ }
3378
+ }
3379
+ /**
3380
+ * Claim a completed withdrawal from the Zyfai Vault
3381
+ *
3382
+ * @param withdrawKey - The withdraw key to claim
3383
+ * @returns Claim transaction result
3384
+ *
3385
+ * @example
3386
+ * ```typescript
3387
+ * const status = await sdk.getVaultWithdrawStatus();
3388
+ * if (status.isClaimable) {
3389
+ * const claim = await sdk.vaultClaim(status.withdrawKey);
3390
+ * console.log("Claimed:", claim.txHash);
3391
+ * }
3392
+ * ```
3393
+ */
3394
+ async vaultClaim(withdrawKey, chainId = 8453) {
3395
+ if (!this.walletClient?.account) {
3396
+ throw new Error("Wallet not connected. Call connectAccount first.");
3397
+ }
3398
+ if (!withdrawKey) {
3399
+ throw new Error("Withdraw key is required");
3400
+ }
3401
+ const chainConfig = getChainConfig(chainId, this.rpcUrls);
3402
+ try {
3403
+ const isClaimable = await chainConfig.publicClient.readContract({
3404
+ address: VAULT_ADDRESS,
3405
+ abi: VAULT_ABI,
3406
+ functionName: "isClaimable",
3407
+ args: [withdrawKey]
3408
+ });
3409
+ if (!isClaimable) {
3410
+ const isClaimed = await chainConfig.publicClient.readContract({
3411
+ address: VAULT_ADDRESS,
3412
+ abi: VAULT_ABI,
3413
+ functionName: "isClaimed",
3414
+ args: [withdrawKey]
3415
+ });
3416
+ if (isClaimed) {
3417
+ throw new Error("This withdrawal has already been claimed");
3418
+ }
3419
+ throw new Error("Withdrawal is not yet claimable. Please wait for processing.");
3420
+ }
3421
+ const claimTx = await this.walletClient.writeContract({
3422
+ address: VAULT_ADDRESS,
3423
+ abi: VAULT_ABI,
3424
+ functionName: "claim",
3425
+ args: [withdrawKey],
3426
+ chain: chainConfig.chain,
3427
+ account: this.walletClient.account
3428
+ });
3429
+ const receipt = await chainConfig.publicClient.waitForTransactionReceipt({
3430
+ hash: claimTx
3431
+ });
3432
+ if (receipt.status !== "success") {
3433
+ throw new Error("Vault claim transaction failed");
3434
+ }
3435
+ return {
3436
+ success: true,
3437
+ txHash: claimTx,
3438
+ claimed: true
3439
+ };
3440
+ } catch (error) {
3441
+ throw new Error(`Vault claim failed: ${error.message}`);
3442
+ }
3443
+ }
3444
+ /**
3445
+ * Get vault shares info for the connected wallet
3446
+ *
3447
+ * @param userAddress - Optional user address (defaults to connected wallet)
3448
+ * @returns Vault shares balance and token symbol
3449
+ *
3450
+ * @example
3451
+ * ```typescript
3452
+ * const { shares, symbol } = await sdk.getVaultShares();
3453
+ * console.log(`Balance: ${shares} ${symbol}`);
3454
+ * ```
3455
+ */
3456
+ async getVaultShares(userAddress, chainId = 8453) {
3457
+ const address = userAddress || this.walletClient?.account?.address;
3458
+ if (!address) {
3459
+ throw new Error("User address required. Provide address or connect wallet first.");
3460
+ }
3461
+ const chainConfig = getChainConfig(chainId, this.rpcUrls);
3462
+ const [shareBalance, tokenSymbol] = await Promise.all([
3463
+ chainConfig.publicClient.readContract({
3464
+ address: VAULT_ADDRESS,
3465
+ abi: VAULT_ABI,
3466
+ functionName: "balanceOf",
3467
+ args: [address]
3468
+ }),
3469
+ chainConfig.publicClient.readContract({
3470
+ address: VAULT_ADDRESS,
3471
+ abi: VAULT_ABI,
3472
+ functionName: "symbol"
3473
+ })
3474
+ ]);
3475
+ return {
3476
+ success: true,
3477
+ shares: shareBalance,
3478
+ symbol: tokenSymbol
3479
+ };
3480
+ }
2984
3481
  };
2985
3482
  // ============================================================================
2986
3483
  // Agent Identity Registry
@@ -2990,9 +3487,177 @@ var _ZyfaiSDK = class _ZyfaiSDK {
2990
3487
  */
2991
3488
  _ZyfaiSDK.IDENTITY_REGISTRY_CHAIN_IDS = [8453, 42161];
2992
3489
  var ZyfaiSDK = _ZyfaiSDK;
3490
+
3491
+ // src/providers/bankr.ts
3492
+ function createBankrProvider(config) {
3493
+ const {
3494
+ apiKey,
3495
+ baseUrl = "https://api.bankr.bot",
3496
+ chainId = 8453
3497
+ } = config;
3498
+ if (!apiKey) {
3499
+ throw new Error("Bankr API key is required");
3500
+ }
3501
+ let cachedWalletAddress = null;
3502
+ const fetchBankr = async (endpoint, body) => {
3503
+ const response = await fetch(`${baseUrl}${endpoint}`, {
3504
+ method: body ? "POST" : "GET",
3505
+ headers: {
3506
+ "Content-Type": "application/json",
3507
+ "X-API-Key": apiKey
3508
+ },
3509
+ body: body ? JSON.stringify(body) : void 0
3510
+ });
3511
+ if (!response.ok) {
3512
+ const errorData = await response.json().catch(() => ({}));
3513
+ throw new Error(errorData.message || errorData.error || `Bankr API error: ${response.status}`);
3514
+ }
3515
+ return response.json();
3516
+ };
3517
+ const getWalletAddress = async () => {
3518
+ if (cachedWalletAddress) {
3519
+ return cachedWalletAddress;
3520
+ }
3521
+ const data = await fetchBankr("/agent/me");
3522
+ const evmWallet = data.wallets?.find((w) => w.chain === "evm");
3523
+ if (!evmWallet?.address) {
3524
+ throw new Error("No EVM wallet found in Bankr account");
3525
+ }
3526
+ cachedWalletAddress = evmWallet.address;
3527
+ return evmWallet.address;
3528
+ };
3529
+ const provider = {
3530
+ /**
3531
+ * EIP-1193 request method
3532
+ * Routes RPC calls to appropriate Bankr API endpoints
3533
+ */
3534
+ async request({ method, params }) {
3535
+ switch (method) {
3536
+ case "eth_requestAccounts":
3537
+ case "eth_accounts": {
3538
+ const address = await getWalletAddress();
3539
+ return [address];
3540
+ }
3541
+ case "eth_chainId": {
3542
+ return `0x${chainId.toString(16)}`;
3543
+ }
3544
+ case "net_version": {
3545
+ return chainId.toString();
3546
+ }
3547
+ case "personal_sign": {
3548
+ const [messageHex, address] = params || [];
3549
+ let message = messageHex;
3550
+ if (typeof messageHex === "string" && messageHex.startsWith("0x")) {
3551
+ const isRawHash = messageHex.length === 66;
3552
+ if (!isRawHash) {
3553
+ try {
3554
+ message = Buffer.from(messageHex.slice(2), "hex").toString("utf8");
3555
+ } catch {
3556
+ message = messageHex;
3557
+ }
3558
+ }
3559
+ }
3560
+ const data = await fetchBankr("/agent/sign", {
3561
+ signatureType: "personal_sign",
3562
+ message
3563
+ });
3564
+ if (!data.success || !data.signature) {
3565
+ throw new Error(data.error || "Bankr signing failed");
3566
+ }
3567
+ return data.signature;
3568
+ }
3569
+ case "eth_signTypedData":
3570
+ case "eth_signTypedData_v4": {
3571
+ const [address, typedDataString] = params || [];
3572
+ const typedData = typeof typedDataString === "string" ? JSON.parse(typedDataString) : typedDataString;
3573
+ const data = await fetchBankr("/agent/sign", {
3574
+ signatureType: "eth_signTypedData_v4",
3575
+ typedData
3576
+ });
3577
+ if (!data.success || !data.signature) {
3578
+ throw new Error(data.error || "Bankr typed data signing failed");
3579
+ }
3580
+ return data.signature;
3581
+ }
3582
+ case "eth_sendTransaction": {
3583
+ const [tx] = params || [];
3584
+ const signData = await fetchBankr("/agent/sign", {
3585
+ signatureType: "eth_signTransaction",
3586
+ transaction: {
3587
+ to: tx.to,
3588
+ chainId: tx.chainId ? parseInt(tx.chainId, 16) : chainId,
3589
+ value: tx.value || "0",
3590
+ data: tx.data || "0x",
3591
+ gas: tx.gas,
3592
+ gasLimit: tx.gasLimit,
3593
+ maxFeePerGas: tx.maxFeePerGas,
3594
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
3595
+ nonce: tx.nonce
3596
+ }
3597
+ });
3598
+ if (!signData.success || !signData.signature) {
3599
+ throw new Error(signData.error || "Bankr transaction signing failed");
3600
+ }
3601
+ const submitData = await fetchBankr("/agent/submit", {
3602
+ signedTransaction: signData.signature,
3603
+ chainId: tx.chainId ? parseInt(tx.chainId, 16) : chainId
3604
+ });
3605
+ if (!submitData.success) {
3606
+ throw new Error(submitData.error || "Bankr transaction submission failed");
3607
+ }
3608
+ return submitData.transactionHash || submitData.txHash;
3609
+ }
3610
+ case "eth_signTransaction": {
3611
+ const [tx] = params || [];
3612
+ const data = await fetchBankr("/agent/sign", {
3613
+ signatureType: "eth_signTransaction",
3614
+ transaction: {
3615
+ to: tx.to,
3616
+ chainId: tx.chainId ? parseInt(tx.chainId, 16) : chainId,
3617
+ value: tx.value || "0",
3618
+ data: tx.data || "0x",
3619
+ gas: tx.gas,
3620
+ gasLimit: tx.gasLimit,
3621
+ maxFeePerGas: tx.maxFeePerGas,
3622
+ maxPriorityFeePerGas: tx.maxPriorityFeePerGas,
3623
+ nonce: tx.nonce
3624
+ }
3625
+ });
3626
+ if (!data.success || !data.signature) {
3627
+ throw new Error(data.error || "Bankr transaction signing failed");
3628
+ }
3629
+ return data.signature;
3630
+ }
3631
+ case "wallet_switchEthereumChain": {
3632
+ return null;
3633
+ }
3634
+ default:
3635
+ throw new Error(`Unsupported method: ${method}. Bankr provider supports: eth_requestAccounts, eth_accounts, eth_chainId, personal_sign, eth_signTypedData_v4, eth_sendTransaction, eth_signTransaction`);
3636
+ }
3637
+ },
3638
+ /**
3639
+ * Event listener stub (required by EIP-1193)
3640
+ * Bankr API doesn't support real-time events
3641
+ */
3642
+ on: (event, callback) => {
3643
+ },
3644
+ /**
3645
+ * Remove event listener stub (required by EIP-1193)
3646
+ */
3647
+ removeListener: (event, callback) => {
3648
+ },
3649
+ /**
3650
+ * Check if this is a Bankr provider
3651
+ */
3652
+ isBankr: true
3653
+ };
3654
+ return provider;
3655
+ }
2993
3656
  export {
2994
3657
  DEFAULT_TOKEN_ADDRESSES,
3658
+ VAULT_ADDRESS,
2995
3659
  ZyfaiSDK,
3660
+ createBankrProvider,
2996
3661
  getChainConfig,
2997
3662
  getDefaultTokenAddress,
2998
3663
  getSupportedChainIds,