@owney/sdk 0.7.25-beta.6 → 0.7.25-beta.8
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 +17 -23
- package/dist/index.cjs +356 -153
- package/dist/index.d.cts +166 -147
- package/dist/index.d.ts +166 -147
- package/dist/index.js +356 -153
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1133,21 +1133,32 @@ function protocolsPolicyNeedsUpdate(current, desiredProtocols, desiredAutoSelect
|
|
|
1133
1133
|
var import_viem = require("viem");
|
|
1134
1134
|
var PAID_RPC_RETRY_COUNT = 3;
|
|
1135
1135
|
var PAID_RPC_RETRY_DELAY_MS = 1e3;
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1136
|
+
function configuredRpcProxyBaseUrl(baseUrl) {
|
|
1137
|
+
const configured = (baseUrl ?? "")?.trim();
|
|
1138
|
+
if (!configured) {
|
|
1139
|
+
throw new Error(
|
|
1140
|
+
"OWNEY_ROUTING_API_BASE_URL is required for RPC proxy requests unless routingApiBaseUrl or all rpcUrls are configured."
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
return configured;
|
|
1144
|
+
}
|
|
1145
|
+
function rpcProxyUrl(chainId, apiKey, baseUrl) {
|
|
1146
|
+
const url = new URL(
|
|
1147
|
+
`${configuredRpcProxyBaseUrl(baseUrl).replace(/\/$/, "")}/api/v1/rpc/${chainId}`
|
|
1148
|
+
);
|
|
1149
|
+
if (apiKey) url.searchParams.set("apiKey", apiKey);
|
|
1150
|
+
return url.toString();
|
|
1151
|
+
}
|
|
1152
|
+
function resolveRpcUrl(rpcUrls, chainId, apiKey = "", baseUrl) {
|
|
1142
1153
|
const url = rpcUrls?.[chainId]?.trim();
|
|
1143
1154
|
if (url) return url;
|
|
1144
|
-
return
|
|
1155
|
+
return rpcProxyUrl(chainId, apiKey, baseUrl);
|
|
1145
1156
|
}
|
|
1146
|
-
function resolveRpcUrls(rpcUrls) {
|
|
1157
|
+
function resolveRpcUrls(rpcUrls, apiKey = "", baseUrl) {
|
|
1147
1158
|
return {
|
|
1148
|
-
1: resolveRpcUrl(rpcUrls, 1),
|
|
1149
|
-
8453: resolveRpcUrl(rpcUrls, 8453),
|
|
1150
|
-
42161: resolveRpcUrl(rpcUrls, 42161)
|
|
1159
|
+
1: resolveRpcUrl(rpcUrls, 1, apiKey, baseUrl),
|
|
1160
|
+
8453: resolveRpcUrl(rpcUrls, 8453, apiKey, baseUrl),
|
|
1161
|
+
42161: resolveRpcUrl(rpcUrls, 42161, apiKey, baseUrl)
|
|
1151
1162
|
};
|
|
1152
1163
|
}
|
|
1153
1164
|
function createPaidRpcClient(chain, rpcUrls) {
|
|
@@ -1173,7 +1184,13 @@ function headerValue(error, name) {
|
|
|
1173
1184
|
seen.add(candidate);
|
|
1174
1185
|
const record = candidate;
|
|
1175
1186
|
const headers = record.headers;
|
|
1176
|
-
|
|
1187
|
+
let found;
|
|
1188
|
+
if (typeof headers?.get === "function") {
|
|
1189
|
+
found = headers.get(name);
|
|
1190
|
+
} else {
|
|
1191
|
+
const headerRecord = headers;
|
|
1192
|
+
found = headerRecord?.[name] ?? headerRecord?.[name.toLowerCase()];
|
|
1193
|
+
}
|
|
1177
1194
|
if (typeof found === "string" && found) {
|
|
1178
1195
|
value = found;
|
|
1179
1196
|
return;
|
|
@@ -2888,10 +2905,11 @@ var YieldseekerApiClient = class {
|
|
|
2888
2905
|
const payload = await response.json().catch(() => null);
|
|
2889
2906
|
if (!response.ok) {
|
|
2890
2907
|
const error = providerError(payload, `HTTP_${response.status}`);
|
|
2908
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
2891
2909
|
throw new YieldseekerApiError(
|
|
2892
2910
|
response.status,
|
|
2893
2911
|
error.code,
|
|
2894
|
-
error.fields
|
|
2912
|
+
retryAfter ? { ...error.fields, headers: { "Retry-After": retryAfter } } : error.fields
|
|
2895
2913
|
);
|
|
2896
2914
|
}
|
|
2897
2915
|
if (payload && typeof payload === "object" && payload.success === true && "data" in payload) {
|
|
@@ -3022,13 +3040,14 @@ function position(value, asset, baseAssetDecimals) {
|
|
|
3022
3040
|
// differ from the underlying asset. Yieldseeker already converts it to
|
|
3023
3041
|
// underlying base-asset units in `assetsBase`; pair that value with the
|
|
3024
3042
|
// snapshot's corresponding `baseAssetDecimals` for display. Keep the raw
|
|
3025
|
-
// share quantity
|
|
3043
|
+
// share quantity separate from the withdrawable underlying asset amount.
|
|
3026
3044
|
amount: decimal(
|
|
3027
3045
|
value.assetsBase,
|
|
3028
3046
|
baseAssetDecimals,
|
|
3029
3047
|
"yield positions"
|
|
3030
3048
|
),
|
|
3031
3049
|
amountRaw: String(value.assetsRaw),
|
|
3050
|
+
withdrawableAmountRaw: String(value.withdrawableAssetsRaw),
|
|
3032
3051
|
apy: percent(option.riskAdjustedApy),
|
|
3033
3052
|
tvl: Number(option.totalDepositsUsd),
|
|
3034
3053
|
liquidity: Number(option.withdrawableDepositsUsd)
|
|
@@ -3357,8 +3376,12 @@ var YIELDSEEKER_USERNAME_PREFIX = "owney_";
|
|
|
3357
3376
|
var YIELDSEEKER_USERNAME_RANDOM_LENGTH = 14;
|
|
3358
3377
|
var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
|
|
3359
3378
|
var YIELDSEEKER_YIELD_OPTIONS_CACHE_MS = 6e4;
|
|
3360
|
-
var YIELDSEEKER_AGENT_LIST_CACHE_MS =
|
|
3361
|
-
var YIELDSEEKER_PORTFOLIO_CACHE_MS =
|
|
3379
|
+
var YIELDSEEKER_AGENT_LIST_CACHE_MS = 12e4;
|
|
3380
|
+
var YIELDSEEKER_PORTFOLIO_CACHE_MS = 12e4;
|
|
3381
|
+
var YIELDSEEKER_SETTLEMENT_CACHE_MS = 5e3;
|
|
3382
|
+
var YIELDSEEKER_SETTLEMENT_ACTIVITY_CACHE_MS = 15e3;
|
|
3383
|
+
var YIELDSEEKER_READ_FAILURE_COOLDOWN_MS = 6e4;
|
|
3384
|
+
var YIELDSEEKER_SETTLEMENT_WINDOW_MS = 5 * 6e4;
|
|
3362
3385
|
var YIELDSEEKER_ACTIVITY_CACHE_MS = 6e4;
|
|
3363
3386
|
function generateYieldseekerUsername() {
|
|
3364
3387
|
const suffix = globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, YIELDSEEKER_USERNAME_RANDOM_LENGTH).toLowerCase();
|
|
@@ -3428,6 +3451,15 @@ var YieldseekerAgent = class {
|
|
|
3428
3451
|
readCache = /* @__PURE__ */ new Map();
|
|
3429
3452
|
pendingReads = /* @__PURE__ */ new Map();
|
|
3430
3453
|
readGeneration = 0;
|
|
3454
|
+
portfolioVersions = /* @__PURE__ */ new Map();
|
|
3455
|
+
snapshotFailures = /* @__PURE__ */ new Map();
|
|
3456
|
+
standardReadFailures = /* @__PURE__ */ new Map();
|
|
3457
|
+
reconcileUntil = /* @__PURE__ */ new Map();
|
|
3458
|
+
activityRefreshUntil = /* @__PURE__ */ new Map();
|
|
3459
|
+
// null means a confirmed movement has no reliable baseline. Do not guess
|
|
3460
|
+
// settlement; keep slow reconciliation after the fast window expires.
|
|
3461
|
+
snapshotMovements = /* @__PURE__ */ new Map();
|
|
3462
|
+
movementEpochs = /* @__PURE__ */ new Map();
|
|
3431
3463
|
yieldOptions = /* @__PURE__ */ new Map();
|
|
3432
3464
|
pendingYieldOptions = /* @__PURE__ */ new Map();
|
|
3433
3465
|
constructor(owneyApiKey, options = {}) {
|
|
@@ -3458,6 +3490,13 @@ var YieldseekerAgent = class {
|
|
|
3458
3490
|
this.pendingWalletContexts.clear();
|
|
3459
3491
|
this.readCache.clear();
|
|
3460
3492
|
this.pendingReads.clear();
|
|
3493
|
+
this.portfolioVersions.clear();
|
|
3494
|
+
this.snapshotFailures.clear();
|
|
3495
|
+
this.standardReadFailures.clear();
|
|
3496
|
+
this.reconcileUntil.clear();
|
|
3497
|
+
this.activityRefreshUntil.clear();
|
|
3498
|
+
this.snapshotMovements.clear();
|
|
3499
|
+
this.movementEpochs.clear();
|
|
3461
3500
|
}
|
|
3462
3501
|
async activateAgent(state, chainId, asset) {
|
|
3463
3502
|
this.assertChain(chainId);
|
|
@@ -3477,41 +3516,37 @@ var YieldseekerAgent = class {
|
|
|
3477
3516
|
);
|
|
3478
3517
|
}
|
|
3479
3518
|
const context = await this.ensureAgent(state, chainId, asset);
|
|
3519
|
+
const generation = this.readGeneration;
|
|
3520
|
+
const movement = this.snapshotMovement(state, chainId, context, BigInt(amount));
|
|
3480
3521
|
let txHash;
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
context.wallet.walletAddress,
|
|
3491
|
-
chainId,
|
|
3492
|
-
amount
|
|
3493
|
-
);
|
|
3494
|
-
await this.waitForReceipt(state, chainId, txHash);
|
|
3495
|
-
} else {
|
|
3496
|
-
txHash = await this.submitTransaction(state, chainId, {
|
|
3497
|
-
from: (0, import_viem7.getAddress)(state.walletAddress),
|
|
3498
|
-
to: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
3499
|
-
data: (0, import_viem7.encodeFunctionData)({
|
|
3500
|
-
abi: import_viem7.erc20Abi,
|
|
3501
|
-
functionName: "transfer",
|
|
3502
|
-
args: [(0, import_viem7.getAddress)(context.wallet.walletAddress), BigInt(amount)]
|
|
3503
|
-
}),
|
|
3504
|
-
value: "0",
|
|
3505
|
-
chainId
|
|
3506
|
-
});
|
|
3507
|
-
}
|
|
3508
|
-
} finally {
|
|
3509
|
-
await this.refreshSnapshotAfterMovement(
|
|
3510
|
-
state,
|
|
3522
|
+
if (depositCallback) {
|
|
3523
|
+
provideDepositVerificationContext(depositCallback, {
|
|
3524
|
+
agentId: "yieldseeker",
|
|
3525
|
+
signature: await this.auth.getToken(state, chainId),
|
|
3526
|
+
userId: context.user.userId,
|
|
3527
|
+
yieldseekerAgentId: context.agent.agentId
|
|
3528
|
+
});
|
|
3529
|
+
txHash = await depositCallback(
|
|
3530
|
+
context.wallet.walletAddress,
|
|
3511
3531
|
chainId,
|
|
3512
|
-
|
|
3513
|
-
"deposit"
|
|
3532
|
+
amount
|
|
3514
3533
|
);
|
|
3534
|
+
await this.waitForReceipt(state, chainId, txHash);
|
|
3535
|
+
} else {
|
|
3536
|
+
txHash = await this.submitTransaction(state, chainId, {
|
|
3537
|
+
from: (0, import_viem7.getAddress)(state.walletAddress),
|
|
3538
|
+
to: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
3539
|
+
data: (0, import_viem7.encodeFunctionData)({
|
|
3540
|
+
abi: import_viem7.erc20Abi,
|
|
3541
|
+
functionName: "transfer",
|
|
3542
|
+
args: [(0, import_viem7.getAddress)(context.wallet.walletAddress), BigInt(amount)]
|
|
3543
|
+
}),
|
|
3544
|
+
value: "0",
|
|
3545
|
+
chainId
|
|
3546
|
+
});
|
|
3547
|
+
}
|
|
3548
|
+
if (this.readGeneration === generation) {
|
|
3549
|
+
await this.refreshSnapshotAfterMovement(state, chainId, context, "deposit", movement);
|
|
3515
3550
|
}
|
|
3516
3551
|
return {
|
|
3517
3552
|
txHash,
|
|
@@ -3539,6 +3574,9 @@ var YieldseekerAgent = class {
|
|
|
3539
3574
|
this.id
|
|
3540
3575
|
);
|
|
3541
3576
|
}
|
|
3577
|
+
const generation = this.readGeneration;
|
|
3578
|
+
let confirmedMovement = false;
|
|
3579
|
+
let settlement = null;
|
|
3542
3580
|
try {
|
|
3543
3581
|
const portfolio = await this.loadPortfolioContext(
|
|
3544
3582
|
state,
|
|
@@ -3556,6 +3594,7 @@ var YieldseekerAgent = class {
|
|
|
3556
3594
|
);
|
|
3557
3595
|
const totalAvailable = idle + deployed;
|
|
3558
3596
|
const requested = amount === void 0 ? totalAvailable : BigInt(amount);
|
|
3597
|
+
const plannedMovement = this.snapshotMovement(state, chainId, context, -requested);
|
|
3559
3598
|
if (requested > totalAvailable) {
|
|
3560
3599
|
throw new OwneyError(
|
|
3561
3600
|
"WITHDRAW_INSUFFICIENT_BALANCE",
|
|
@@ -3591,6 +3630,7 @@ var YieldseekerAgent = class {
|
|
|
3591
3630
|
throw this.invalidResponse("position withdrawal");
|
|
3592
3631
|
}
|
|
3593
3632
|
await this.waitForReceipt(state, chainId, response.transactionHash);
|
|
3633
|
+
confirmedMovement = true;
|
|
3594
3634
|
remaining -= assetsRaw;
|
|
3595
3635
|
}
|
|
3596
3636
|
if (remaining > 0n) {
|
|
@@ -3615,18 +3655,23 @@ var YieldseekerAgent = class {
|
|
|
3615
3655
|
value: "0",
|
|
3616
3656
|
chainId
|
|
3617
3657
|
});
|
|
3658
|
+
confirmedMovement = true;
|
|
3659
|
+
settlement = plannedMovement;
|
|
3618
3660
|
return {
|
|
3619
3661
|
txHash,
|
|
3620
3662
|
type: amount === void 0 ? "full" : "partial",
|
|
3621
3663
|
amount: requested.toString()
|
|
3622
3664
|
};
|
|
3623
3665
|
} finally {
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3666
|
+
if (confirmedMovement && this.readGeneration === generation) {
|
|
3667
|
+
await this.refreshSnapshotAfterMovement(
|
|
3668
|
+
state,
|
|
3669
|
+
chainId,
|
|
3670
|
+
context,
|
|
3671
|
+
"withdrawal",
|
|
3672
|
+
settlement
|
|
3673
|
+
);
|
|
3674
|
+
}
|
|
3630
3675
|
}
|
|
3631
3676
|
}
|
|
3632
3677
|
async getBalances(state, chainId) {
|
|
@@ -3720,6 +3765,16 @@ var YieldseekerAgent = class {
|
|
|
3720
3765
|
contextKey(state, chainId, asset) {
|
|
3721
3766
|
return `${this.userKey(state, chainId)}:${asset}`;
|
|
3722
3767
|
}
|
|
3768
|
+
assertSession(generation, chainId, asset) {
|
|
3769
|
+
if (this.readGeneration !== generation) {
|
|
3770
|
+
throw new OwneyError(
|
|
3771
|
+
"NOT_CONNECTED",
|
|
3772
|
+
"Wallet session changed during the Yieldseeker request.",
|
|
3773
|
+
{ rpcSource: "agent-api", chainId, ...asset ? { asset } : {} },
|
|
3774
|
+
this.id
|
|
3775
|
+
);
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3723
3778
|
cachedRead(key2, ttlMs, read2) {
|
|
3724
3779
|
const cached = this.readCache.get(key2);
|
|
3725
3780
|
if (cached && cached.expiresAt > Date.now()) {
|
|
@@ -3729,7 +3784,7 @@ var YieldseekerAgent = class {
|
|
|
3729
3784
|
if (pending) return pending;
|
|
3730
3785
|
const generation = this.readGeneration;
|
|
3731
3786
|
const request = Promise.resolve().then(read2).then((value) => {
|
|
3732
|
-
if (this.readGeneration === generation) {
|
|
3787
|
+
if (this.readGeneration === generation && this.pendingReads.get(key2) === request) {
|
|
3733
3788
|
this.readCache.set(key2, {
|
|
3734
3789
|
expiresAt: Date.now() + ttlMs,
|
|
3735
3790
|
value
|
|
@@ -3777,6 +3832,7 @@ var YieldseekerAgent = class {
|
|
|
3777
3832
|
chainId,
|
|
3778
3833
|
`/users/${user.userId}/agents/${agent.agentId}/wallet`
|
|
3779
3834
|
).then((walletResponse) => {
|
|
3835
|
+
this.assertSession(generation, chainId, asset);
|
|
3780
3836
|
if (!walletResponse?.agentWallet || !(0, import_viem7.isAddress)(walletResponse.agentWallet.walletAddress)) {
|
|
3781
3837
|
throw this.invalidResponse("agent wallet");
|
|
3782
3838
|
}
|
|
@@ -3786,9 +3842,7 @@ var YieldseekerAgent = class {
|
|
|
3786
3842
|
wallet: walletResponse.agentWallet,
|
|
3787
3843
|
asset
|
|
3788
3844
|
};
|
|
3789
|
-
|
|
3790
|
-
this.agentContexts.set(key2, context);
|
|
3791
|
-
}
|
|
3845
|
+
this.agentContexts.set(key2, context);
|
|
3792
3846
|
return context;
|
|
3793
3847
|
});
|
|
3794
3848
|
this.pendingWalletContexts.set(key2, request);
|
|
@@ -3810,6 +3864,7 @@ var YieldseekerAgent = class {
|
|
|
3810
3864
|
return persisted;
|
|
3811
3865
|
}
|
|
3812
3866
|
const walletAddress = (0, import_viem7.getAddress)(state.walletAddress);
|
|
3867
|
+
const generation = this.readGeneration;
|
|
3813
3868
|
let user = null;
|
|
3814
3869
|
try {
|
|
3815
3870
|
const login = await this.providerRequest(
|
|
@@ -3856,6 +3911,7 @@ var YieldseekerAgent = class {
|
|
|
3856
3911
|
if (!user || !/^[a-zA-Z0-9_-]{1,128}$/.test(user.userId)) {
|
|
3857
3912
|
throw this.invalidResponse("wallet identity");
|
|
3858
3913
|
}
|
|
3914
|
+
this.assertSession(generation, chainId);
|
|
3859
3915
|
const resolved = { userId: user.userId };
|
|
3860
3916
|
this.users.set(key2, resolved);
|
|
3861
3917
|
writeYieldseekerIdentity(state.walletAddress, chainId, resolved.userId);
|
|
@@ -3871,10 +3927,13 @@ var YieldseekerAgent = class {
|
|
|
3871
3927
|
if (cached) return cached;
|
|
3872
3928
|
const pending = this.pendingAgents.get(key2);
|
|
3873
3929
|
if (pending) return pending;
|
|
3930
|
+
const generation = this.readGeneration;
|
|
3874
3931
|
const request = this.resolveAgent(state, chainId, asset, true).then(
|
|
3875
3932
|
async (context) => {
|
|
3933
|
+
this.assertSession(generation, chainId, asset);
|
|
3876
3934
|
if (!context) throw this.invalidResponse("agent creation");
|
|
3877
3935
|
await this.deployAgent(state, chainId, context);
|
|
3936
|
+
this.assertSession(generation, chainId, asset);
|
|
3878
3937
|
this.agentContexts.set(key2, context);
|
|
3879
3938
|
return context;
|
|
3880
3939
|
}
|
|
@@ -3883,20 +3942,25 @@ var YieldseekerAgent = class {
|
|
|
3883
3942
|
try {
|
|
3884
3943
|
return await request;
|
|
3885
3944
|
} finally {
|
|
3886
|
-
this.pendingAgents.delete(key2);
|
|
3945
|
+
if (this.pendingAgents.get(key2) === request) this.pendingAgents.delete(key2);
|
|
3887
3946
|
}
|
|
3888
3947
|
}
|
|
3889
3948
|
async findAgent(state, chainId, asset) {
|
|
3890
3949
|
const key2 = this.contextKey(state, chainId, asset);
|
|
3891
3950
|
const cached = this.agentContexts.get(key2);
|
|
3892
3951
|
if (cached) return cached;
|
|
3952
|
+
const generation = this.readGeneration;
|
|
3893
3953
|
const context = await this.resolveAgent(state, chainId, asset, false);
|
|
3954
|
+
this.assertSession(generation, chainId, asset);
|
|
3894
3955
|
if (context) this.agentContexts.set(key2, context);
|
|
3895
3956
|
return context;
|
|
3896
3957
|
}
|
|
3897
3958
|
async resolveAgent(state, chainId, asset, createIfMissing) {
|
|
3959
|
+
const generation = this.readGeneration;
|
|
3898
3960
|
const user = await this.resolveUser(state, chainId);
|
|
3961
|
+
this.assertSession(generation, chainId, asset);
|
|
3899
3962
|
const agents = await this.listAgents(state, chainId, user);
|
|
3963
|
+
this.assertSession(generation, chainId, asset);
|
|
3900
3964
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
3901
3965
|
let agent = agents.find(
|
|
3902
3966
|
(candidate) => this.isOwneyAgent(candidate) && candidate.chainId === chainId && candidate.type === "vault" && candidate.assetAddress.toLowerCase() === metadata.address.toLowerCase()
|
|
@@ -3918,6 +3982,7 @@ var YieldseekerAgent = class {
|
|
|
3918
3982
|
}
|
|
3919
3983
|
}
|
|
3920
3984
|
);
|
|
3985
|
+
this.assertSession(generation, chainId, asset);
|
|
3921
3986
|
agent = created?.agent;
|
|
3922
3987
|
if (agent) {
|
|
3923
3988
|
this.readCache.set(this.agentListKey(state, chainId), {
|
|
@@ -3933,8 +3998,11 @@ var YieldseekerAgent = class {
|
|
|
3933
3998
|
return this.contextForAgent(state, chainId, user, agent, asset);
|
|
3934
3999
|
}
|
|
3935
4000
|
async loadPortfolio(state, chainId, options) {
|
|
4001
|
+
const generation = this.readGeneration;
|
|
3936
4002
|
const user = await this.resolveUser(state, chainId);
|
|
4003
|
+
this.assertSession(generation, chainId);
|
|
3937
4004
|
const agents = await this.listAgents(state, chainId, user);
|
|
4005
|
+
this.assertSession(generation, chainId);
|
|
3938
4006
|
const contexts = [];
|
|
3939
4007
|
for (const agent of agents) {
|
|
3940
4008
|
const asset = this.assetForAgent(agent);
|
|
@@ -3945,81 +4013,187 @@ var YieldseekerAgent = class {
|
|
|
3945
4013
|
contexts.push(this.contextForAgent(state, chainId, user, agent, asset));
|
|
3946
4014
|
}
|
|
3947
4015
|
const resolvedContexts = await Promise.all(contexts);
|
|
4016
|
+
this.assertSession(generation, chainId);
|
|
3948
4017
|
return Promise.all(
|
|
3949
4018
|
resolvedContexts.map(
|
|
3950
4019
|
(context) => this.loadPortfolioContext(state, chainId, context, options)
|
|
3951
4020
|
)
|
|
3952
4021
|
);
|
|
3953
4022
|
}
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
3958
|
-
|
|
3959
|
-
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
4023
|
+
portfolioVersion(contextKey) {
|
|
4024
|
+
return this.portfolioVersions.get(contextKey) ?? 0;
|
|
4025
|
+
}
|
|
4026
|
+
portfolioCacheMs(contextKey) {
|
|
4027
|
+
return (this.reconcileUntil.get(contextKey) ?? 0) > Date.now() ? YIELDSEEKER_SETTLEMENT_CACHE_MS : YIELDSEEKER_PORTFOLIO_CACHE_MS;
|
|
4028
|
+
}
|
|
4029
|
+
snapshotMovement(state, chainId, context, delta) {
|
|
4030
|
+
const key2 = this.contextKey(state, chainId, context.asset);
|
|
4031
|
+
const previous = this.snapshotMovements.get(key2);
|
|
4032
|
+
if (this.snapshotMovements.has(key2)) {
|
|
4033
|
+
if (!previous || previous.delta > 0n !== delta > 0n) return null;
|
|
4034
|
+
return {
|
|
4035
|
+
...previous,
|
|
4036
|
+
epoch: this.movementEpochs.get(key2) ?? 0,
|
|
4037
|
+
delta: previous.delta + delta,
|
|
4038
|
+
expectedBalance: previous.expectedBalance + delta,
|
|
4039
|
+
expectedNetDeposits: previous.expectedNetDeposits + delta
|
|
4040
|
+
};
|
|
4041
|
+
}
|
|
4042
|
+
const cached = this.readCache.get(`snapshot:${key2}`);
|
|
4043
|
+
if (!cached || cached.expiresAt <= Date.now()) return null;
|
|
4044
|
+
const snapshot = cached.value.agentSnapshot;
|
|
4045
|
+
if (snapshot.baseAssetDecimals !== YIELDSEEKER_ASSET_METADATA[context.asset].decimals) return null;
|
|
4046
|
+
if (!/^-?\d+$/.test(snapshot.netDepositsBase) || !/^\d+$/.test(snapshot.totalValueBase)) return null;
|
|
4047
|
+
return {
|
|
4048
|
+
epoch: this.movementEpochs.get(key2) ?? 0,
|
|
4049
|
+
delta,
|
|
4050
|
+
decimals: snapshot.baseAssetDecimals,
|
|
4051
|
+
expectedBalance: BigInt(snapshot.totalValueBase) + delta,
|
|
4052
|
+
expectedNetDeposits: BigInt(snapshot.netDepositsBase) + delta
|
|
4053
|
+
};
|
|
4054
|
+
}
|
|
4055
|
+
advancePortfolioVersion(contextKey) {
|
|
4056
|
+
const version = this.portfolioVersion(contextKey) + 1;
|
|
4057
|
+
this.portfolioVersions.set(contextKey, version);
|
|
4058
|
+
this.snapshotFailures.delete(contextKey);
|
|
4059
|
+
for (const kind of ["snapshot", "positions", "historic", "actions"]) {
|
|
4060
|
+
const key2 = `${kind}:${contextKey}`;
|
|
4061
|
+
this.readCache.delete(key2);
|
|
4062
|
+
this.pendingReads.delete(key2);
|
|
4063
|
+
}
|
|
4064
|
+
return version;
|
|
4065
|
+
}
|
|
4066
|
+
requestPortfolioSnapshot(state, chainId, context, contextKey, version, generation, forceRefresh = false) {
|
|
4067
|
+
return this.walletRequest(
|
|
4068
|
+
state,
|
|
4069
|
+
chainId,
|
|
4070
|
+
`${this.agentPath(context, "snapshot")}${query(forceRefresh ? { shouldForceRefresh: true } : { shouldOnlyUseRecentValue: true, shouldAllowStaleOnError: true })}`
|
|
4071
|
+
).then((response) => {
|
|
4072
|
+
if (!response?.agentSnapshot) {
|
|
4073
|
+
throw this.invalidResponse("agent snapshot");
|
|
4074
|
+
}
|
|
4075
|
+
if (this.readGeneration === generation && this.portfolioVersion(contextKey) === version) {
|
|
4076
|
+
this.snapshotFailures.delete(contextKey);
|
|
4077
|
+
const movement = this.snapshotMovements.get(contextKey);
|
|
4078
|
+
const snapshot = response.agentSnapshot;
|
|
4079
|
+
if (movement && snapshot.baseAssetDecimals === movement.decimals && /^-?\d+$/.test(snapshot.netDepositsBase) && /^\d+$/.test(snapshot.totalValueBase)) {
|
|
4080
|
+
const balance = BigInt(snapshot.totalValueBase);
|
|
4081
|
+
const netDeposits = BigInt(snapshot.netDepositsBase);
|
|
4082
|
+
const reconciled = movement.delta > 0n ? balance >= movement.expectedBalance && netDeposits >= movement.expectedNetDeposits : balance <= movement.expectedBalance && netDeposits <= movement.expectedNetDeposits;
|
|
4083
|
+
if (reconciled) {
|
|
4084
|
+
this.snapshotMovements.delete(contextKey);
|
|
4085
|
+
this.reconcileUntil.delete(contextKey);
|
|
3986
4086
|
}
|
|
3987
|
-
return response;
|
|
3988
4087
|
}
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4088
|
+
}
|
|
4089
|
+
return response;
|
|
4090
|
+
}).catch((error) => {
|
|
4091
|
+
if (this.readGeneration === generation && this.portfolioVersion(contextKey) === version) {
|
|
4092
|
+
this.snapshotFailures.set(contextKey, {
|
|
4093
|
+
retryAt: Date.now() + Math.max(YIELDSEEKER_READ_FAILURE_COOLDOWN_MS, rateLimitDelay(error) ?? 0),
|
|
4094
|
+
error
|
|
4095
|
+
});
|
|
4096
|
+
}
|
|
4097
|
+
throw error;
|
|
4098
|
+
});
|
|
4099
|
+
}
|
|
4100
|
+
portfolioSnapshot(state, chainId, context, contextKey) {
|
|
4101
|
+
const key2 = `snapshot:${contextKey}`;
|
|
4102
|
+
const cached = this.readCache.get(key2);
|
|
4103
|
+
if ((!cached || cached.expiresAt <= Date.now()) && !this.pendingReads.has(key2)) {
|
|
4104
|
+
const failure = this.snapshotFailures.get(contextKey);
|
|
4105
|
+
if (failure && failure.retryAt > Date.now()) throw failure.error;
|
|
4106
|
+
this.advancePortfolioVersion(contextKey);
|
|
4107
|
+
}
|
|
4108
|
+
const version = this.portfolioVersion(contextKey);
|
|
4109
|
+
const generation = this.readGeneration;
|
|
4110
|
+
return {
|
|
4111
|
+
version,
|
|
4112
|
+
read: this.cachedRead(key2, this.portfolioCacheMs(contextKey), () => (
|
|
4113
|
+
// Only event-driven reconciliation forces refreshes. Routine reads
|
|
4114
|
+
// remain non-forced; the cache and shared cooldown still bound calls.
|
|
4115
|
+
this.requestPortfolioSnapshot(
|
|
4003
4116
|
state,
|
|
4004
4117
|
chainId,
|
|
4005
|
-
|
|
4118
|
+
context,
|
|
4119
|
+
contextKey,
|
|
4120
|
+
version,
|
|
4121
|
+
generation,
|
|
4122
|
+
this.snapshotMovements.has(contextKey)
|
|
4006
4123
|
)
|
|
4007
|
-
)
|
|
4008
|
-
]);
|
|
4009
|
-
if (!snapshot?.agentSnapshot) {
|
|
4010
|
-
throw this.invalidResponse("agent snapshot");
|
|
4011
|
-
}
|
|
4012
|
-
if (!Array.isArray(positions?.yieldPositions)) {
|
|
4013
|
-
throw this.invalidResponse("yield positions");
|
|
4014
|
-
}
|
|
4015
|
-
return {
|
|
4016
|
-
...context,
|
|
4017
|
-
snapshot: snapshot.agentSnapshot,
|
|
4018
|
-
positions: positions.yieldPositions,
|
|
4019
|
-
...historic?.position ? { historic: historic.position } : {},
|
|
4020
|
-
...actions?.actions ? { actions: actions.actions } : {}
|
|
4124
|
+
))
|
|
4021
4125
|
};
|
|
4022
4126
|
}
|
|
4127
|
+
async loadPortfolioContext(state, chainId, context, options = {}) {
|
|
4128
|
+
const contextKey = this.contextKey(state, chainId, context.asset);
|
|
4129
|
+
const generation = this.readGeneration;
|
|
4130
|
+
const assertSession = () => this.assertSession(generation, chainId, context.asset);
|
|
4131
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
4132
|
+
const { version, read: read2 } = this.portfolioSnapshot(state, chainId, context, contextKey);
|
|
4133
|
+
try {
|
|
4134
|
+
const snapshot = await read2;
|
|
4135
|
+
assertSession();
|
|
4136
|
+
if (this.portfolioVersion(contextKey) !== version) continue;
|
|
4137
|
+
const [positions, historic, actions] = await Promise.all([
|
|
4138
|
+
this.cachedRead(
|
|
4139
|
+
`positions:${contextKey}`,
|
|
4140
|
+
this.portfolioCacheMs(contextKey),
|
|
4141
|
+
async () => {
|
|
4142
|
+
const response = await this.walletRequest(
|
|
4143
|
+
state,
|
|
4144
|
+
chainId,
|
|
4145
|
+
this.agentPath(context, "yield-positions")
|
|
4146
|
+
);
|
|
4147
|
+
if (!Array.isArray(response?.yieldPositions)) {
|
|
4148
|
+
throw this.invalidResponse("yield positions");
|
|
4149
|
+
}
|
|
4150
|
+
return response;
|
|
4151
|
+
}
|
|
4152
|
+
),
|
|
4153
|
+
options.historic ? this.cachedRead(
|
|
4154
|
+
`historic:${contextKey}`,
|
|
4155
|
+
(this.activityRefreshUntil.get(contextKey) ?? 0) > Date.now() ? YIELDSEEKER_SETTLEMENT_ACTIVITY_CACHE_MS : YIELDSEEKER_ACTIVITY_CACHE_MS,
|
|
4156
|
+
() => this.walletRequest(
|
|
4157
|
+
state,
|
|
4158
|
+
chainId,
|
|
4159
|
+
this.agentPath(context, "wallet/historic-position")
|
|
4160
|
+
)
|
|
4161
|
+
) : Promise.resolve(void 0),
|
|
4162
|
+
options.actions ? this.cachedRead(
|
|
4163
|
+
`actions:${contextKey}`,
|
|
4164
|
+
(this.activityRefreshUntil.get(contextKey) ?? 0) > Date.now() ? YIELDSEEKER_SETTLEMENT_ACTIVITY_CACHE_MS : YIELDSEEKER_ACTIVITY_CACHE_MS,
|
|
4165
|
+
() => this.walletRequest(
|
|
4166
|
+
state,
|
|
4167
|
+
chainId,
|
|
4168
|
+
this.agentPath(context, "actions")
|
|
4169
|
+
)
|
|
4170
|
+
) : Promise.resolve(void 0)
|
|
4171
|
+
]);
|
|
4172
|
+
assertSession();
|
|
4173
|
+
if (this.portfolioVersion(contextKey) !== version) continue;
|
|
4174
|
+
if (!Array.isArray(positions?.yieldPositions)) {
|
|
4175
|
+
throw this.invalidResponse("yield positions");
|
|
4176
|
+
}
|
|
4177
|
+
return {
|
|
4178
|
+
...context,
|
|
4179
|
+
snapshot: snapshot.agentSnapshot,
|
|
4180
|
+
positions: positions.yieldPositions,
|
|
4181
|
+
...historic?.position ? { historic: historic.position } : {},
|
|
4182
|
+
...actions?.actions ? { actions: actions.actions } : {}
|
|
4183
|
+
};
|
|
4184
|
+
} catch (error) {
|
|
4185
|
+
assertSession();
|
|
4186
|
+
if (this.portfolioVersion(contextKey) !== version) continue;
|
|
4187
|
+
throw error;
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
throw new OwneyError(
|
|
4191
|
+
"AGENT_API_ERROR",
|
|
4192
|
+
"Yieldseeker portfolio changed during the read. Please retry.",
|
|
4193
|
+
{ rpcSource: "agent-api", chainId, asset: context.asset },
|
|
4194
|
+
this.id
|
|
4195
|
+
);
|
|
4196
|
+
}
|
|
4023
4197
|
async deployAgent(state, chainId, context) {
|
|
4024
4198
|
if (context.wallet.initializedDate != null) return;
|
|
4025
4199
|
const walletAddress = context.wallet.walletAddress.toLowerCase();
|
|
@@ -4036,42 +4210,52 @@ var YieldseekerAgent = class {
|
|
|
4036
4210
|
}
|
|
4037
4211
|
context.wallet = deployed.agentWallet;
|
|
4038
4212
|
}
|
|
4039
|
-
async refreshSnapshotAfterMovement(state, chainId, context, movement) {
|
|
4213
|
+
async refreshSnapshotAfterMovement(state, chainId, context, movement, settlement) {
|
|
4040
4214
|
const contextKey = this.contextKey(state, chainId, context.asset);
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4215
|
+
this.reconcileUntil.set(contextKey, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
|
|
4216
|
+
this.activityRefreshUntil.set(contextKey, Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS);
|
|
4217
|
+
const epoch = this.movementEpochs.get(contextKey) ?? 0;
|
|
4218
|
+
this.snapshotMovements.set(contextKey, settlement?.epoch === epoch ? settlement : null);
|
|
4219
|
+
this.movementEpochs.set(contextKey, epoch + 1);
|
|
4220
|
+
const version = this.advancePortfolioVersion(contextKey);
|
|
4221
|
+
const generation = this.readGeneration;
|
|
4047
4222
|
try {
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
shouldForceRefresh: true
|
|
4053
|
-
})}`
|
|
4223
|
+
await this.cachedRead(
|
|
4224
|
+
`snapshot:${contextKey}`,
|
|
4225
|
+
YIELDSEEKER_SETTLEMENT_CACHE_MS,
|
|
4226
|
+
() => this.requestPortfolioSnapshot(state, chainId, context, contextKey, version, generation, true)
|
|
4054
4227
|
);
|
|
4055
|
-
if (!response?.agentSnapshot) {
|
|
4056
|
-
throw this.invalidResponse("agent snapshot refresh");
|
|
4057
|
-
}
|
|
4058
4228
|
} catch (error) {
|
|
4059
4229
|
console.warn(
|
|
4060
4230
|
`[owney-sdk] Yieldseeker ${movement} snapshot refresh failed:`,
|
|
4061
4231
|
error
|
|
4062
4232
|
);
|
|
4063
|
-
} finally {
|
|
4064
|
-
invalidatePortfolio();
|
|
4065
4233
|
}
|
|
4066
4234
|
}
|
|
4067
4235
|
agentPath(context, suffix) {
|
|
4068
4236
|
return `/users/${context.user.userId}/agents/${context.agent.agentId}/${suffix}`;
|
|
4069
4237
|
}
|
|
4070
4238
|
async walletRequest(state, chainId, path, options = {}) {
|
|
4239
|
+
const read2 = (options.method ?? "GET") === "GET";
|
|
4240
|
+
const userKey = this.userKey(state, chainId);
|
|
4241
|
+
if (read2) {
|
|
4242
|
+
const failure = this.standardReadFailures.get(userKey);
|
|
4243
|
+
if (failure && failure.retryAt > Date.now()) throw failure.error;
|
|
4244
|
+
if (failure) this.standardReadFailures.delete(userKey);
|
|
4245
|
+
}
|
|
4246
|
+
const generation = this.readGeneration;
|
|
4071
4247
|
try {
|
|
4072
4248
|
return await this.providerRequest(state, chainId, path, options);
|
|
4073
4249
|
} catch (error) {
|
|
4074
|
-
|
|
4250
|
+
const mapped = this.mapApiError(error);
|
|
4251
|
+
const delay = read2 ? rateLimitDelay(mapped) : void 0;
|
|
4252
|
+
if (delay !== void 0 && this.readGeneration === generation) {
|
|
4253
|
+
this.standardReadFailures.set(userKey, {
|
|
4254
|
+
retryAt: Date.now() + Math.max(YIELDSEEKER_READ_FAILURE_COOLDOWN_MS, delay),
|
|
4255
|
+
error: mapped
|
|
4256
|
+
});
|
|
4257
|
+
}
|
|
4258
|
+
throw mapped;
|
|
4075
4259
|
}
|
|
4076
4260
|
}
|
|
4077
4261
|
async providerRequest(state, chainId, path, options = {}) {
|
|
@@ -4368,16 +4552,16 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
4368
4552
|
const positionChain = position2.chain.trim().toUpperCase();
|
|
4369
4553
|
const matchesChain = positionChain === String(chainId) || targetChain !== void 0 && positionChain === targetChain;
|
|
4370
4554
|
if (!matchesChain || position2.asset.toUpperCase() !== target) continue;
|
|
4371
|
-
|
|
4372
|
-
try {
|
|
4373
|
-
balance += BigInt(position2.amountRaw);
|
|
4374
|
-
continue;
|
|
4375
|
-
} catch {
|
|
4376
|
-
}
|
|
4377
|
-
}
|
|
4378
|
-
balance += (0, import_viem8.parseUnits)(position2.amount, decimals);
|
|
4555
|
+
balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : (0, import_viem8.parseUnits)(position2.amount, decimals);
|
|
4379
4556
|
}
|
|
4380
4557
|
}
|
|
4558
|
+
const assetTotal = agentBalance?.assetBalances?.find(
|
|
4559
|
+
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
4560
|
+
);
|
|
4561
|
+
if (assetTotal) {
|
|
4562
|
+
const total = (0, import_viem8.parseUnits)(assetTotal.amount, decimals);
|
|
4563
|
+
if (total < balance) balance = total > 0n ? total : 0n;
|
|
4564
|
+
}
|
|
4381
4565
|
return { agent, balance };
|
|
4382
4566
|
});
|
|
4383
4567
|
}
|
|
@@ -5137,8 +5321,12 @@ var OwneySDK = class {
|
|
|
5137
5321
|
constructor(config) {
|
|
5138
5322
|
this.apiKey = config.apiKey;
|
|
5139
5323
|
if (config.debug) setOwneyDebug(true);
|
|
5140
|
-
this.rpcUrls =
|
|
5141
|
-
|
|
5324
|
+
this.rpcUrls = resolveRpcUrls(
|
|
5325
|
+
config.rpcUrls,
|
|
5326
|
+
config.apiKey,
|
|
5327
|
+
config.routingApiBaseUrl
|
|
5328
|
+
);
|
|
5329
|
+
this.zyfaiRpcUrls = config.rpcUrls ? void 0 : config.zyfaiRpcUrls;
|
|
5142
5330
|
this.yieldseekerApiBaseUrl = config.yieldseekerApiBaseUrl;
|
|
5143
5331
|
this.yieldseekerSiweOrigin = config.yieldseekerSiweOrigin;
|
|
5144
5332
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
@@ -5413,7 +5601,11 @@ var OwneySDK = class {
|
|
|
5413
5601
|
if (!key2) return null;
|
|
5414
5602
|
return new ZyfaiAgent(
|
|
5415
5603
|
key2,
|
|
5416
|
-
this.
|
|
5604
|
+
this.zyfaiRpcUrls ? resolveRpcUrls(
|
|
5605
|
+
this.zyfaiRpcUrls,
|
|
5606
|
+
this.apiKey,
|
|
5607
|
+
this.routingApiBaseUrl
|
|
5608
|
+
) : this.rpcUrls,
|
|
5417
5609
|
this.referralSource
|
|
5418
5610
|
);
|
|
5419
5611
|
}
|
|
@@ -5990,7 +6182,14 @@ var OwneySDK = class {
|
|
|
5990
6182
|
* @returns {AgentWithdrawResult} for a single agent, or {OwneyWithdrawResult} with per-agent results
|
|
5991
6183
|
*/
|
|
5992
6184
|
async withdraw(options) {
|
|
5993
|
-
const { asset, amount, agentId } = options;
|
|
6185
|
+
const { asset, amount, agentId, onAgentResult } = options;
|
|
6186
|
+
const notifyAgentResult = (id, result) => {
|
|
6187
|
+
try {
|
|
6188
|
+
onAgentResult?.(id, result);
|
|
6189
|
+
} catch (error) {
|
|
6190
|
+
console.warn("Withdrawal result observer failed:", error);
|
|
6191
|
+
}
|
|
6192
|
+
};
|
|
5994
6193
|
const state = this.requireState();
|
|
5995
6194
|
const chainId = this.requireChainId();
|
|
5996
6195
|
const token = asset;
|
|
@@ -6006,12 +6205,14 @@ var OwneySDK = class {
|
|
|
6006
6205
|
if (agentId) {
|
|
6007
6206
|
const agent = this.getAgent(agentId);
|
|
6008
6207
|
this.validateAssetSupport(agent, chainId, asset);
|
|
6009
|
-
|
|
6208
|
+
const result = await withFailureReporting(
|
|
6010
6209
|
this.apiKey,
|
|
6011
6210
|
agent.id,
|
|
6012
6211
|
() => agent.withdraw(state, chainId, token, amount),
|
|
6013
6212
|
this.routingApiBaseUrl
|
|
6014
6213
|
);
|
|
6214
|
+
notifyAgentResult(agent.id, result);
|
|
6215
|
+
return result;
|
|
6015
6216
|
}
|
|
6016
6217
|
const eligibleAgents = this.getEligibleAgents(chainId, asset);
|
|
6017
6218
|
const withdrawalAgents = this.orderAgentsForWithdrawal(eligibleAgents);
|
|
@@ -6021,6 +6222,7 @@ var OwneySDK = class {
|
|
|
6021
6222
|
for (const agent of withdrawalAgents) {
|
|
6022
6223
|
try {
|
|
6023
6224
|
results2[agent.id] = await agent.withdraw(state, chainId, token);
|
|
6225
|
+
notifyAgentResult(agent.id, results2[agent.id]);
|
|
6024
6226
|
} catch (err) {
|
|
6025
6227
|
if (this.isUserRejectedWithdrawal(err)) throw err;
|
|
6026
6228
|
console.error(`withdraw failed for agent "${agent.id}":`, err);
|
|
@@ -6118,6 +6320,7 @@ var OwneySDK = class {
|
|
|
6118
6320
|
token,
|
|
6119
6321
|
p.planned.toString()
|
|
6120
6322
|
);
|
|
6323
|
+
notifyAgentResult(p.agent.id, results[p.agent.id]);
|
|
6121
6324
|
} catch (err) {
|
|
6122
6325
|
if (this.isUserRejectedWithdrawal(err)) throw err;
|
|
6123
6326
|
console.error(`withdraw failed for agent "${p.agent.id}":`, err);
|