@owney/sdk 0.7.25-beta.16 → 0.7.25-beta.18
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.cjs +383 -141
- package/dist/index.d.cts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +319 -76
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1574,6 +1574,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1574
1574
|
earningsRefreshes = /* @__PURE__ */ new Map();
|
|
1575
1575
|
earningsSnapshot = null;
|
|
1576
1576
|
earningsGeneration = 0;
|
|
1577
|
+
balanceSnapshots = /* @__PURE__ */ new WeakMap();
|
|
1577
1578
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
1578
1579
|
this.rpcUrls = resolveRpcUrls(rpcUrls);
|
|
1579
1580
|
this.sdk = new import_sdk.ZyfaiSDK({
|
|
@@ -1777,7 +1778,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1777
1778
|
* chain/account switch fires the provider's `accountsChanged` →
|
|
1778
1779
|
* `disconnectAccount` (nulls walletClient + authenticatedUserId) while our
|
|
1779
1780
|
* own `connectAuth` guard still believes this chain is connected and
|
|
1780
|
-
* early-returns. Without this, authenticated calls (
|
|
1781
|
+
* early-returns. Without this, authenticated calls (sendDeposit,
|
|
1781
1782
|
* withdrawFunds) fail with "No account connected".
|
|
1782
1783
|
*/
|
|
1783
1784
|
async ensureConnected(state, chainId) {
|
|
@@ -2399,7 +2400,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2399
2400
|
return { txHash, smartWallet, amount, evidence: evidence2 };
|
|
2400
2401
|
}
|
|
2401
2402
|
await this.ensureWalletDeployed(this.getAddress(), validChainId);
|
|
2402
|
-
const raw2 = await this.sdk.
|
|
2403
|
+
const raw2 = await this.sdk.sendDeposit(
|
|
2403
2404
|
this.getAddress(),
|
|
2404
2405
|
validChainId,
|
|
2405
2406
|
amount,
|
|
@@ -2415,7 +2416,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2415
2416
|
intendedAmount: amount,
|
|
2416
2417
|
txHash: raw2.txHash,
|
|
2417
2418
|
transfer: "unknown",
|
|
2418
|
-
registration: "unknown",
|
|
2419
|
+
registration: raw2.registration ? "confirmed" : "unknown",
|
|
2419
2420
|
delivery: "not-applicable"
|
|
2420
2421
|
};
|
|
2421
2422
|
notifyFunding(onProgress, evidence);
|
|
@@ -2723,10 +2724,37 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2723
2724
|
}
|
|
2724
2725
|
async getBalances(state, chainId) {
|
|
2725
2726
|
const requestedAt = Date.now();
|
|
2727
|
+
const generation = this.earningsGeneration;
|
|
2726
2728
|
const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
|
|
2727
2729
|
const raw2 = await this.sdk.getPortfolio(this.getAddress());
|
|
2728
2730
|
const balance = mapBalances(raw2, validChainId, smartWallet);
|
|
2729
|
-
|
|
2731
|
+
const reads = balance.readMetadata?.map((read2) => ({ ...read2, requestedAt })) ?? [];
|
|
2732
|
+
for (const asset of SupportedAssets.filter((item) => item.chainId === chainId)) {
|
|
2733
|
+
if (!reads.some((read2) => read2.chainId === chainId && read2.asset === asset.symbol) && hasEmptyWithdrawalSnapshot(raw2, chainId, asset.symbol)) {
|
|
2734
|
+
reads.push({ chainId, asset: asset.symbol, requestedAt, fetchedAt: Date.now(), positionsStatus: "available" });
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
const result = { ...balance, readMetadata: reads };
|
|
2738
|
+
for (const read2 of reads) this.balanceSnapshots.set(read2, { raw: raw2, generation, owner: state.walletAddress.toLowerCase() });
|
|
2739
|
+
return result;
|
|
2740
|
+
}
|
|
2741
|
+
async verifyWithdrawalBalance(state, evidence, balance) {
|
|
2742
|
+
const read2 = balance.readMetadata?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
|
|
2743
|
+
const snapshot = read2 && this.balanceSnapshots.get(read2);
|
|
2744
|
+
const asset = SupportedAssets.find((item) => item.chainId === evidence.chainId && item.symbol === evidence.token);
|
|
2745
|
+
if (!snapshot || snapshot.generation !== this.earningsGeneration || snapshot.owner !== state.walletAddress.toLowerCase() || !read2 || !asset || !evidence.txHash || !evidence.blockNumber || !balance.smartWallet || balance.smartWallet.toLowerCase() !== evidence.agentWallet?.toLowerCase() || !hasEmptyWithdrawalSnapshot(snapshot.raw, evidence.chainId, evidence.token)) return void 0;
|
|
2746
|
+
const client = this.getPublicClient(evidence.chainId);
|
|
2747
|
+
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
2748
|
+
if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
|
|
2749
|
+
const idle = await client.readContract({
|
|
2750
|
+
address: asset.address,
|
|
2751
|
+
abi: import_viem4.erc20Abi,
|
|
2752
|
+
functionName: "balanceOf",
|
|
2753
|
+
args: [balance.smartWallet],
|
|
2754
|
+
blockNumber
|
|
2755
|
+
});
|
|
2756
|
+
if (idle !== 0n || snapshot.generation !== this.earningsGeneration || this.connectedAddress?.toLowerCase() !== snapshot.owner || this.connectedChainId !== evidence.chainId) return void 0;
|
|
2757
|
+
return { ...read2, withdrawalCheck: { txHash: evidence.txHash, blockNumber: blockNumber.toString() } };
|
|
2730
2758
|
}
|
|
2731
2759
|
earningsKey(state, chainId, smartWallet) {
|
|
2732
2760
|
return JSON.stringify([
|
|
@@ -2925,7 +2953,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2925
2953
|
};
|
|
2926
2954
|
|
|
2927
2955
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
2928
|
-
var
|
|
2956
|
+
var import_viem12 = require("viem");
|
|
2929
2957
|
var import_chains4 = require("viem/chains");
|
|
2930
2958
|
|
|
2931
2959
|
// src/lib/chain-guard.ts
|
|
@@ -3709,6 +3737,7 @@ function mapYieldseekerBalances(contexts) {
|
|
|
3709
3737
|
chainId: context.agent.chainId,
|
|
3710
3738
|
asset: context.asset,
|
|
3711
3739
|
fetchedAt: context.fetchedAt,
|
|
3740
|
+
requestedAt: context.requestedAt,
|
|
3712
3741
|
readVersion: context.readVersion,
|
|
3713
3742
|
providerUpdatedAt: context.snapshot.updatedDate,
|
|
3714
3743
|
snapshotId: String(context.snapshot.agentWalletSnapshotId),
|
|
@@ -4086,13 +4115,59 @@ function mapYieldseekerAgentApy(options, days) {
|
|
|
4086
4115
|
};
|
|
4087
4116
|
}
|
|
4088
4117
|
|
|
4089
|
-
// src/
|
|
4118
|
+
// src/lib/remaining-vault-balance.ts
|
|
4090
4119
|
var import_viem9 = require("viem");
|
|
4120
|
+
async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber) {
|
|
4121
|
+
const addresses = [...new Set(vaults.map((value) => value.toLowerCase()))];
|
|
4122
|
+
if (addresses.length > 64) return void 0;
|
|
4123
|
+
const batches = [];
|
|
4124
|
+
for (let index = 0; index < addresses.length; index += 10) batches.push(addresses.slice(index, index + 10));
|
|
4125
|
+
const values = await Promise.all(batches.map(async (batch) => {
|
|
4126
|
+
const balances = await client.multicall({
|
|
4127
|
+
blockNumber,
|
|
4128
|
+
allowFailure: true,
|
|
4129
|
+
contracts: batch.map((address) => ({
|
|
4130
|
+
address: (0, import_viem9.getAddress)(address),
|
|
4131
|
+
abi: import_viem9.erc20Abi,
|
|
4132
|
+
functionName: "balanceOf",
|
|
4133
|
+
args: [wallet]
|
|
4134
|
+
}))
|
|
4135
|
+
});
|
|
4136
|
+
if (balances.length !== batch.length) return void 0;
|
|
4137
|
+
const funded = [];
|
|
4138
|
+
for (let index = 0; index < batch.length; index++) {
|
|
4139
|
+
const result = balances[index];
|
|
4140
|
+
if (result?.status !== "success" || typeof result.result !== "bigint" || result.result < 0n) return void 0;
|
|
4141
|
+
if (result.result > 0n) funded.push({ address: (0, import_viem9.getAddress)(batch[index]), shares: result.result });
|
|
4142
|
+
}
|
|
4143
|
+
if (!funded.length) return 0n;
|
|
4144
|
+
const valuations = await client.multicall({
|
|
4145
|
+
blockNumber,
|
|
4146
|
+
allowFailure: true,
|
|
4147
|
+
contracts: funded.flatMap(({ address, shares }) => [
|
|
4148
|
+
{ address, abi: import_viem9.erc4626Abi, functionName: "asset" },
|
|
4149
|
+
{ address, abi: import_viem9.erc4626Abi, functionName: "convertToAssets", args: [shares] }
|
|
4150
|
+
])
|
|
4151
|
+
});
|
|
4152
|
+
if (valuations.length !== funded.length * 2) return void 0;
|
|
4153
|
+
let total = 0n;
|
|
4154
|
+
for (let index = 0; index < funded.length; index++) {
|
|
4155
|
+
const underlying = valuations[index * 2], value = valuations[index * 2 + 1];
|
|
4156
|
+
if (underlying?.status !== "success" || typeof underlying.result !== "string" || underlying.result.toLowerCase() !== asset.toLowerCase() || value?.status !== "success" || typeof value.result !== "bigint" || value.result < 0n) return void 0;
|
|
4157
|
+
total += value.result;
|
|
4158
|
+
}
|
|
4159
|
+
return total;
|
|
4160
|
+
}));
|
|
4161
|
+
return values.some((value) => value === void 0) ? void 0 : values.reduce((sum, value) => sum + value, 0n);
|
|
4162
|
+
}
|
|
4163
|
+
|
|
4164
|
+
// src/agents/yieldseeker/yieldseeker.wallet-version.ts
|
|
4165
|
+
var import_viem10 = require("viem");
|
|
4091
4166
|
var YIELDSEEKER_FACTORY = "0x9c7410a0faCAC60850C46eE5b58B518daec95130";
|
|
4092
4167
|
var YIELDSEEKER_V1_IMPLEMENTATION = "0x32403455357589523435dB18b414057D7cE05051";
|
|
4093
4168
|
var YIELDSEEKER_V2_IMPLEMENTATION = "0x613Db9c924ADB7A7A90c11b02Cce20c913E3Fe50";
|
|
4094
4169
|
var ERC1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
|
|
4095
|
-
var walletAbi = (0,
|
|
4170
|
+
var walletAbi = (0, import_viem10.parseAbi)([
|
|
4096
4171
|
"function owner() view returns (address)",
|
|
4097
4172
|
"function ownerAgentIndex() view returns (uint256)",
|
|
4098
4173
|
"function baseAsset() view returns (address)",
|
|
@@ -4100,7 +4175,7 @@ var walletAbi = (0, import_viem9.parseAbi)([
|
|
|
4100
4175
|
"function upgradeToLatest()",
|
|
4101
4176
|
"event Upgraded(address indexed implementation)"
|
|
4102
4177
|
]);
|
|
4103
|
-
var factoryAbi = (0,
|
|
4178
|
+
var factoryAbi = (0, import_viem10.parseAbi)([
|
|
4104
4179
|
"function userWallets(address owner, uint256 index) view returns (address)",
|
|
4105
4180
|
"function agentWalletImplementation() view returns (address)"
|
|
4106
4181
|
]);
|
|
@@ -4108,9 +4183,9 @@ function yieldseekerOwnerPath(code) {
|
|
|
4108
4183
|
return !code || code === "0x" || /^0xef0100[0-9a-f]{40}$/i.test(code) ? "eoa" : "smart";
|
|
4109
4184
|
}
|
|
4110
4185
|
async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNumber) {
|
|
4111
|
-
const agentWallet = (0,
|
|
4112
|
-
const expectedOwner = (0,
|
|
4113
|
-
const expectedAsset = (0,
|
|
4186
|
+
const agentWallet = (0, import_viem10.getAddress)(wallet);
|
|
4187
|
+
const expectedOwner = (0, import_viem10.getAddress)(owner);
|
|
4188
|
+
const expectedAsset = (0, import_viem10.getAddress)(asset);
|
|
4114
4189
|
const [code, ownerCode, slot, actualOwner, index, actualAsset, actualFactory, latest] = await Promise.all([
|
|
4115
4190
|
client.getBytecode({ address: agentWallet, blockNumber }),
|
|
4116
4191
|
client.getBytecode({ address: expectedOwner, blockNumber }),
|
|
@@ -4124,7 +4199,7 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
|
|
|
4124
4199
|
if (!code || code === "0x" || !slot || /^0x0+$/.test(slot)) {
|
|
4125
4200
|
throw new Error("Yieldseeker wallet is not a deployed ERC1967 proxy");
|
|
4126
4201
|
}
|
|
4127
|
-
const implementation = (0,
|
|
4202
|
+
const implementation = (0, import_viem10.getAddress)(`0x${slot.slice(-40)}`);
|
|
4128
4203
|
const mapped = await client.readContract({
|
|
4129
4204
|
address: YIELDSEEKER_FACTORY,
|
|
4130
4205
|
abi: factoryAbi,
|
|
@@ -4132,8 +4207,8 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
|
|
|
4132
4207
|
args: [expectedOwner, index],
|
|
4133
4208
|
blockNumber
|
|
4134
4209
|
});
|
|
4135
|
-
const verified = (0,
|
|
4136
|
-
const version = !verified ? "unknown" : (0,
|
|
4210
|
+
const verified = (0, import_viem10.isAddressEqual)(actualOwner, expectedOwner) && (0, import_viem10.isAddressEqual)(actualAsset, expectedAsset) && (0, import_viem10.isAddressEqual)(actualFactory, YIELDSEEKER_FACTORY) && (0, import_viem10.isAddressEqual)(mapped, agentWallet);
|
|
4211
|
+
const version = !verified ? "unknown" : (0, import_viem10.isAddressEqual)(implementation, YIELDSEEKER_V2_IMPLEMENTATION) ? "v2" : (0, import_viem10.isAddressEqual)(implementation, YIELDSEEKER_V1_IMPLEMENTATION) ? "v1" : "unknown";
|
|
4137
4212
|
return {
|
|
4138
4213
|
agentWallet,
|
|
4139
4214
|
owner: actualOwner,
|
|
@@ -4142,13 +4217,13 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
|
|
|
4142
4217
|
implementation,
|
|
4143
4218
|
version,
|
|
4144
4219
|
verified,
|
|
4145
|
-
upgradeAvailable: version === "v1" && (0,
|
|
4220
|
+
upgradeAvailable: version === "v1" && (0, import_viem10.isAddressEqual)(latest, YIELDSEEKER_V2_IMPLEMENTATION)
|
|
4146
4221
|
};
|
|
4147
4222
|
}
|
|
4148
4223
|
var YIELDSEEKER_UPGRADE_ABI = walletAbi;
|
|
4149
4224
|
|
|
4150
4225
|
// src/agents/yieldseeker/yieldseeker.sponsored-withdraw.ts
|
|
4151
|
-
var
|
|
4226
|
+
var import_viem11 = require("viem");
|
|
4152
4227
|
var import_account_abstraction2 = require("viem/account-abstraction");
|
|
4153
4228
|
var import_accounts = require("viem/accounts");
|
|
4154
4229
|
var import_chains3 = require("viem/chains");
|
|
@@ -4198,6 +4273,14 @@ function sponsorError(message, safeToFallback, details = {}) {
|
|
|
4198
4273
|
"yieldseeker"
|
|
4199
4274
|
);
|
|
4200
4275
|
}
|
|
4276
|
+
function assertIntentFresh(expiresAt) {
|
|
4277
|
+
if (!Number.isFinite(expiresAt) || Date.now() + 5e3 >= expiresAt * 1e3)
|
|
4278
|
+
throw sponsorError(
|
|
4279
|
+
"The withdrawal sponsorship request expired. Please try again.",
|
|
4280
|
+
true,
|
|
4281
|
+
{ failureCode: "SPONSOR_INTENT_EXPIRED" }
|
|
4282
|
+
);
|
|
4283
|
+
}
|
|
4201
4284
|
function providerReason(value) {
|
|
4202
4285
|
if (typeof value !== "string") return void 0;
|
|
4203
4286
|
return value.replace(/https?:\/\/\S+/gi, "[url]").replace(/0x[0-9a-fA-F]{40,}/g, "[hex]").replace(/[A-Za-z0-9_+=\/-]{48,}/g, "[token]").slice(0, 300);
|
|
@@ -4227,7 +4310,7 @@ function rpcDiagnostics(data) {
|
|
|
4227
4310
|
details.revertName = data.revertName;
|
|
4228
4311
|
if (typeof data?.aaCode === "string" && /^AA[0-9]{2}$/.test(data.aaCode)) details.aaCode = data.aaCode;
|
|
4229
4312
|
if (typeof data?.panicCode === "string" && /^0x[0-9a-fA-F]{1,2}$/.test(data.panicCode)) {
|
|
4230
|
-
const panicCode = (0,
|
|
4313
|
+
const panicCode = (0, import_viem11.toHex)(BigInt(data.panicCode));
|
|
4231
4314
|
if (["0x0", "0x1", "0x11", "0x12", "0x21", "0x22", "0x31", "0x32", "0x41", "0x51"].includes(panicCode))
|
|
4232
4315
|
details.panicCode = panicCode;
|
|
4233
4316
|
}
|
|
@@ -4447,14 +4530,14 @@ async function submitEoa(input) {
|
|
|
4447
4530
|
throw sponsorError("Base did not return EIP-1559 gas fees.", true);
|
|
4448
4531
|
let operation = {
|
|
4449
4532
|
sender: input.agentWallet,
|
|
4450
|
-
nonce: (0,
|
|
4533
|
+
nonce: (0, import_viem11.toHex)(nonce),
|
|
4451
4534
|
initCode: "0x",
|
|
4452
4535
|
callData: input.callData,
|
|
4453
|
-
callGasLimit: (0,
|
|
4454
|
-
verificationGasLimit: (0,
|
|
4455
|
-
preVerificationGas: (0,
|
|
4456
|
-
maxFeePerGas: (0,
|
|
4457
|
-
maxPriorityFeePerGas: (0,
|
|
4536
|
+
callGasLimit: (0, import_viem11.toHex)(3e5),
|
|
4537
|
+
verificationGasLimit: (0, import_viem11.toHex)(3e5),
|
|
4538
|
+
preVerificationGas: (0, import_viem11.toHex)(6e4),
|
|
4539
|
+
maxFeePerGas: (0, import_viem11.toHex)(fees.maxFeePerGas * USER_OP_FEE_HEADROOM),
|
|
4540
|
+
maxPriorityFeePerGas: (0, import_viem11.toHex)(fees.maxPriorityFeePerGas),
|
|
4458
4541
|
paymasterAndData: "0x",
|
|
4459
4542
|
signature: "0x"
|
|
4460
4543
|
};
|
|
@@ -4462,7 +4545,7 @@ async function submitEoa(input) {
|
|
|
4462
4545
|
const stub = await rpc(
|
|
4463
4546
|
input.rpcUrl,
|
|
4464
4547
|
"pm_getPaymasterStubData",
|
|
4465
|
-
[operation, ENTRY_POINT_V06, (0,
|
|
4548
|
+
[operation, ENTRY_POINT_V06, (0, import_viem11.toHex)(8453), {}],
|
|
4466
4549
|
"prepare"
|
|
4467
4550
|
);
|
|
4468
4551
|
if (!stub.paymasterAndData?.startsWith("0x"))
|
|
@@ -4477,7 +4560,7 @@ async function submitEoa(input) {
|
|
|
4477
4560
|
const final = await rpc(
|
|
4478
4561
|
input.rpcUrl,
|
|
4479
4562
|
"pm_getPaymasterData",
|
|
4480
|
-
[operation, ENTRY_POINT_V06, (0,
|
|
4563
|
+
[operation, ENTRY_POINT_V06, (0, import_viem11.toHex)(8453), {}],
|
|
4481
4564
|
"prepare"
|
|
4482
4565
|
);
|
|
4483
4566
|
if (!final.paymasterAndData?.startsWith("0x"))
|
|
@@ -4486,14 +4569,16 @@ async function submitEoa(input) {
|
|
|
4486
4569
|
}
|
|
4487
4570
|
const userOpHash = operationHash(operation);
|
|
4488
4571
|
await assertOwnerSession(input.state, input.owner);
|
|
4489
|
-
|
|
4572
|
+
assertIntentFresh(input.expiresAt);
|
|
4573
|
+
const wallet = (0, import_viem11.createWalletClient)({
|
|
4490
4574
|
account: input.owner,
|
|
4491
4575
|
chain: import_chains3.base,
|
|
4492
|
-
transport: (0,
|
|
4576
|
+
transport: (0, import_viem11.custom)(input.state.provider)
|
|
4493
4577
|
});
|
|
4494
4578
|
const signature = await wallet.signMessage({ message: { raw: userOpHash } });
|
|
4495
4579
|
operation = { ...operation, signature };
|
|
4496
4580
|
await assertOwnerSession(input.state, input.owner);
|
|
4581
|
+
assertIntentFresh(input.expiresAt);
|
|
4497
4582
|
const userOperation = {
|
|
4498
4583
|
sender: operation.sender,
|
|
4499
4584
|
nonce: operation.nonce,
|
|
@@ -4566,12 +4651,13 @@ async function submitSmart(input) {
|
|
|
4566
4651
|
} catch {
|
|
4567
4652
|
throw sponsorError("This account cannot check paymaster support on Base.", true);
|
|
4568
4653
|
}
|
|
4569
|
-
const supportsPaymaster = capabilities?.[(0,
|
|
4654
|
+
const supportsPaymaster = capabilities?.[(0, import_viem11.toHex)(8453)]?.paymasterService?.supported ?? capabilities?.["8453"]?.paymasterService?.supported ?? capabilities?.["0x0"]?.paymasterService?.supported;
|
|
4570
4655
|
if (supportsPaymaster !== true)
|
|
4571
4656
|
throw sponsorError("This account cannot use a paymaster on Base.", true);
|
|
4572
4657
|
await assertOwnerSession(input.state, input.owner);
|
|
4573
4658
|
let sent;
|
|
4574
|
-
|
|
4659
|
+
assertIntentFresh(input.expiresAt);
|
|
4660
|
+
const requestedId = (0, import_viem11.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
4575
4661
|
savePending(input.onPending, { callsId: requestedId }, true);
|
|
4576
4662
|
await checkpoint(input.onBeforeSubmission, { callsId: requestedId });
|
|
4577
4663
|
try {
|
|
@@ -4580,7 +4666,7 @@ async function submitSmart(input) {
|
|
|
4580
4666
|
params: [{
|
|
4581
4667
|
version: "2.0.0",
|
|
4582
4668
|
from: input.owner,
|
|
4583
|
-
chainId: (0,
|
|
4669
|
+
chainId: (0, import_viem11.toHex)(8453),
|
|
4584
4670
|
id: requestedId,
|
|
4585
4671
|
atomicRequired: false,
|
|
4586
4672
|
calls: [{ to: input.agentWallet, value: "0x0", data: input.callData }],
|
|
@@ -4655,7 +4741,7 @@ async function submitSmart(input) {
|
|
|
4655
4741
|
);
|
|
4656
4742
|
}
|
|
4657
4743
|
async function submitYieldseekerSponsoredWithdrawal(input) {
|
|
4658
|
-
const owner = (0,
|
|
4744
|
+
const owner = (0, import_viem11.getAddress)(input.state.walletAddress);
|
|
4659
4745
|
const { intent, rpcUrl } = await requestIntent({
|
|
4660
4746
|
apiKey: input.apiKey,
|
|
4661
4747
|
routingApiBaseUrl: input.routingApiBaseUrl,
|
|
@@ -4669,11 +4755,12 @@ async function submitYieldseekerSponsoredWithdrawal(input) {
|
|
|
4669
4755
|
action: "withdraw",
|
|
4670
4756
|
refreshYieldseekerSignature: input.refreshYieldseekerSignature
|
|
4671
4757
|
});
|
|
4672
|
-
|
|
4758
|
+
assertIntentFresh(intent.expiresAt);
|
|
4759
|
+
const args = { ...input, owner, rpcUrl, expiresAt: intent.expiresAt };
|
|
4673
4760
|
return intent.ownerPath === "eoa" ? submitEoa(args) : submitSmart(args);
|
|
4674
4761
|
}
|
|
4675
4762
|
async function submitYieldseekerSponsoredUpgrade(input) {
|
|
4676
|
-
const owner = (0,
|
|
4763
|
+
const owner = (0, import_viem11.getAddress)(input.state.walletAddress);
|
|
4677
4764
|
const { intent, rpcUrl } = await requestIntent({
|
|
4678
4765
|
apiKey: input.apiKey,
|
|
4679
4766
|
routingApiBaseUrl: input.routingApiBaseUrl,
|
|
@@ -4689,7 +4776,8 @@ async function submitYieldseekerSponsoredUpgrade(input) {
|
|
|
4689
4776
|
});
|
|
4690
4777
|
if (intent.ownerPath !== "smart")
|
|
4691
4778
|
throw sponsorError("V1 upgrade sponsorship requires a Base Account owner.", true);
|
|
4692
|
-
|
|
4779
|
+
assertIntentFresh(intent.expiresAt);
|
|
4780
|
+
return submitSmart({ ...input, owner, rpcUrl, expiresAt: intent.expiresAt });
|
|
4693
4781
|
}
|
|
4694
4782
|
|
|
4695
4783
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
@@ -4790,6 +4878,8 @@ var YieldseekerAgent = class {
|
|
|
4790
4878
|
transactionExecutor;
|
|
4791
4879
|
unwindReceiptWaiter;
|
|
4792
4880
|
agentContexts = /* @__PURE__ */ new Map();
|
|
4881
|
+
balanceContexts = /* @__PURE__ */ new WeakMap();
|
|
4882
|
+
balanceVaults = /* @__PURE__ */ new Map();
|
|
4793
4883
|
users = /* @__PURE__ */ new Map();
|
|
4794
4884
|
pendingAgents = /* @__PURE__ */ new Map();
|
|
4795
4885
|
pendingWalletContexts = /* @__PURE__ */ new Map();
|
|
@@ -4835,8 +4925,8 @@ var YieldseekerAgent = class {
|
|
|
4835
4925
|
if (useCachedV2 && cached && Date.now() - cached.at < 15 * 6e4) return { ...cached.status };
|
|
4836
4926
|
const status = await readYieldseekerWalletStatus(
|
|
4837
4927
|
this.getReceiptClient(),
|
|
4838
|
-
(0,
|
|
4839
|
-
(0,
|
|
4928
|
+
(0, import_viem12.getAddress)(context.wallet.walletAddress),
|
|
4929
|
+
(0, import_viem12.getAddress)(state.walletAddress),
|
|
4840
4930
|
YIELDSEEKER_ASSET_METADATA[asset].address
|
|
4841
4931
|
);
|
|
4842
4932
|
this.rememberWalletStatus(key2, status);
|
|
@@ -4866,12 +4956,12 @@ var YieldseekerAgent = class {
|
|
|
4866
4956
|
const pendingKey2 = `owney.yieldseeker.upgrade:${before.owner.toLowerCase()}:${before.agentWallet.toLowerCase()}`;
|
|
4867
4957
|
const confirmUpgrade = async (hash, receipt2) => {
|
|
4868
4958
|
this.withdrawalVersionCache.delete(versionKey);
|
|
4869
|
-
const upgradeTopic = (0,
|
|
4959
|
+
const upgradeTopic = (0, import_viem12.encodeEventTopics)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded" })[0];
|
|
4870
4960
|
const lastUpgrade = receipt2?.logs.filter((log) => log.address.toLowerCase() === before.agentWallet.toLowerCase() && log.topics[0] === upgradeTopic).at(-1);
|
|
4871
4961
|
const expectedUpgrade = (() => {
|
|
4872
4962
|
if (!lastUpgrade || lastUpgrade.removed) return false;
|
|
4873
4963
|
try {
|
|
4874
|
-
const event = (0,
|
|
4964
|
+
const event = (0, import_viem12.decodeEventLog)({ abi: YIELDSEEKER_UPGRADE_ABI, eventName: "Upgraded", data: lastUpgrade.data, topics: lastUpgrade.topics });
|
|
4875
4965
|
return event.args.implementation.toLowerCase() === YIELDSEEKER_V2_IMPLEMENTATION.toLowerCase();
|
|
4876
4966
|
} catch {
|
|
4877
4967
|
return false;
|
|
@@ -4989,7 +5079,7 @@ var YieldseekerAgent = class {
|
|
|
4989
5079
|
{ version: before.version },
|
|
4990
5080
|
this.id
|
|
4991
5081
|
);
|
|
4992
|
-
const data = (0,
|
|
5082
|
+
const data = (0, import_viem12.encodeFunctionData)({ abi: YIELDSEEKER_UPGRADE_ABI, functionName: "upgradeToLatest" });
|
|
4993
5083
|
let txHash;
|
|
4994
5084
|
let receipt;
|
|
4995
5085
|
if (gasMode === "sponsored") {
|
|
@@ -5032,7 +5122,7 @@ var YieldseekerAgent = class {
|
|
|
5032
5122
|
}
|
|
5033
5123
|
} else {
|
|
5034
5124
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5035
|
-
from: (0,
|
|
5125
|
+
from: (0, import_viem12.getAddress)(state.walletAddress),
|
|
5036
5126
|
to: before.agentWallet,
|
|
5037
5127
|
data,
|
|
5038
5128
|
value: "0",
|
|
@@ -5055,6 +5145,7 @@ var YieldseekerAgent = class {
|
|
|
5055
5145
|
}
|
|
5056
5146
|
this.users.clear();
|
|
5057
5147
|
this.agentContexts.clear();
|
|
5148
|
+
this.balanceVaults.clear();
|
|
5058
5149
|
this.pendingAgents.clear();
|
|
5059
5150
|
this.pendingWalletContexts.clear();
|
|
5060
5151
|
this.readCache.clear();
|
|
@@ -5118,12 +5209,12 @@ var YieldseekerAgent = class {
|
|
|
5118
5209
|
} else {
|
|
5119
5210
|
try {
|
|
5120
5211
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5121
|
-
from: (0,
|
|
5212
|
+
from: (0, import_viem12.getAddress)(state.walletAddress),
|
|
5122
5213
|
to: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
5123
|
-
data: (0,
|
|
5124
|
-
abi:
|
|
5214
|
+
data: (0, import_viem12.encodeFunctionData)({
|
|
5215
|
+
abi: import_viem12.erc20Abi,
|
|
5125
5216
|
functionName: "transfer",
|
|
5126
|
-
args: [(0,
|
|
5217
|
+
args: [(0, import_viem12.getAddress)(context.wallet.walletAddress), BigInt(amount)]
|
|
5127
5218
|
}),
|
|
5128
5219
|
value: "0",
|
|
5129
5220
|
chainId
|
|
@@ -5257,7 +5348,7 @@ var YieldseekerAgent = class {
|
|
|
5257
5348
|
);
|
|
5258
5349
|
const positionsRead = this.readWithdrawalPositions(state, chainId, context);
|
|
5259
5350
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
5260
|
-
const agentWallet = (0,
|
|
5351
|
+
const agentWallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
|
|
5261
5352
|
const readOwnerFunds = async (blockNumber) => {
|
|
5262
5353
|
const feeTracker = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5263
5354
|
address: agentWallet,
|
|
@@ -5266,18 +5357,18 @@ var YieldseekerAgent = class {
|
|
|
5266
5357
|
blockNumber
|
|
5267
5358
|
}), chainId, "eth_call", this.id);
|
|
5268
5359
|
this.assertSession(generation, chainId, asset);
|
|
5269
|
-
if (!(0,
|
|
5360
|
+
if (!(0, import_viem12.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker))
|
|
5270
5361
|
throw this.invalidResponse("wallet fee tracker");
|
|
5271
5362
|
const [idle2, fees] = await Promise.all([
|
|
5272
5363
|
withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5273
5364
|
address: metadata.address,
|
|
5274
|
-
abi:
|
|
5365
|
+
abi: import_viem12.erc20Abi,
|
|
5275
5366
|
functionName: "balanceOf",
|
|
5276
5367
|
args: [agentWallet],
|
|
5277
5368
|
blockNumber
|
|
5278
5369
|
}), chainId, "eth_call", this.id),
|
|
5279
5370
|
withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5280
|
-
address: (0,
|
|
5371
|
+
address: (0, import_viem12.getAddress)(feeTracker),
|
|
5281
5372
|
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
5282
5373
|
functionName: "getFeesOwed",
|
|
5283
5374
|
args: [agentWallet],
|
|
@@ -5319,13 +5410,13 @@ var YieldseekerAgent = class {
|
|
|
5319
5410
|
let active = true;
|
|
5320
5411
|
const checks = this.readVaultLiquidity(values.map((position2) => position2.yieldOption), agentWallet, blockNumber).catch(() => []);
|
|
5321
5412
|
const reads = values.map(async (position2, index) => {
|
|
5322
|
-
const address = (0,
|
|
5413
|
+
const address = (0, import_viem12.getAddress)(position2.yieldOption.address);
|
|
5323
5414
|
try {
|
|
5324
5415
|
const group = (await checks).slice(index * 3, index * 3 + 3);
|
|
5325
5416
|
if (!active || group.length !== 3 || group.some((value) => value.status !== "success")) return null;
|
|
5326
5417
|
this.assertSession(generation, chainId, asset);
|
|
5327
5418
|
const [underlying, shares, withdrawable] = group.map((value) => value.result);
|
|
5328
|
-
if (typeof underlying !== "string" || !(0,
|
|
5419
|
+
if (typeof underlying !== "string" || !(0, import_viem12.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n || typeof withdrawable !== "bigint" || withdrawable < 0n) return null;
|
|
5329
5420
|
const verified = { ...position2, assetsRaw: shares.toString(), withdrawableAssetsRaw: withdrawable.toString() };
|
|
5330
5421
|
if (shares > 0n && withdrawable === 0n) {
|
|
5331
5422
|
let positiveValue = false;
|
|
@@ -5333,7 +5424,7 @@ var YieldseekerAgent = class {
|
|
|
5333
5424
|
try {
|
|
5334
5425
|
const value = await this.getReceiptClient().readContract({
|
|
5335
5426
|
address,
|
|
5336
|
-
abi:
|
|
5427
|
+
abi: import_viem12.erc4626Abi,
|
|
5337
5428
|
functionName,
|
|
5338
5429
|
args: [shares],
|
|
5339
5430
|
blockNumber
|
|
@@ -5546,14 +5637,14 @@ var YieldseekerAgent = class {
|
|
|
5546
5637
|
delta: maxSettlementBasis.delta - payout,
|
|
5547
5638
|
expectedNetDeposits: maxSettlementBasis.expectedNetDeposits - payout
|
|
5548
5639
|
} : this.snapshotMovement(state, chainId, context, -payout);
|
|
5549
|
-
const account = (0,
|
|
5640
|
+
const account = (0, import_viem12.getAddress)(state.walletAddress);
|
|
5550
5641
|
let receipt;
|
|
5551
5642
|
const base6 = { agentId: this.id, chainId, token: asset, walletAddress: state.walletAddress, agentWallet: context.wallet.walletAddress, intendedAmount: amount === void 0 ? "MAX" : payout.toString(), transfer: "pending", registration: "not-applicable", delivery: "pending" };
|
|
5552
|
-
const data = amount === void 0 ? (0,
|
|
5643
|
+
const data = amount === void 0 ? (0, import_viem12.encodeFunctionData)({
|
|
5553
5644
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
5554
5645
|
functionName: "withdrawAllAssetToUser",
|
|
5555
5646
|
args: [account, metadata.address]
|
|
5556
|
-
}) : (0,
|
|
5647
|
+
}) : (0, import_viem12.encodeFunctionData)({
|
|
5557
5648
|
abi: YIELDSEEKER_AGENT_WALLET_ABI,
|
|
5558
5649
|
functionName: "withdrawAssetToUser",
|
|
5559
5650
|
args: [account, metadata.address, payout]
|
|
@@ -5569,7 +5660,7 @@ var YieldseekerAgent = class {
|
|
|
5569
5660
|
refreshYieldseekerSignature: (rejected) => this.auth.refreshToken(state, chainId, rejected),
|
|
5570
5661
|
userId: context.user.userId,
|
|
5571
5662
|
agentId: context.agent.agentId,
|
|
5572
|
-
agentWallet: (0,
|
|
5663
|
+
agentWallet: (0, import_viem12.getAddress)(context.wallet.walletAddress),
|
|
5573
5664
|
asset: metadata.address,
|
|
5574
5665
|
callData: data,
|
|
5575
5666
|
onPending: (pending) => notifyFunding(onProgress, { ...base6, ...pending }),
|
|
@@ -5584,7 +5675,7 @@ var YieldseekerAgent = class {
|
|
|
5584
5675
|
onOwnerTransferAttempted?.();
|
|
5585
5676
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5586
5677
|
from: account,
|
|
5587
|
-
to: (0,
|
|
5678
|
+
to: (0, import_viem12.getAddress)(context.wallet.walletAddress),
|
|
5588
5679
|
data,
|
|
5589
5680
|
value: "0",
|
|
5590
5681
|
chainId
|
|
@@ -5692,17 +5783,17 @@ var YieldseekerAgent = class {
|
|
|
5692
5783
|
return proof.available;
|
|
5693
5784
|
}
|
|
5694
5785
|
async readVaultLiquidity(options, wallet, blockNumber) {
|
|
5695
|
-
const owner = (0,
|
|
5786
|
+
const owner = (0, import_viem12.getAddress)(wallet);
|
|
5696
5787
|
const batches = Array.from({ length: Math.ceil(options.length / YIELDSEEKER_VAULTS_PER_RPC_BATCH) }, (_, index) => options.slice(index * YIELDSEEKER_VAULTS_PER_RPC_BATCH, (index + 1) * YIELDSEEKER_VAULTS_PER_RPC_BATCH));
|
|
5697
5788
|
const results = await Promise.all(batches.map((batch) => this.getReceiptClient().multicall({
|
|
5698
5789
|
blockNumber,
|
|
5699
5790
|
allowFailure: true,
|
|
5700
5791
|
contracts: batch.flatMap((option) => {
|
|
5701
|
-
const address = (0,
|
|
5792
|
+
const address = (0, import_viem12.getAddress)(option.address);
|
|
5702
5793
|
return [
|
|
5703
|
-
{ address, abi:
|
|
5704
|
-
{ address, abi:
|
|
5705
|
-
{ address, abi:
|
|
5794
|
+
{ address, abi: import_viem12.erc4626Abi, functionName: "asset" },
|
|
5795
|
+
{ address, abi: import_viem12.erc20Abi, functionName: "balanceOf", args: [owner] },
|
|
5796
|
+
{ address, abi: import_viem12.erc4626Abi, functionName: "maxWithdraw", args: [owner] }
|
|
5706
5797
|
];
|
|
5707
5798
|
})
|
|
5708
5799
|
})));
|
|
@@ -5713,7 +5804,7 @@ var YieldseekerAgent = class {
|
|
|
5713
5804
|
const seen = /* @__PURE__ */ new Set();
|
|
5714
5805
|
for (const value of values) {
|
|
5715
5806
|
const option = value?.yieldOption;
|
|
5716
|
-
if (!option || typeof option.address !== "string" || !(0,
|
|
5807
|
+
if (!option || typeof option.address !== "string" || !(0, import_viem12.isAddress)(option.address) || seen.has(option.address.toLowerCase()) || option.chainId !== void 0 && option.chainId !== chainId || option.assetAddress !== void 0 && (typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== underlying) || typeof value.assetsRaw !== "string" || !/^\d+$/.test(value.assetsRaw) || typeof value.withdrawableAssetsRaw !== "string" || !/^\d+$/.test(value.withdrawableAssetsRaw))
|
|
5717
5808
|
throw this.invalidResponse("yield positions");
|
|
5718
5809
|
seen.add(option.address.toLowerCase());
|
|
5719
5810
|
}
|
|
@@ -5726,7 +5817,7 @@ var YieldseekerAgent = class {
|
|
|
5726
5817
|
const historic = this.readCache.get(`historic:${key2}`)?.value?.position;
|
|
5727
5818
|
const receivedAssets = new Set((historic?.movements ?? []).filter((movement) => movement.chainId === chainId && movement.agentWalletId === context.wallet.agentWalletId && movement.toAddress?.toLowerCase() === context.wallet.walletAddress.toLowerCase()).filter((movement) => typeof movement.assetAddress === "string").map((movement) => movement.assetAddress.toLowerCase()));
|
|
5728
5819
|
for (const option of this.yieldOptions.get(context.asset)?.value ?? []) {
|
|
5729
|
-
if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0,
|
|
5820
|
+
if (option.chainId !== chainId || typeof option.assetAddress !== "string" || option.assetAddress.toLowerCase() !== YIELDSEEKER_ASSET_METADATA[context.asset].address.toLowerCase() || !(0, import_viem12.isAddress)(option.address) || !receivedAssets.has(option.address.toLowerCase()) || hints.has(option.address.toLowerCase())) continue;
|
|
5730
5821
|
hints.set(option.address.toLowerCase(), {
|
|
5731
5822
|
yieldOption: option,
|
|
5732
5823
|
assetsRaw: "0",
|
|
@@ -5778,7 +5869,7 @@ var YieldseekerAgent = class {
|
|
|
5778
5869
|
const read2 = async () => {
|
|
5779
5870
|
const client = this.getReceiptClient();
|
|
5780
5871
|
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
5781
|
-
const wallet = (0,
|
|
5872
|
+
const wallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
|
|
5782
5873
|
assertReadCurrent();
|
|
5783
5874
|
if (typeof blockNumber !== "bigint") throw unavailable();
|
|
5784
5875
|
const indexedPositions = this.validateWithdrawalPositions(positions ?? [], chainId, context.asset);
|
|
@@ -5792,7 +5883,7 @@ var YieldseekerAgent = class {
|
|
|
5792
5883
|
this.readVaultLiquidity(options, wallet, blockNumber),
|
|
5793
5884
|
client.readContract({
|
|
5794
5885
|
address: metadata.address,
|
|
5795
|
-
abi:
|
|
5886
|
+
abi: import_viem12.erc20Abi,
|
|
5796
5887
|
functionName: "balanceOf",
|
|
5797
5888
|
args: [wallet],
|
|
5798
5889
|
blockNumber
|
|
@@ -5804,10 +5895,10 @@ var YieldseekerAgent = class {
|
|
|
5804
5895
|
blockNumber
|
|
5805
5896
|
})
|
|
5806
5897
|
]);
|
|
5807
|
-
if (typeof idle !== "bigint" || idle < 0n || !(0,
|
|
5898
|
+
if (typeof idle !== "bigint" || idle < 0n || !(0, import_viem12.isAddress)(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
|
|
5808
5899
|
assertReadCurrent();
|
|
5809
5900
|
const fees = await client.readContract({
|
|
5810
|
-
address: (0,
|
|
5901
|
+
address: (0, import_viem12.getAddress)(feeTracker),
|
|
5811
5902
|
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
5812
5903
|
functionName: "getFeesOwed",
|
|
5813
5904
|
args: [wallet],
|
|
@@ -5818,15 +5909,21 @@ var YieldseekerAgent = class {
|
|
|
5818
5909
|
const verifiedVaults = [];
|
|
5819
5910
|
let deployed = 0n;
|
|
5820
5911
|
const collect = (options2, results) => {
|
|
5912
|
+
assertReadCurrent();
|
|
5913
|
+
const known = this.balanceVaults.get(contextKey) ?? /* @__PURE__ */ new Set();
|
|
5914
|
+
this.balanceVaults.set(contextKey, known);
|
|
5821
5915
|
let valid2 = true;
|
|
5822
5916
|
options2.forEach((option, index) => {
|
|
5823
5917
|
const group = results.slice(index * 3, index * 3 + 3);
|
|
5918
|
+
const shareProbe = group[1];
|
|
5919
|
+
if (shareProbe?.status === "success" && typeof shareProbe.result === "bigint" && shareProbe.result > 0n)
|
|
5920
|
+
known.add(option.address.toLowerCase());
|
|
5824
5921
|
if (group.length !== 3 || group.some((value) => value.status !== "success")) {
|
|
5825
5922
|
valid2 = false;
|
|
5826
5923
|
return;
|
|
5827
5924
|
}
|
|
5828
5925
|
const [underlying, shares, withdrawable] = group.map((value) => value.result);
|
|
5829
|
-
if (typeof underlying !== "string" || !(0,
|
|
5926
|
+
if (typeof underlying !== "string" || !(0, import_viem12.isAddress)(underlying) || underlying.toLowerCase() !== metadata.address.toLowerCase() || typeof shares !== "bigint" || shares < 0n || typeof withdrawable !== "bigint" || withdrawable < 0n || shares === 0n && withdrawable > 0n) {
|
|
5830
5927
|
valid2 = false;
|
|
5831
5928
|
return;
|
|
5832
5929
|
}
|
|
@@ -5870,7 +5967,7 @@ var YieldseekerAgent = class {
|
|
|
5870
5967
|
assertReadCurrent();
|
|
5871
5968
|
const eligible = /* @__PURE__ */ new Map();
|
|
5872
5969
|
for (const option of catalog ?? []) {
|
|
5873
|
-
if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0,
|
|
5970
|
+
if (option?.chainId === chainId && typeof option.assetAddress === "string" && option.assetAddress.toLowerCase() === metadata.address.toLowerCase() && (0, import_viem12.isAddress)(option.address))
|
|
5874
5971
|
eligible.set(option.address.toLowerCase(), option);
|
|
5875
5972
|
}
|
|
5876
5973
|
const extra = [...eligible].filter(([address]) => !candidates.has(address)).map(([, option]) => option);
|
|
@@ -5899,7 +5996,59 @@ var YieldseekerAgent = class {
|
|
|
5899
5996
|
async getBalances(state, chainId, asset) {
|
|
5900
5997
|
this.assertChain(chainId);
|
|
5901
5998
|
if (asset !== void 0) this.assertAsset(asset);
|
|
5902
|
-
|
|
5999
|
+
const contexts = await this.loadPortfolio(state, chainId, { asset, allowMissingPositions: true });
|
|
6000
|
+
const balance = mapYieldseekerBalances(contexts);
|
|
6001
|
+
for (const context of contexts) {
|
|
6002
|
+
const read2 = balance.readMetadata.find((item) => item.asset === context.asset);
|
|
6003
|
+
this.balanceContexts.set(read2, { context, generation: this.readGeneration });
|
|
6004
|
+
const key2 = this.contextKey(state, chainId, context.asset);
|
|
6005
|
+
const known = this.balanceVaults.get(key2) ?? /* @__PURE__ */ new Set();
|
|
6006
|
+
for (const position2 of context.positions) known.add(position2.yieldOption.address.toLowerCase());
|
|
6007
|
+
this.balanceVaults.set(key2, known);
|
|
6008
|
+
}
|
|
6009
|
+
return balance;
|
|
6010
|
+
}
|
|
6011
|
+
async verifyWithdrawalBalance(state, evidence, balance) {
|
|
6012
|
+
this.assertAsset(evidence.token);
|
|
6013
|
+
this.assertChain(evidence.chainId);
|
|
6014
|
+
const read2 = balance.readMetadata?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
|
|
6015
|
+
const cached = read2 && this.balanceContexts.get(read2);
|
|
6016
|
+
const context = cached?.generation === this.readGeneration ? cached.context : void 0;
|
|
6017
|
+
if (!context || context.positionsUnavailable || !read2 || !evidence.blockNumber || !evidence.txHash || context.wallet.walletAddress.toLowerCase() !== evidence.agentWallet?.toLowerCase()) return void 0;
|
|
6018
|
+
const key2 = this.contextKey(state, evidence.chainId, evidence.token);
|
|
6019
|
+
const generation = this.readGeneration, version = this.portfolioVersion(key2);
|
|
6020
|
+
if (read2.readVersion !== version) return void 0;
|
|
6021
|
+
const wallet = (0, import_viem12.getAddress)(context.wallet.walletAddress);
|
|
6022
|
+
const asset = YIELDSEEKER_ASSET_METADATA[evidence.token];
|
|
6023
|
+
const client = this.getReceiptClient();
|
|
6024
|
+
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
6025
|
+
if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
|
|
6026
|
+
const vaults = [...this.balanceVaults.get(key2) ?? []];
|
|
6027
|
+
const [invested, idle, tracker] = await Promise.all([
|
|
6028
|
+
remainingVaultBalance(client, wallet, asset.address, vaults, blockNumber),
|
|
6029
|
+
client.readContract({ address: asset.address, abi: import_viem12.erc20Abi, functionName: "balanceOf", args: [wallet], blockNumber }),
|
|
6030
|
+
client.readContract({ address: wallet, abi: YIELDSEEKER_AGENT_WALLET_ABI, functionName: "feeTracker", blockNumber })
|
|
6031
|
+
]);
|
|
6032
|
+
if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !(0, import_viem12.isAddress)(tracker) || /^0x0{40}$/i.test(tracker)) return void 0;
|
|
6033
|
+
const fees = await client.readContract({
|
|
6034
|
+
address: tracker,
|
|
6035
|
+
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
6036
|
+
functionName: "getFeesOwed",
|
|
6037
|
+
args: [wallet],
|
|
6038
|
+
blockNumber
|
|
6039
|
+
});
|
|
6040
|
+
this.assertSession(generation, evidence.chainId, evidence.token);
|
|
6041
|
+
if (version !== this.portfolioVersion(key2) || typeof fees !== "bigint" || fees < 0n) return void 0;
|
|
6042
|
+
const total = idle + invested > fees ? idle + invested - fees : 0n;
|
|
6043
|
+
const displayed = balance.assetBalances?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
|
|
6044
|
+
if (!displayed || !evidence.confirmedAmount || !/^\d+$/.test(evidence.confirmedAmount)) return void 0;
|
|
6045
|
+
const amount = (0, import_viem12.parseUnits)(displayed.amount, asset.decimals);
|
|
6046
|
+
if (amount < 0n) return void 0;
|
|
6047
|
+
const displayUnit = evidence.token === "USDC" ? 5000n : 500000000000n;
|
|
6048
|
+
const movementUnit = BigInt(evidence.confirmedAmount) / 1000n;
|
|
6049
|
+
const tolerance = movementUnit < displayUnit ? movementUnit : displayUnit;
|
|
6050
|
+
if ((total > amount ? total - amount : amount - total) > tolerance) return void 0;
|
|
6051
|
+
return { ...read2, withdrawalCheck: { txHash: evidence.txHash, blockNumber: blockNumber.toString() } };
|
|
5903
6052
|
}
|
|
5904
6053
|
invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS) {
|
|
5905
6054
|
this.assertAsset(asset);
|
|
@@ -5939,9 +6088,9 @@ var YieldseekerAgent = class {
|
|
|
5939
6088
|
if (!context) return void 0;
|
|
5940
6089
|
const idle = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5941
6090
|
address: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
5942
|
-
abi:
|
|
6091
|
+
abi: import_viem12.erc20Abi,
|
|
5943
6092
|
functionName: "balanceOf",
|
|
5944
|
-
args: [(0,
|
|
6093
|
+
args: [(0, import_viem12.getAddress)(context.wallet.walletAddress)]
|
|
5945
6094
|
}), chainId, "eth_call", this.id);
|
|
5946
6095
|
this.assertSession(generation, chainId, asset);
|
|
5947
6096
|
if (typeof idle !== "bigint" || idle < 0n) throw this.invalidResponse("wallet deposit balance");
|
|
@@ -5977,7 +6126,7 @@ var YieldseekerAgent = class {
|
|
|
5977
6126
|
);
|
|
5978
6127
|
const vaultAddresses = new Set(
|
|
5979
6128
|
catalog.flat().filter(
|
|
5980
|
-
(yieldOption) => yieldOption.chainId === chainId && (0,
|
|
6129
|
+
(yieldOption) => yieldOption.chainId === chainId && (0, import_viem12.isAddress)(yieldOption.address)
|
|
5981
6130
|
).map((yieldOption) => yieldOption.address.toLowerCase())
|
|
5982
6131
|
);
|
|
5983
6132
|
return mapYieldseekerHistory(contexts, {
|
|
@@ -6053,11 +6202,13 @@ var YieldseekerAgent = class {
|
|
|
6053
6202
|
const pending = this.pendingReads.get(key2);
|
|
6054
6203
|
if (pending) return pending;
|
|
6055
6204
|
const generation = this.readGeneration;
|
|
6205
|
+
const requestedAt = Date.now();
|
|
6056
6206
|
const request = Promise.resolve().then(read2).then((value) => {
|
|
6057
6207
|
if (this.readGeneration === generation && this.pendingReads.get(key2) === request) {
|
|
6058
6208
|
this.readCache.set(key2, {
|
|
6059
6209
|
expiresAt: Date.now() + ttlMs,
|
|
6060
6210
|
fetchedAt: Date.now(),
|
|
6211
|
+
requestedAt,
|
|
6061
6212
|
value
|
|
6062
6213
|
});
|
|
6063
6214
|
}
|
|
@@ -6104,7 +6255,7 @@ var YieldseekerAgent = class {
|
|
|
6104
6255
|
`/users/${user.userId}/agents/${agent.agentId}/wallet`
|
|
6105
6256
|
).then((walletResponse) => {
|
|
6106
6257
|
this.assertSession(generation, chainId, asset);
|
|
6107
|
-
if (!walletResponse?.agentWallet || !(0,
|
|
6258
|
+
if (!walletResponse?.agentWallet || !(0, import_viem12.isAddress)(walletResponse.agentWallet.walletAddress)) {
|
|
6108
6259
|
throw this.invalidResponse("agent wallet");
|
|
6109
6260
|
}
|
|
6110
6261
|
const context = {
|
|
@@ -6134,7 +6285,7 @@ var YieldseekerAgent = class {
|
|
|
6134
6285
|
this.users.set(key2, persisted);
|
|
6135
6286
|
return persisted;
|
|
6136
6287
|
}
|
|
6137
|
-
const walletAddress = (0,
|
|
6288
|
+
const walletAddress = (0, import_viem12.getAddress)(state.walletAddress);
|
|
6138
6289
|
const generation = this.readGeneration;
|
|
6139
6290
|
let user = null;
|
|
6140
6291
|
try {
|
|
@@ -6426,6 +6577,7 @@ var YieldseekerAgent = class {
|
|
|
6426
6577
|
...context,
|
|
6427
6578
|
snapshot: snapshot.agentSnapshot,
|
|
6428
6579
|
fetchedAt: this.readCache.get(`snapshot:${contextKey}`)?.fetchedAt,
|
|
6580
|
+
requestedAt: this.readCache.get(`snapshot:${contextKey}`)?.requestedAt,
|
|
6429
6581
|
readVersion: version,
|
|
6430
6582
|
positionsUnavailable,
|
|
6431
6583
|
...portfolioParts
|
|
@@ -6517,7 +6669,7 @@ var YieldseekerAgent = class {
|
|
|
6517
6669
|
this.agentPath(context, "deploy"),
|
|
6518
6670
|
{ method: "POST", body: {} }
|
|
6519
6671
|
);
|
|
6520
|
-
if (!deployed?.agentWallet || !(0,
|
|
6672
|
+
if (!deployed?.agentWallet || !(0, import_viem12.isAddress)(deployed.agentWallet.walletAddress) || deployed.agentWallet.walletAddress.toLowerCase() !== walletAddress) {
|
|
6521
6673
|
throw this.invalidResponse("agent deployment", {
|
|
6522
6674
|
reason: "Deploy did not return the expected Agent Wallet."
|
|
6523
6675
|
});
|
|
@@ -6625,15 +6777,15 @@ var YieldseekerAgent = class {
|
|
|
6625
6777
|
return hash2;
|
|
6626
6778
|
}
|
|
6627
6779
|
this.assertTransaction(transaction, state, chainId);
|
|
6628
|
-
const account = (0,
|
|
6629
|
-
const walletClient = (0,
|
|
6780
|
+
const account = (0, import_viem12.getAddress)(state.walletAddress);
|
|
6781
|
+
const walletClient = (0, import_viem12.createWalletClient)({
|
|
6630
6782
|
account,
|
|
6631
6783
|
chain: import_chains4.base,
|
|
6632
|
-
transport: (0,
|
|
6784
|
+
transport: (0, import_viem12.custom)(state.provider)
|
|
6633
6785
|
});
|
|
6634
|
-
const walletChainClient = (0,
|
|
6786
|
+
const walletChainClient = (0, import_viem12.createPublicClient)({
|
|
6635
6787
|
chain: import_chains4.base,
|
|
6636
|
-
transport: (0,
|
|
6788
|
+
transport: (0, import_viem12.custom)(state.provider)
|
|
6637
6789
|
});
|
|
6638
6790
|
await ensureWalletOnChain(
|
|
6639
6791
|
walletChainClient,
|
|
@@ -6643,7 +6795,7 @@ var YieldseekerAgent = class {
|
|
|
6643
6795
|
const hash = await walletClient.sendTransaction({
|
|
6644
6796
|
account,
|
|
6645
6797
|
chain: import_chains4.base,
|
|
6646
|
-
to: (0,
|
|
6798
|
+
to: (0, import_viem12.getAddress)(transaction.to),
|
|
6647
6799
|
data: transaction.data,
|
|
6648
6800
|
value: BigInt(transaction.value)
|
|
6649
6801
|
});
|
|
@@ -6747,12 +6899,12 @@ var YieldseekerAgent = class {
|
|
|
6747
6899
|
return receipt;
|
|
6748
6900
|
}
|
|
6749
6901
|
assertTransaction(transaction, state, chainId) {
|
|
6750
|
-
if (!transaction || typeof transaction.from !== "string" || !(0,
|
|
6902
|
+
if (!transaction || typeof transaction.from !== "string" || !(0, import_viem12.isAddress)(transaction.from) || typeof transaction.to !== "string" || !(0, import_viem12.isAddress)(transaction.to) || typeof transaction.data !== "string" || !/^0x[a-fA-F0-9]*$/.test(transaction.data) || typeof transaction.value !== "string" || !/^[0-9]+$/.test(transaction.value) || transaction.chainId !== chainId || (0, import_viem12.getAddress)(transaction.from) !== (0, import_viem12.getAddress)(state.walletAddress)) {
|
|
6751
6903
|
throw this.invalidResponse("transaction");
|
|
6752
6904
|
}
|
|
6753
6905
|
}
|
|
6754
6906
|
assertAgent(agent) {
|
|
6755
|
-
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0,
|
|
6907
|
+
if (typeof agent.agentId !== "string" || typeof agent.assetAddress !== "string" || !(0, import_viem12.isAddress)(agent.assetAddress) || agent.chainId !== 8453) {
|
|
6756
6908
|
throw this.invalidResponse("agent");
|
|
6757
6909
|
}
|
|
6758
6910
|
}
|
|
@@ -6906,7 +7058,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
|
|
|
6906
7058
|
}
|
|
6907
7059
|
|
|
6908
7060
|
// src/lib/helpers/withdraw-helper.ts
|
|
6909
|
-
var
|
|
7061
|
+
var import_viem13 = require("viem");
|
|
6910
7062
|
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
6911
7063
|
const target = asset.toUpperCase();
|
|
6912
7064
|
return agents.map((agent) => {
|
|
@@ -6914,7 +7066,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
6914
7066
|
const tokenBalance = agentBalance?.tokens.find(
|
|
6915
7067
|
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
6916
7068
|
);
|
|
6917
|
-
let balance = tokenBalance ? (0,
|
|
7069
|
+
let balance = tokenBalance ? (0, import_viem13.parseUnits)(tokenBalance.amount, decimals) : 0n;
|
|
6918
7070
|
if (agent.balanceComposition === "tokens-plus-positions") {
|
|
6919
7071
|
const chainNameById = {
|
|
6920
7072
|
1: "ETHEREUM",
|
|
@@ -6926,14 +7078,14 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
6926
7078
|
const positionChain = position2.chain.trim().toUpperCase();
|
|
6927
7079
|
const matchesChain = positionChain === String(chainId) || targetChain !== void 0 && positionChain === targetChain;
|
|
6928
7080
|
if (!matchesChain || position2.asset.toUpperCase() !== target) continue;
|
|
6929
|
-
balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : (0,
|
|
7081
|
+
balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : (0, import_viem13.parseUnits)(position2.amount, decimals);
|
|
6930
7082
|
}
|
|
6931
7083
|
}
|
|
6932
7084
|
const assetTotal = agentBalance?.assetBalances?.find(
|
|
6933
7085
|
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
6934
7086
|
);
|
|
6935
7087
|
if (assetTotal) {
|
|
6936
|
-
const total = (0,
|
|
7088
|
+
const total = (0, import_viem13.parseUnits)(assetTotal.amount, decimals);
|
|
6937
7089
|
if (total < balance) balance = total > 0n ? total : 0n;
|
|
6938
7090
|
}
|
|
6939
7091
|
return { agent, balance };
|
|
@@ -7092,14 +7244,14 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
7092
7244
|
}
|
|
7093
7245
|
|
|
7094
7246
|
// src/client.ts
|
|
7095
|
-
var
|
|
7247
|
+
var import_viem17 = require("viem");
|
|
7096
7248
|
var import_chains5 = require("viem/chains");
|
|
7097
7249
|
|
|
7098
7250
|
// src/lib/sponsored-token-batch.ts
|
|
7099
|
-
var
|
|
7251
|
+
var import_viem15 = require("viem");
|
|
7100
7252
|
|
|
7101
7253
|
// src/lib/permit2-batch.ts
|
|
7102
|
-
var
|
|
7254
|
+
var import_viem14 = require("viem");
|
|
7103
7255
|
var BATCH_PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
7104
7256
|
var BASE_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
7105
7257
|
var ERC2612_PERMIT_TYPES = {
|
|
@@ -7111,7 +7263,7 @@ var ERC2612_PERMIT_TYPES = {
|
|
|
7111
7263
|
{ name: "deadline", type: "uint256" }
|
|
7112
7264
|
]
|
|
7113
7265
|
};
|
|
7114
|
-
var ERC2612_READ_ABI = (0,
|
|
7266
|
+
var ERC2612_READ_ABI = (0, import_viem14.parseAbi)([
|
|
7115
7267
|
"function name() view returns (string)",
|
|
7116
7268
|
"function version() view returns (string)",
|
|
7117
7269
|
"function nonces(address owner) view returns (uint256)"
|
|
@@ -7149,7 +7301,7 @@ var PERMIT_BATCH_TYPES = {
|
|
|
7149
7301
|
{ name: "amount", type: "uint256" }
|
|
7150
7302
|
]
|
|
7151
7303
|
};
|
|
7152
|
-
var PERMIT2_BATCH_ABI = (0,
|
|
7304
|
+
var PERMIT2_BATCH_ABI = (0, import_viem14.parseAbi)([
|
|
7153
7305
|
"struct TokenPermissions { address token; uint256 amount; }",
|
|
7154
7306
|
"struct PermitBatchTransferFrom { TokenPermissions[] permitted; uint256 nonce; uint256 deadline; }",
|
|
7155
7307
|
"struct SignatureTransferDetails { address to; uint256 requestedAmount; }",
|
|
@@ -7192,14 +7344,14 @@ var planOf = (transfers) => JSON.stringify(
|
|
|
7192
7344
|
amount: BigInt(t.amount).toString()
|
|
7193
7345
|
}))
|
|
7194
7346
|
);
|
|
7195
|
-
var pendingKey = (i) => `owney.token-batch.v1:${(0,
|
|
7347
|
+
var pendingKey = (i) => `owney.token-batch.v1:${(0, import_viem15.keccak256)((0, import_viem15.toBytes)(i.apiKey))}:${i.baseUrl ?? "default"}:${i.chainId}:${i.owner.toLowerCase()}:${i.token.toLowerCase()}`;
|
|
7196
7348
|
function pendingTokenBatch(i) {
|
|
7197
7349
|
try {
|
|
7198
7350
|
const saved = read(pendingKey(i));
|
|
7199
7351
|
if (!saved) return;
|
|
7200
7352
|
const body = JSON.parse(saved);
|
|
7201
|
-
if (!body.serializedTransaction || body.chainId !== i.chainId || !(0,
|
|
7202
|
-
return { txHash: (0,
|
|
7353
|
+
if (!body.serializedTransaction || body.chainId !== i.chainId || !(0, import_viem15.isAddressEqual)(body.from, i.owner) || !(0, import_viem15.isAddressEqual)(body.token, i.token) || !body.transfers?.length) return;
|
|
7354
|
+
return { txHash: (0, import_viem15.keccak256)(body.serializedTransaction), transfers: body.transfers.map(({ to, amount }) => ({ to, amount })) };
|
|
7203
7355
|
} catch {
|
|
7204
7356
|
return;
|
|
7205
7357
|
}
|
|
@@ -7244,14 +7396,47 @@ async function execute(i, key2, plan) {
|
|
|
7244
7396
|
const send = async (initial) => {
|
|
7245
7397
|
let body = initial;
|
|
7246
7398
|
save(key2, body);
|
|
7399
|
+
const rejectedPreparation = (error) => !body.serializedTransaction && error instanceof OwneyError && typeof error.details?.statusCode === "number" && error.details.statusCode >= 400 && error.details.statusCode < 500 && ![408, 429].includes(error.details.statusCode);
|
|
7247
7400
|
try {
|
|
7401
|
+
const post = () => postSponsorBatchTransfer({ apiKey: i.apiKey, baseUrl: i.baseUrl, body });
|
|
7402
|
+
const pendingError = (phase, txHash) => new OwneyError(
|
|
7403
|
+
"DEPOSIT_IN_PROGRESS",
|
|
7404
|
+
phase === "approval" ? "Deposit approval is awaiting confirmation. Retry the same amount to continue it." : "Deposit is awaiting confirmation. Its transaction is still being checked.",
|
|
7405
|
+
{ sponsorPending: true, phase, txHash, safeToFallback: false }
|
|
7406
|
+
);
|
|
7407
|
+
const assertReceipt = (receipt, phase) => {
|
|
7408
|
+
if (receipt.status !== "success") throw new OwneyError(
|
|
7409
|
+
"SPONSOR_REQUEST_FAILED",
|
|
7410
|
+
`Sponsored ${phase} transaction reverted. Please retry.`,
|
|
7411
|
+
{ notSubmitted: true, safeToFallback: false }
|
|
7412
|
+
);
|
|
7413
|
+
};
|
|
7414
|
+
const waitForConfirmation = async (phase, hash2) => {
|
|
7415
|
+
let receipt;
|
|
7416
|
+
try {
|
|
7417
|
+
receipt = await i.pub.waitForTransactionReceipt({ hash: hash2, confirmations: 1, timeout: 9e4, checkReplacement: false });
|
|
7418
|
+
} catch {
|
|
7419
|
+
receipt = await i.pub.getTransactionReceipt({ hash: hash2 }).catch(() => void 0);
|
|
7420
|
+
}
|
|
7421
|
+
if (!receipt) throw pendingError(phase, hash2);
|
|
7422
|
+
assertReceipt(receipt, phase);
|
|
7423
|
+
};
|
|
7424
|
+
const postSigned = async (phase, hash2) => {
|
|
7425
|
+
try {
|
|
7426
|
+
return await post();
|
|
7427
|
+
} catch (error) {
|
|
7428
|
+
if (rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true) throw error;
|
|
7429
|
+
await waitForConfirmation(phase, hash2);
|
|
7430
|
+
return void 0;
|
|
7431
|
+
}
|
|
7432
|
+
};
|
|
7248
7433
|
if (body.erc2612Permit && !body.serializedPermitTransaction) {
|
|
7249
7434
|
const preparedPermit = await postSponsorBatchTransfer({
|
|
7250
7435
|
apiKey: i.apiKey,
|
|
7251
7436
|
baseUrl: i.baseUrl,
|
|
7252
7437
|
body
|
|
7253
7438
|
});
|
|
7254
|
-
if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0,
|
|
7439
|
+
if (!preparedPermit.serializedPermitTransaction || !preparedPermit.permitTxHash || (0, import_viem15.keccak256)(preparedPermit.serializedPermitTransaction) !== preparedPermit.permitTxHash)
|
|
7255
7440
|
throw new Error(
|
|
7256
7441
|
"Sponsorship API did not return a valid prepared permit transaction."
|
|
7257
7442
|
);
|
|
@@ -7262,12 +7447,18 @@ async function execute(i, key2, plan) {
|
|
|
7262
7447
|
save(key2, body);
|
|
7263
7448
|
}
|
|
7264
7449
|
if (!body.serializedTransaction) {
|
|
7265
|
-
const
|
|
7266
|
-
|
|
7267
|
-
|
|
7268
|
-
|
|
7269
|
-
|
|
7270
|
-
|
|
7450
|
+
const permitHash = body.serializedPermitTransaction ? (0, import_viem15.keccak256)(body.serializedPermitTransaction) : void 0;
|
|
7451
|
+
let prepared = permitHash ? await postSigned("approval", permitHash) : await post();
|
|
7452
|
+
if (prepared?.status === "pending") {
|
|
7453
|
+
if (!permitHash || prepared.phase !== "approval" || prepared.txHash !== permitHash)
|
|
7454
|
+
throw new Error("Sponsorship approval does not match the pending transaction.");
|
|
7455
|
+
await waitForConfirmation("approval", permitHash);
|
|
7456
|
+
prepared = void 0;
|
|
7457
|
+
}
|
|
7458
|
+
if (!prepared) prepared = await post();
|
|
7459
|
+
if (prepared.status === "pending" && permitHash && prepared.phase === "approval" && prepared.txHash === permitHash)
|
|
7460
|
+
throw pendingError("approval", permitHash);
|
|
7461
|
+
if (!prepared.serializedTransaction || (0, import_viem15.keccak256)(prepared.serializedTransaction) !== prepared.txHash)
|
|
7271
7462
|
throw new Error(
|
|
7272
7463
|
"Sponsorship API did not return a valid prepared transaction."
|
|
7273
7464
|
);
|
|
@@ -7278,22 +7469,33 @@ async function execute(i, key2, plan) {
|
|
|
7278
7469
|
save(key2, body);
|
|
7279
7470
|
}
|
|
7280
7471
|
try {
|
|
7281
|
-
i.onSubmitted?.((0,
|
|
7472
|
+
i.onSubmitted?.((0, import_viem15.keccak256)(body.serializedTransaction));
|
|
7282
7473
|
} catch {
|
|
7283
7474
|
}
|
|
7284
|
-
const
|
|
7285
|
-
|
|
7286
|
-
|
|
7287
|
-
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7475
|
+
const hash = (0, import_viem15.keccak256)(body.serializedTransaction);
|
|
7476
|
+
const existing = await i.pub.getTransactionReceipt({ hash }).catch(() => void 0);
|
|
7477
|
+
if (existing) {
|
|
7478
|
+
assertReceipt(existing, "deposit");
|
|
7479
|
+
void post().catch(() => void 0);
|
|
7480
|
+
clear(key2);
|
|
7481
|
+
return hash;
|
|
7482
|
+
}
|
|
7483
|
+
let result = await postSigned("deposit", hash);
|
|
7484
|
+
if (result?.status === "pending" && result.phase === "approval" && body.serializedPermitTransaction && result.txHash === (0, import_viem15.keccak256)(body.serializedPermitTransaction)) {
|
|
7485
|
+
await waitForConfirmation("approval", result.txHash);
|
|
7486
|
+
result = await postSigned("deposit", hash);
|
|
7487
|
+
if (result?.status === "pending" && result.phase === "approval" && result.txHash === (0, import_viem15.keccak256)(body.serializedPermitTransaction)) throw pendingError("approval", result.txHash);
|
|
7488
|
+
}
|
|
7489
|
+
if (result) {
|
|
7490
|
+
if (result.txHash !== hash || result.status === "pending" && result.phase !== "deposit")
|
|
7491
|
+
throw new Error("Sponsorship receipt does not match the pending transaction.");
|
|
7492
|
+
if (result.status === "pending") await waitForConfirmation("deposit", hash);
|
|
7493
|
+
}
|
|
7494
|
+
if (!result || result.status === "pending") void post().catch(() => void 0);
|
|
7293
7495
|
clear(key2);
|
|
7294
|
-
return
|
|
7496
|
+
return hash;
|
|
7295
7497
|
} catch (error) {
|
|
7296
|
-
if (!body.serializedTransaction || error instanceof OwneyError && error.details?.notSubmitted === true)
|
|
7498
|
+
if (!body.serializedTransaction && !body.serializedPermitTransaction || rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true)
|
|
7297
7499
|
clear(key2);
|
|
7298
7500
|
throw error;
|
|
7299
7501
|
}
|
|
@@ -7303,7 +7505,7 @@ async function execute(i, key2, plan) {
|
|
|
7303
7505
|
throw new OwneyError("DEPOSIT_IN_PROGRESS", "The saved deposit changed. Check its status before depositing again.");
|
|
7304
7506
|
if (saved) {
|
|
7305
7507
|
const previous = JSON.parse(saved);
|
|
7306
|
-
if (previous.chainId !== i.chainId || !(0,
|
|
7508
|
+
if (previous.chainId !== i.chainId || !(0, import_viem15.isAddressEqual)(previous.from, i.owner) || !(0, import_viem15.isAddressEqual)(previous.token, i.token) || planOf(previous.transfers) !== plan)
|
|
7307
7509
|
throw new Error(
|
|
7308
7510
|
"Retry the previous token deposit and agent split first to reconcile its status."
|
|
7309
7511
|
);
|
|
@@ -7320,7 +7522,7 @@ async function execute(i, key2, plan) {
|
|
|
7320
7522
|
"DEPOSIT_INSUFFICIENT_BALANCE",
|
|
7321
7523
|
"Insufficient token balance for this deposit."
|
|
7322
7524
|
);
|
|
7323
|
-
if (allowance < total && (i.chainId !== 8453 || !(0,
|
|
7525
|
+
if (allowance < total && (i.chainId !== 8453 || !(0, import_viem15.isAddressEqual)(i.token, BASE_USDC_ADDRESS)))
|
|
7324
7526
|
throw new OwneyError(
|
|
7325
7527
|
"PERMIT2_APPROVAL_REQUIRED",
|
|
7326
7528
|
"token deposits need a one-time Permit2 approval."
|
|
@@ -7499,7 +7701,7 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
|
|
|
7499
7701
|
}
|
|
7500
7702
|
|
|
7501
7703
|
// src/lib/sponsored-calls-deposit.ts
|
|
7502
|
-
var
|
|
7704
|
+
var import_viem16 = require("viem");
|
|
7503
7705
|
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
7504
7706
|
var DEFAULT_MAX_POLLS = 30;
|
|
7505
7707
|
async function paymasterSupported(provider, owner, chainId) {
|
|
@@ -7507,7 +7709,7 @@ async function paymasterSupported(provider, owner, chainId) {
|
|
|
7507
7709
|
method: "wallet_getCapabilities",
|
|
7508
7710
|
params: [owner]
|
|
7509
7711
|
});
|
|
7510
|
-
const forChain = caps?.[(0,
|
|
7712
|
+
const forChain = caps?.[(0, import_viem16.toHex)(chainId)] ?? caps?.[String(chainId)];
|
|
7511
7713
|
return Boolean(forChain?.paymasterService?.supported);
|
|
7512
7714
|
}
|
|
7513
7715
|
function makeSponsoredCallsCallback(deps) {
|
|
@@ -7544,8 +7746,8 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
7544
7746
|
const calls = transfers.map((transfer) => ({
|
|
7545
7747
|
to: token,
|
|
7546
7748
|
value: "0x0",
|
|
7547
|
-
data: (0,
|
|
7548
|
-
abi:
|
|
7749
|
+
data: (0, import_viem16.encodeFunctionData)({
|
|
7750
|
+
abi: import_viem16.erc20Abi,
|
|
7549
7751
|
functionName: "transfer",
|
|
7550
7752
|
args: [transfer.to, BigInt(transfer.amount)]
|
|
7551
7753
|
})
|
|
@@ -7577,7 +7779,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
7577
7779
|
url.searchParams.append("owneyIntent", intent);
|
|
7578
7780
|
paymasterUrl = url.toString();
|
|
7579
7781
|
}
|
|
7580
|
-
const requestedId = (0,
|
|
7782
|
+
const requestedId = (0, import_viem16.toHex)(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
7581
7783
|
const progress = (id, transfer) => {
|
|
7582
7784
|
try {
|
|
7583
7785
|
deps.onCallsProgress?.(id, transfers, transfer);
|
|
@@ -7594,7 +7796,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
7594
7796
|
version: "2.0.0",
|
|
7595
7797
|
id: requestedId,
|
|
7596
7798
|
from: deps.ownerAddress,
|
|
7597
|
-
chainId: (0,
|
|
7799
|
+
chainId: (0, import_viem16.toHex)(chainId),
|
|
7598
7800
|
atomicRequired: transfers.length > 1,
|
|
7599
7801
|
calls,
|
|
7600
7802
|
capabilities: {
|
|
@@ -7746,6 +7948,7 @@ var OwneySDK = class {
|
|
|
7746
7948
|
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
7747
7949
|
agentReads = new AgentReads();
|
|
7748
7950
|
recoveredFundingReads = /* @__PURE__ */ new Set();
|
|
7951
|
+
fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
|
|
7749
7952
|
activationChecks = /* @__PURE__ */ new Map();
|
|
7750
7953
|
readAgent(agent, method, fetch2, params = null) {
|
|
7751
7954
|
const key2 = JSON.stringify([
|
|
@@ -7791,6 +7994,7 @@ var OwneySDK = class {
|
|
|
7791
7994
|
}
|
|
7792
7995
|
this.agentReads.clearInFlight();
|
|
7793
7996
|
this.activationChecks.clear();
|
|
7997
|
+
this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
|
|
7794
7998
|
this.state = { provider, walletAddress, chainId: null };
|
|
7795
7999
|
this.cachedSponsoredCallback = null;
|
|
7796
8000
|
this.cachedWethSponsoredCallback = null;
|
|
@@ -7802,6 +8006,7 @@ var OwneySDK = class {
|
|
|
7802
8006
|
*/
|
|
7803
8007
|
async disconnect() {
|
|
7804
8008
|
this.state = null;
|
|
8009
|
+
this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
|
|
7805
8010
|
for (const agent of this.agents.values()) {
|
|
7806
8011
|
await agent.disconnect();
|
|
7807
8012
|
}
|
|
@@ -7876,14 +8081,14 @@ var OwneySDK = class {
|
|
|
7876
8081
|
// PublicClient/WalletClient param types — structurally identical at
|
|
7877
8082
|
// runtime, but the two share a name TS treats as unrelated.
|
|
7878
8083
|
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
7879
|
-
getWalletChainClient: (cid) => (0,
|
|
8084
|
+
getWalletChainClient: (cid) => (0, import_viem17.createPublicClient)({
|
|
7880
8085
|
chain: VIEM_CHAIN2[cid],
|
|
7881
|
-
transport: (0,
|
|
8086
|
+
transport: (0, import_viem17.custom)(provider)
|
|
7882
8087
|
}),
|
|
7883
|
-
getWalletClient: (cid) => (0,
|
|
8088
|
+
getWalletClient: (cid) => (0, import_viem17.createWalletClient)({
|
|
7884
8089
|
account: owner,
|
|
7885
8090
|
chain: VIEM_CHAIN2[cid],
|
|
7886
|
-
transport: (0,
|
|
8091
|
+
transport: (0, import_viem17.custom)(provider)
|
|
7887
8092
|
})
|
|
7888
8093
|
});
|
|
7889
8094
|
if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedSponsoredCallback = callback;
|
|
@@ -7931,14 +8136,14 @@ var OwneySDK = class {
|
|
|
7931
8136
|
// PublicClient/WalletClient param types — structurally identical at
|
|
7932
8137
|
// runtime, but the two share a name TS treats as unrelated.
|
|
7933
8138
|
getPublicClient: (cid) => this.getPaidRpcClient(cid),
|
|
7934
|
-
getWalletChainClient: (cid) => (0,
|
|
8139
|
+
getWalletChainClient: (cid) => (0, import_viem17.createPublicClient)({
|
|
7935
8140
|
chain: VIEM_CHAIN2[cid],
|
|
7936
|
-
transport: (0,
|
|
8141
|
+
transport: (0, import_viem17.custom)(provider)
|
|
7937
8142
|
}),
|
|
7938
|
-
getWalletClient: (cid) => (0,
|
|
8143
|
+
getWalletClient: (cid) => (0, import_viem17.createWalletClient)({
|
|
7939
8144
|
account: owner,
|
|
7940
8145
|
chain: VIEM_CHAIN2[cid],
|
|
7941
|
-
transport: (0,
|
|
8146
|
+
transport: (0, import_viem17.custom)(provider)
|
|
7942
8147
|
})
|
|
7943
8148
|
});
|
|
7944
8149
|
if (!onApproved && !onSubmitted && !resumeTxHash) this.cachedWethSponsoredCallback = callback;
|
|
@@ -8702,9 +8907,8 @@ var OwneySDK = class {
|
|
|
8702
8907
|
verified = inspectFundingReceipt(receipt, { ...evidence, agentWallet, intendedAmount: "MAX" }, token.address, direction);
|
|
8703
8908
|
}
|
|
8704
8909
|
const key2 = `${state.walletAddress.toLowerCase()}:${chainId}:${evidence.agentId}:${evidence.token}:${evidence.txHash}`;
|
|
8705
|
-
if ((verified.transfer === "confirmed" || verified.transfer === "failed" && verified.confirmedAmount === "0") && !this.recoveredFundingReads.has(key2)) {
|
|
8706
|
-
|
|
8707
|
-
agent.invalidateFundingRead?.(state, chainId, evidence.token, options.balanceRefreshUntil);
|
|
8910
|
+
if (options.refreshBalance !== false && (verified.transfer === "confirmed" || verified.transfer === "failed" && verified.confirmedAmount === "0") && !this.recoveredFundingReads.has(key2)) {
|
|
8911
|
+
agent.invalidateFundingRead?.(state, chainId, evidence.token, options.balanceRefreshUntil);
|
|
8708
8912
|
this.recoveredFundingReads.add(key2);
|
|
8709
8913
|
if (this.recoveredFundingReads.size > 256) this.recoveredFundingReads.delete(this.recoveredFundingReads.values().next().value);
|
|
8710
8914
|
}
|
|
@@ -8812,6 +9016,44 @@ var OwneySDK = class {
|
|
|
8812
9016
|
assertCurrent();
|
|
8813
9017
|
return true;
|
|
8814
9018
|
}
|
|
9019
|
+
/** Optional post-payout display proof; receipt verification and the provider
|
|
9020
|
+
* adapter must agree before attaching it to this exact balance object. */
|
|
9021
|
+
async verifyWithdrawalBalance(evidence, balance) {
|
|
9022
|
+
const { state, chainId, assertCurrent } = this.captureReadScope(evidence.chainId);
|
|
9023
|
+
const agent = this.getAgent(evidence.agentId);
|
|
9024
|
+
if (!agent.verifyWithdrawalBalance || !evidence.txHash || state.walletAddress.toLowerCase() !== evidence.walletAddress.toLowerCase()) return balance;
|
|
9025
|
+
const key2 = `${state.walletAddress.toLowerCase()}:${chainId}:${evidence.agentId}:${evidence.token}:${evidence.txHash}:${evidence.intendedAmount}`;
|
|
9026
|
+
const checks = this.fundingBalanceChecks.get(balance) ?? /* @__PURE__ */ new Map();
|
|
9027
|
+
this.fundingBalanceChecks.set(balance, checks);
|
|
9028
|
+
const previous = checks.get(key2);
|
|
9029
|
+
if (previous) {
|
|
9030
|
+
const result2 = await previous;
|
|
9031
|
+
assertCurrent();
|
|
9032
|
+
return result2;
|
|
9033
|
+
}
|
|
9034
|
+
let timer;
|
|
9035
|
+
const read2 = async () => {
|
|
9036
|
+
const verified = await this.inspectFunding(evidence, "withdraw", { refreshBalance: false });
|
|
9037
|
+
assertCurrent();
|
|
9038
|
+
if (verified.transfer !== "confirmed" || verified.delivery !== "confirmed" || !verified.blockNumber) return balance;
|
|
9039
|
+
const metadata = await agent.verifyWithdrawalBalance(state, verified, balance);
|
|
9040
|
+
assertCurrent();
|
|
9041
|
+
if (!metadata || metadata.chainId !== chainId || metadata.asset.toUpperCase() !== evidence.token || !metadata.withdrawalCheck || metadata.withdrawalCheck.txHash.toLowerCase() !== verified.txHash?.toLowerCase() || BigInt(metadata.withdrawalCheck.blockNumber) < BigInt(verified.blockNumber)) return balance;
|
|
9042
|
+
return { ...balance, readMetadata: [
|
|
9043
|
+
...(balance.readMetadata ?? []).filter((item) => !(item.chainId === chainId && item.asset.toUpperCase() === evidence.token)),
|
|
9044
|
+
metadata
|
|
9045
|
+
] };
|
|
9046
|
+
};
|
|
9047
|
+
const pending = Promise.race([read2(), new Promise((resolve) => {
|
|
9048
|
+
timer = setTimeout(() => resolve(balance), 2e3);
|
|
9049
|
+
})]).catch(() => balance).finally(() => {
|
|
9050
|
+
if (timer) clearTimeout(timer);
|
|
9051
|
+
});
|
|
9052
|
+
checks.set(key2, pending);
|
|
9053
|
+
const result = await pending;
|
|
9054
|
+
assertCurrent();
|
|
9055
|
+
return result;
|
|
9056
|
+
}
|
|
8815
9057
|
/** A display acknowledgement controls polling only; it never confirms a financial outcome. */
|
|
8816
9058
|
endFundingBalanceRefresh(evidence, read2) {
|
|
8817
9059
|
const { state, chainId } = this.captureReadScope(evidence.chainId);
|
|
@@ -9080,7 +9322,7 @@ var OwneySDK = class {
|
|
|
9080
9322
|
if (this.isUserRejectedWithdrawal(originalFailure)) throw originalFailure;
|
|
9081
9323
|
if (entry.balance !== 0n && entry.agent.id !== "yieldseeker") {
|
|
9082
9324
|
const total = aggregated.agentBalances[entry.agent.id]?.assetBalances?.find((value) => value.chainId === chainId && value.asset.toUpperCase() === token);
|
|
9083
|
-
if (!total || (0,
|
|
9325
|
+
if (!total || (0, import_viem17.parseUnits)(total.amount, assetInfo.decimals) <= entry.balance) return;
|
|
9084
9326
|
}
|
|
9085
9327
|
try {
|
|
9086
9328
|
const otherAvailable = indexedAvailable - entry.balance;
|
|
@@ -9684,16 +9926,16 @@ var OwneySDK = class {
|
|
|
9684
9926
|
);
|
|
9685
9927
|
}
|
|
9686
9928
|
const provider = this.requireConnectedProvider();
|
|
9687
|
-
const walletChainClient = (0,
|
|
9929
|
+
const walletChainClient = (0, import_viem17.createPublicClient)({
|
|
9688
9930
|
chain: VIEM_CHAIN2[chainId],
|
|
9689
|
-
transport: (0,
|
|
9931
|
+
transport: (0, import_viem17.custom)(provider)
|
|
9690
9932
|
});
|
|
9691
9933
|
const publicClient = this.getPaidRpcClient(chainId);
|
|
9692
9934
|
const approvalAmount = permit2ApprovalAmount(requiredAmount);
|
|
9693
|
-
const wallet = (0,
|
|
9935
|
+
const wallet = (0, import_viem17.createWalletClient)({
|
|
9694
9936
|
account: state.walletAddress,
|
|
9695
9937
|
chain: VIEM_CHAIN2[chainId],
|
|
9696
|
-
transport: (0,
|
|
9938
|
+
transport: (0, import_viem17.custom)(provider)
|
|
9697
9939
|
});
|
|
9698
9940
|
await ensureWalletOnChain(walletChainClient, wallet, chainId);
|
|
9699
9941
|
const hash = await wallet.writeContract({
|
|
@@ -9855,7 +10097,7 @@ var OwneySDK = class {
|
|
|
9855
10097
|
};
|
|
9856
10098
|
|
|
9857
10099
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
9858
|
-
var
|
|
10100
|
+
var import_viem18 = require("viem");
|
|
9859
10101
|
var import_siwe2 = require("siwe");
|
|
9860
10102
|
var import_sdk2 = require("@zyfai/sdk");
|
|
9861
10103
|
|
|
@@ -9982,7 +10224,7 @@ function buildSIWXConfig(deps) {
|
|
|
9982
10224
|
issuedAt,
|
|
9983
10225
|
toString() {
|
|
9984
10226
|
return new import_siwe2.SiweMessage({
|
|
9985
|
-
address: (0,
|
|
10227
|
+
address: (0, import_viem18.getAddress)(accountAddress),
|
|
9986
10228
|
chainId: numericChainId(chainId),
|
|
9987
10229
|
domain,
|
|
9988
10230
|
uri,
|