@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.d.mts +205 -12
- package/dist/index.d.ts +205 -12
- package/dist/index.js +678 -11
- package/dist/index.mjs +676 -11
- package/package.json +1 -1
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:
|
|
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,
|