@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.js
CHANGED
|
@@ -1543,6 +1543,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1543
1543
|
earningsRefreshes = /* @__PURE__ */ new Map();
|
|
1544
1544
|
earningsSnapshot = null;
|
|
1545
1545
|
earningsGeneration = 0;
|
|
1546
|
+
balanceSnapshots = /* @__PURE__ */ new WeakMap();
|
|
1546
1547
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
1547
1548
|
this.rpcUrls = resolveRpcUrls(rpcUrls);
|
|
1548
1549
|
this.sdk = new ZyfaiSDK({
|
|
@@ -1746,7 +1747,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
1746
1747
|
* chain/account switch fires the provider's `accountsChanged` →
|
|
1747
1748
|
* `disconnectAccount` (nulls walletClient + authenticatedUserId) while our
|
|
1748
1749
|
* own `connectAuth` guard still believes this chain is connected and
|
|
1749
|
-
* early-returns. Without this, authenticated calls (
|
|
1750
|
+
* early-returns. Without this, authenticated calls (sendDeposit,
|
|
1750
1751
|
* withdrawFunds) fail with "No account connected".
|
|
1751
1752
|
*/
|
|
1752
1753
|
async ensureConnected(state, chainId) {
|
|
@@ -2368,7 +2369,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2368
2369
|
return { txHash, smartWallet, amount, evidence: evidence2 };
|
|
2369
2370
|
}
|
|
2370
2371
|
await this.ensureWalletDeployed(this.getAddress(), validChainId);
|
|
2371
|
-
const raw2 = await this.sdk.
|
|
2372
|
+
const raw2 = await this.sdk.sendDeposit(
|
|
2372
2373
|
this.getAddress(),
|
|
2373
2374
|
validChainId,
|
|
2374
2375
|
amount,
|
|
@@ -2384,7 +2385,7 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2384
2385
|
intendedAmount: amount,
|
|
2385
2386
|
txHash: raw2.txHash,
|
|
2386
2387
|
transfer: "unknown",
|
|
2387
|
-
registration: "unknown",
|
|
2388
|
+
registration: raw2.registration ? "confirmed" : "unknown",
|
|
2388
2389
|
delivery: "not-applicable"
|
|
2389
2390
|
};
|
|
2390
2391
|
notifyFunding(onProgress, evidence);
|
|
@@ -2692,10 +2693,37 @@ var ZyfaiAgent = class _ZyfaiAgent {
|
|
|
2692
2693
|
}
|
|
2693
2694
|
async getBalances(state, chainId) {
|
|
2694
2695
|
const requestedAt = Date.now();
|
|
2696
|
+
const generation = this.earningsGeneration;
|
|
2695
2697
|
const { smartWallet, chainId: validChainId } = await this.resolveSmartWallet(state, chainId);
|
|
2696
2698
|
const raw2 = await this.sdk.getPortfolio(this.getAddress());
|
|
2697
2699
|
const balance = mapBalances(raw2, validChainId, smartWallet);
|
|
2698
|
-
|
|
2700
|
+
const reads = balance.readMetadata?.map((read2) => ({ ...read2, requestedAt })) ?? [];
|
|
2701
|
+
for (const asset of SupportedAssets.filter((item) => item.chainId === chainId)) {
|
|
2702
|
+
if (!reads.some((read2) => read2.chainId === chainId && read2.asset === asset.symbol) && hasEmptyWithdrawalSnapshot(raw2, chainId, asset.symbol)) {
|
|
2703
|
+
reads.push({ chainId, asset: asset.symbol, requestedAt, fetchedAt: Date.now(), positionsStatus: "available" });
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
const result = { ...balance, readMetadata: reads };
|
|
2707
|
+
for (const read2 of reads) this.balanceSnapshots.set(read2, { raw: raw2, generation, owner: state.walletAddress.toLowerCase() });
|
|
2708
|
+
return result;
|
|
2709
|
+
}
|
|
2710
|
+
async verifyWithdrawalBalance(state, evidence, balance) {
|
|
2711
|
+
const read2 = balance.readMetadata?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
|
|
2712
|
+
const snapshot = read2 && this.balanceSnapshots.get(read2);
|
|
2713
|
+
const asset = SupportedAssets.find((item) => item.chainId === evidence.chainId && item.symbol === evidence.token);
|
|
2714
|
+
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;
|
|
2715
|
+
const client = this.getPublicClient(evidence.chainId);
|
|
2716
|
+
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
2717
|
+
if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
|
|
2718
|
+
const idle = await client.readContract({
|
|
2719
|
+
address: asset.address,
|
|
2720
|
+
abi: erc20Abi2,
|
|
2721
|
+
functionName: "balanceOf",
|
|
2722
|
+
args: [balance.smartWallet],
|
|
2723
|
+
blockNumber
|
|
2724
|
+
});
|
|
2725
|
+
if (idle !== 0n || snapshot.generation !== this.earningsGeneration || this.connectedAddress?.toLowerCase() !== snapshot.owner || this.connectedChainId !== evidence.chainId) return void 0;
|
|
2726
|
+
return { ...read2, withdrawalCheck: { txHash: evidence.txHash, blockNumber: blockNumber.toString() } };
|
|
2699
2727
|
}
|
|
2700
2728
|
earningsKey(state, chainId, smartWallet) {
|
|
2701
2729
|
return JSON.stringify([
|
|
@@ -2901,10 +2929,11 @@ import {
|
|
|
2901
2929
|
decodeEventLog as decodeEventLog2,
|
|
2902
2930
|
encodeEventTopics,
|
|
2903
2931
|
encodeFunctionData,
|
|
2904
|
-
erc20Abi as
|
|
2905
|
-
erc4626Abi,
|
|
2906
|
-
getAddress as
|
|
2907
|
-
isAddress as isAddress3
|
|
2932
|
+
erc20Abi as erc20Abi4,
|
|
2933
|
+
erc4626Abi as erc4626Abi2,
|
|
2934
|
+
getAddress as getAddress5,
|
|
2935
|
+
isAddress as isAddress3,
|
|
2936
|
+
parseUnits
|
|
2908
2937
|
} from "viem";
|
|
2909
2938
|
import { base as base4 } from "viem/chains";
|
|
2910
2939
|
|
|
@@ -3694,6 +3723,7 @@ function mapYieldseekerBalances(contexts) {
|
|
|
3694
3723
|
chainId: context.agent.chainId,
|
|
3695
3724
|
asset: context.asset,
|
|
3696
3725
|
fetchedAt: context.fetchedAt,
|
|
3726
|
+
requestedAt: context.requestedAt,
|
|
3697
3727
|
readVersion: context.readVersion,
|
|
3698
3728
|
providerUpdatedAt: context.snapshot.updatedDate,
|
|
3699
3729
|
snapshotId: String(context.snapshot.agentWalletSnapshotId),
|
|
@@ -4071,9 +4101,55 @@ function mapYieldseekerAgentApy(options, days) {
|
|
|
4071
4101
|
};
|
|
4072
4102
|
}
|
|
4073
4103
|
|
|
4104
|
+
// src/lib/remaining-vault-balance.ts
|
|
4105
|
+
import { erc20Abi as erc20Abi3, erc4626Abi, getAddress as getAddress2 } from "viem";
|
|
4106
|
+
async function remainingVaultBalance(client, wallet, asset, vaults, blockNumber) {
|
|
4107
|
+
const addresses = [...new Set(vaults.map((value) => value.toLowerCase()))];
|
|
4108
|
+
if (addresses.length > 64) return void 0;
|
|
4109
|
+
const batches = [];
|
|
4110
|
+
for (let index = 0; index < addresses.length; index += 10) batches.push(addresses.slice(index, index + 10));
|
|
4111
|
+
const values = await Promise.all(batches.map(async (batch) => {
|
|
4112
|
+
const balances = await client.multicall({
|
|
4113
|
+
blockNumber,
|
|
4114
|
+
allowFailure: true,
|
|
4115
|
+
contracts: batch.map((address) => ({
|
|
4116
|
+
address: getAddress2(address),
|
|
4117
|
+
abi: erc20Abi3,
|
|
4118
|
+
functionName: "balanceOf",
|
|
4119
|
+
args: [wallet]
|
|
4120
|
+
}))
|
|
4121
|
+
});
|
|
4122
|
+
if (balances.length !== batch.length) return void 0;
|
|
4123
|
+
const funded = [];
|
|
4124
|
+
for (let index = 0; index < batch.length; index++) {
|
|
4125
|
+
const result = balances[index];
|
|
4126
|
+
if (result?.status !== "success" || typeof result.result !== "bigint" || result.result < 0n) return void 0;
|
|
4127
|
+
if (result.result > 0n) funded.push({ address: getAddress2(batch[index]), shares: result.result });
|
|
4128
|
+
}
|
|
4129
|
+
if (!funded.length) return 0n;
|
|
4130
|
+
const valuations = await client.multicall({
|
|
4131
|
+
blockNumber,
|
|
4132
|
+
allowFailure: true,
|
|
4133
|
+
contracts: funded.flatMap(({ address, shares }) => [
|
|
4134
|
+
{ address, abi: erc4626Abi, functionName: "asset" },
|
|
4135
|
+
{ address, abi: erc4626Abi, functionName: "convertToAssets", args: [shares] }
|
|
4136
|
+
])
|
|
4137
|
+
});
|
|
4138
|
+
if (valuations.length !== funded.length * 2) return void 0;
|
|
4139
|
+
let total = 0n;
|
|
4140
|
+
for (let index = 0; index < funded.length; index++) {
|
|
4141
|
+
const underlying = valuations[index * 2], value = valuations[index * 2 + 1];
|
|
4142
|
+
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;
|
|
4143
|
+
total += value.result;
|
|
4144
|
+
}
|
|
4145
|
+
return total;
|
|
4146
|
+
}));
|
|
4147
|
+
return values.some((value) => value === void 0) ? void 0 : values.reduce((sum, value) => sum + value, 0n);
|
|
4148
|
+
}
|
|
4149
|
+
|
|
4074
4150
|
// src/agents/yieldseeker/yieldseeker.wallet-version.ts
|
|
4075
4151
|
import {
|
|
4076
|
-
getAddress as
|
|
4152
|
+
getAddress as getAddress3,
|
|
4077
4153
|
isAddressEqual,
|
|
4078
4154
|
parseAbi as parseAbi3
|
|
4079
4155
|
} from "viem";
|
|
@@ -4097,9 +4173,9 @@ function yieldseekerOwnerPath(code) {
|
|
|
4097
4173
|
return !code || code === "0x" || /^0xef0100[0-9a-f]{40}$/i.test(code) ? "eoa" : "smart";
|
|
4098
4174
|
}
|
|
4099
4175
|
async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNumber) {
|
|
4100
|
-
const agentWallet =
|
|
4101
|
-
const expectedOwner =
|
|
4102
|
-
const expectedAsset =
|
|
4176
|
+
const agentWallet = getAddress3(wallet);
|
|
4177
|
+
const expectedOwner = getAddress3(owner);
|
|
4178
|
+
const expectedAsset = getAddress3(asset);
|
|
4103
4179
|
const [code, ownerCode, slot, actualOwner, index, actualAsset, actualFactory, latest] = await Promise.all([
|
|
4104
4180
|
client.getBytecode({ address: agentWallet, blockNumber }),
|
|
4105
4181
|
client.getBytecode({ address: expectedOwner, blockNumber }),
|
|
@@ -4113,7 +4189,7 @@ async function readYieldseekerWalletStatus(client, wallet, owner, asset, blockNu
|
|
|
4113
4189
|
if (!code || code === "0x" || !slot || /^0x0+$/.test(slot)) {
|
|
4114
4190
|
throw new Error("Yieldseeker wallet is not a deployed ERC1967 proxy");
|
|
4115
4191
|
}
|
|
4116
|
-
const implementation =
|
|
4192
|
+
const implementation = getAddress3(`0x${slot.slice(-40)}`);
|
|
4117
4193
|
const mapped = await client.readContract({
|
|
4118
4194
|
address: YIELDSEEKER_FACTORY,
|
|
4119
4195
|
abi: factoryAbi,
|
|
@@ -4140,7 +4216,7 @@ var YIELDSEEKER_UPGRADE_ABI = walletAbi;
|
|
|
4140
4216
|
import {
|
|
4141
4217
|
createWalletClient as createWalletClient2,
|
|
4142
4218
|
custom as custom2,
|
|
4143
|
-
getAddress as
|
|
4219
|
+
getAddress as getAddress4,
|
|
4144
4220
|
toHex
|
|
4145
4221
|
} from "viem";
|
|
4146
4222
|
import { getUserOperationHash as getUserOperationHash2 } from "viem/account-abstraction";
|
|
@@ -4192,6 +4268,14 @@ function sponsorError(message, safeToFallback, details = {}) {
|
|
|
4192
4268
|
"yieldseeker"
|
|
4193
4269
|
);
|
|
4194
4270
|
}
|
|
4271
|
+
function assertIntentFresh(expiresAt) {
|
|
4272
|
+
if (!Number.isFinite(expiresAt) || Date.now() + 5e3 >= expiresAt * 1e3)
|
|
4273
|
+
throw sponsorError(
|
|
4274
|
+
"The withdrawal sponsorship request expired. Please try again.",
|
|
4275
|
+
true,
|
|
4276
|
+
{ failureCode: "SPONSOR_INTENT_EXPIRED" }
|
|
4277
|
+
);
|
|
4278
|
+
}
|
|
4195
4279
|
function providerReason(value) {
|
|
4196
4280
|
if (typeof value !== "string") return void 0;
|
|
4197
4281
|
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);
|
|
@@ -4480,6 +4564,7 @@ async function submitEoa(input) {
|
|
|
4480
4564
|
}
|
|
4481
4565
|
const userOpHash = operationHash(operation);
|
|
4482
4566
|
await assertOwnerSession(input.state, input.owner);
|
|
4567
|
+
assertIntentFresh(input.expiresAt);
|
|
4483
4568
|
const wallet = createWalletClient2({
|
|
4484
4569
|
account: input.owner,
|
|
4485
4570
|
chain: base3,
|
|
@@ -4488,6 +4573,7 @@ async function submitEoa(input) {
|
|
|
4488
4573
|
const signature = await wallet.signMessage({ message: { raw: userOpHash } });
|
|
4489
4574
|
operation = { ...operation, signature };
|
|
4490
4575
|
await assertOwnerSession(input.state, input.owner);
|
|
4576
|
+
assertIntentFresh(input.expiresAt);
|
|
4491
4577
|
const userOperation = {
|
|
4492
4578
|
sender: operation.sender,
|
|
4493
4579
|
nonce: operation.nonce,
|
|
@@ -4565,6 +4651,7 @@ async function submitSmart(input) {
|
|
|
4565
4651
|
throw sponsorError("This account cannot use a paymaster on Base.", true);
|
|
4566
4652
|
await assertOwnerSession(input.state, input.owner);
|
|
4567
4653
|
let sent;
|
|
4654
|
+
assertIntentFresh(input.expiresAt);
|
|
4568
4655
|
const requestedId = toHex(globalThis.crypto.getRandomValues(new Uint8Array(32)));
|
|
4569
4656
|
savePending(input.onPending, { callsId: requestedId }, true);
|
|
4570
4657
|
await checkpoint(input.onBeforeSubmission, { callsId: requestedId });
|
|
@@ -4649,7 +4736,7 @@ async function submitSmart(input) {
|
|
|
4649
4736
|
);
|
|
4650
4737
|
}
|
|
4651
4738
|
async function submitYieldseekerSponsoredWithdrawal(input) {
|
|
4652
|
-
const owner =
|
|
4739
|
+
const owner = getAddress4(input.state.walletAddress);
|
|
4653
4740
|
const { intent, rpcUrl } = await requestIntent({
|
|
4654
4741
|
apiKey: input.apiKey,
|
|
4655
4742
|
routingApiBaseUrl: input.routingApiBaseUrl,
|
|
@@ -4663,11 +4750,12 @@ async function submitYieldseekerSponsoredWithdrawal(input) {
|
|
|
4663
4750
|
action: "withdraw",
|
|
4664
4751
|
refreshYieldseekerSignature: input.refreshYieldseekerSignature
|
|
4665
4752
|
});
|
|
4666
|
-
|
|
4753
|
+
assertIntentFresh(intent.expiresAt);
|
|
4754
|
+
const args = { ...input, owner, rpcUrl, expiresAt: intent.expiresAt };
|
|
4667
4755
|
return intent.ownerPath === "eoa" ? submitEoa(args) : submitSmart(args);
|
|
4668
4756
|
}
|
|
4669
4757
|
async function submitYieldseekerSponsoredUpgrade(input) {
|
|
4670
|
-
const owner =
|
|
4758
|
+
const owner = getAddress4(input.state.walletAddress);
|
|
4671
4759
|
const { intent, rpcUrl } = await requestIntent({
|
|
4672
4760
|
apiKey: input.apiKey,
|
|
4673
4761
|
routingApiBaseUrl: input.routingApiBaseUrl,
|
|
@@ -4683,7 +4771,8 @@ async function submitYieldseekerSponsoredUpgrade(input) {
|
|
|
4683
4771
|
});
|
|
4684
4772
|
if (intent.ownerPath !== "smart")
|
|
4685
4773
|
throw sponsorError("V1 upgrade sponsorship requires a Base Account owner.", true);
|
|
4686
|
-
|
|
4774
|
+
assertIntentFresh(intent.expiresAt);
|
|
4775
|
+
return submitSmart({ ...input, owner, rpcUrl, expiresAt: intent.expiresAt });
|
|
4687
4776
|
}
|
|
4688
4777
|
|
|
4689
4778
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
@@ -4784,6 +4873,8 @@ var YieldseekerAgent = class {
|
|
|
4784
4873
|
transactionExecutor;
|
|
4785
4874
|
unwindReceiptWaiter;
|
|
4786
4875
|
agentContexts = /* @__PURE__ */ new Map();
|
|
4876
|
+
balanceContexts = /* @__PURE__ */ new WeakMap();
|
|
4877
|
+
balanceVaults = /* @__PURE__ */ new Map();
|
|
4787
4878
|
users = /* @__PURE__ */ new Map();
|
|
4788
4879
|
pendingAgents = /* @__PURE__ */ new Map();
|
|
4789
4880
|
pendingWalletContexts = /* @__PURE__ */ new Map();
|
|
@@ -4829,8 +4920,8 @@ var YieldseekerAgent = class {
|
|
|
4829
4920
|
if (useCachedV2 && cached && Date.now() - cached.at < 15 * 6e4) return { ...cached.status };
|
|
4830
4921
|
const status = await readYieldseekerWalletStatus(
|
|
4831
4922
|
this.getReceiptClient(),
|
|
4832
|
-
|
|
4833
|
-
|
|
4923
|
+
getAddress5(context.wallet.walletAddress),
|
|
4924
|
+
getAddress5(state.walletAddress),
|
|
4834
4925
|
YIELDSEEKER_ASSET_METADATA[asset].address
|
|
4835
4926
|
);
|
|
4836
4927
|
this.rememberWalletStatus(key2, status);
|
|
@@ -5026,7 +5117,7 @@ var YieldseekerAgent = class {
|
|
|
5026
5117
|
}
|
|
5027
5118
|
} else {
|
|
5028
5119
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5029
|
-
from:
|
|
5120
|
+
from: getAddress5(state.walletAddress),
|
|
5030
5121
|
to: before.agentWallet,
|
|
5031
5122
|
data,
|
|
5032
5123
|
value: "0",
|
|
@@ -5049,6 +5140,7 @@ var YieldseekerAgent = class {
|
|
|
5049
5140
|
}
|
|
5050
5141
|
this.users.clear();
|
|
5051
5142
|
this.agentContexts.clear();
|
|
5143
|
+
this.balanceVaults.clear();
|
|
5052
5144
|
this.pendingAgents.clear();
|
|
5053
5145
|
this.pendingWalletContexts.clear();
|
|
5054
5146
|
this.readCache.clear();
|
|
@@ -5112,12 +5204,12 @@ var YieldseekerAgent = class {
|
|
|
5112
5204
|
} else {
|
|
5113
5205
|
try {
|
|
5114
5206
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5115
|
-
from:
|
|
5207
|
+
from: getAddress5(state.walletAddress),
|
|
5116
5208
|
to: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
5117
5209
|
data: encodeFunctionData({
|
|
5118
|
-
abi:
|
|
5210
|
+
abi: erc20Abi4,
|
|
5119
5211
|
functionName: "transfer",
|
|
5120
|
-
args: [
|
|
5212
|
+
args: [getAddress5(context.wallet.walletAddress), BigInt(amount)]
|
|
5121
5213
|
}),
|
|
5122
5214
|
value: "0",
|
|
5123
5215
|
chainId
|
|
@@ -5251,7 +5343,7 @@ var YieldseekerAgent = class {
|
|
|
5251
5343
|
);
|
|
5252
5344
|
const positionsRead = this.readWithdrawalPositions(state, chainId, context);
|
|
5253
5345
|
const metadata = YIELDSEEKER_ASSET_METADATA[asset];
|
|
5254
|
-
const agentWallet =
|
|
5346
|
+
const agentWallet = getAddress5(context.wallet.walletAddress);
|
|
5255
5347
|
const readOwnerFunds = async (blockNumber) => {
|
|
5256
5348
|
const feeTracker = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5257
5349
|
address: agentWallet,
|
|
@@ -5265,13 +5357,13 @@ var YieldseekerAgent = class {
|
|
|
5265
5357
|
const [idle2, fees] = await Promise.all([
|
|
5266
5358
|
withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5267
5359
|
address: metadata.address,
|
|
5268
|
-
abi:
|
|
5360
|
+
abi: erc20Abi4,
|
|
5269
5361
|
functionName: "balanceOf",
|
|
5270
5362
|
args: [agentWallet],
|
|
5271
5363
|
blockNumber
|
|
5272
5364
|
}), chainId, "eth_call", this.id),
|
|
5273
5365
|
withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5274
|
-
address:
|
|
5366
|
+
address: getAddress5(feeTracker),
|
|
5275
5367
|
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
5276
5368
|
functionName: "getFeesOwed",
|
|
5277
5369
|
args: [agentWallet],
|
|
@@ -5313,7 +5405,7 @@ var YieldseekerAgent = class {
|
|
|
5313
5405
|
let active = true;
|
|
5314
5406
|
const checks = this.readVaultLiquidity(values.map((position2) => position2.yieldOption), agentWallet, blockNumber).catch(() => []);
|
|
5315
5407
|
const reads = values.map(async (position2, index) => {
|
|
5316
|
-
const address =
|
|
5408
|
+
const address = getAddress5(position2.yieldOption.address);
|
|
5317
5409
|
try {
|
|
5318
5410
|
const group = (await checks).slice(index * 3, index * 3 + 3);
|
|
5319
5411
|
if (!active || group.length !== 3 || group.some((value) => value.status !== "success")) return null;
|
|
@@ -5327,7 +5419,7 @@ var YieldseekerAgent = class {
|
|
|
5327
5419
|
try {
|
|
5328
5420
|
const value = await this.getReceiptClient().readContract({
|
|
5329
5421
|
address,
|
|
5330
|
-
abi:
|
|
5422
|
+
abi: erc4626Abi2,
|
|
5331
5423
|
functionName,
|
|
5332
5424
|
args: [shares],
|
|
5333
5425
|
blockNumber
|
|
@@ -5540,7 +5632,7 @@ var YieldseekerAgent = class {
|
|
|
5540
5632
|
delta: maxSettlementBasis.delta - payout,
|
|
5541
5633
|
expectedNetDeposits: maxSettlementBasis.expectedNetDeposits - payout
|
|
5542
5634
|
} : this.snapshotMovement(state, chainId, context, -payout);
|
|
5543
|
-
const account =
|
|
5635
|
+
const account = getAddress5(state.walletAddress);
|
|
5544
5636
|
let receipt;
|
|
5545
5637
|
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" };
|
|
5546
5638
|
const data = amount === void 0 ? encodeFunctionData({
|
|
@@ -5563,7 +5655,7 @@ var YieldseekerAgent = class {
|
|
|
5563
5655
|
refreshYieldseekerSignature: (rejected) => this.auth.refreshToken(state, chainId, rejected),
|
|
5564
5656
|
userId: context.user.userId,
|
|
5565
5657
|
agentId: context.agent.agentId,
|
|
5566
|
-
agentWallet:
|
|
5658
|
+
agentWallet: getAddress5(context.wallet.walletAddress),
|
|
5567
5659
|
asset: metadata.address,
|
|
5568
5660
|
callData: data,
|
|
5569
5661
|
onPending: (pending) => notifyFunding(onProgress, { ...base6, ...pending }),
|
|
@@ -5578,7 +5670,7 @@ var YieldseekerAgent = class {
|
|
|
5578
5670
|
onOwnerTransferAttempted?.();
|
|
5579
5671
|
txHash = await this.submitTransaction(state, chainId, {
|
|
5580
5672
|
from: account,
|
|
5581
|
-
to:
|
|
5673
|
+
to: getAddress5(context.wallet.walletAddress),
|
|
5582
5674
|
data,
|
|
5583
5675
|
value: "0",
|
|
5584
5676
|
chainId
|
|
@@ -5686,17 +5778,17 @@ var YieldseekerAgent = class {
|
|
|
5686
5778
|
return proof.available;
|
|
5687
5779
|
}
|
|
5688
5780
|
async readVaultLiquidity(options, wallet, blockNumber) {
|
|
5689
|
-
const owner =
|
|
5781
|
+
const owner = getAddress5(wallet);
|
|
5690
5782
|
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));
|
|
5691
5783
|
const results = await Promise.all(batches.map((batch) => this.getReceiptClient().multicall({
|
|
5692
5784
|
blockNumber,
|
|
5693
5785
|
allowFailure: true,
|
|
5694
5786
|
contracts: batch.flatMap((option) => {
|
|
5695
|
-
const address =
|
|
5787
|
+
const address = getAddress5(option.address);
|
|
5696
5788
|
return [
|
|
5697
|
-
{ address, abi:
|
|
5698
|
-
{ address, abi:
|
|
5699
|
-
{ address, abi:
|
|
5789
|
+
{ address, abi: erc4626Abi2, functionName: "asset" },
|
|
5790
|
+
{ address, abi: erc20Abi4, functionName: "balanceOf", args: [owner] },
|
|
5791
|
+
{ address, abi: erc4626Abi2, functionName: "maxWithdraw", args: [owner] }
|
|
5700
5792
|
];
|
|
5701
5793
|
})
|
|
5702
5794
|
})));
|
|
@@ -5772,7 +5864,7 @@ var YieldseekerAgent = class {
|
|
|
5772
5864
|
const read2 = async () => {
|
|
5773
5865
|
const client = this.getReceiptClient();
|
|
5774
5866
|
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
5775
|
-
const wallet =
|
|
5867
|
+
const wallet = getAddress5(context.wallet.walletAddress);
|
|
5776
5868
|
assertReadCurrent();
|
|
5777
5869
|
if (typeof blockNumber !== "bigint") throw unavailable();
|
|
5778
5870
|
const indexedPositions = this.validateWithdrawalPositions(positions ?? [], chainId, context.asset);
|
|
@@ -5786,7 +5878,7 @@ var YieldseekerAgent = class {
|
|
|
5786
5878
|
this.readVaultLiquidity(options, wallet, blockNumber),
|
|
5787
5879
|
client.readContract({
|
|
5788
5880
|
address: metadata.address,
|
|
5789
|
-
abi:
|
|
5881
|
+
abi: erc20Abi4,
|
|
5790
5882
|
functionName: "balanceOf",
|
|
5791
5883
|
args: [wallet],
|
|
5792
5884
|
blockNumber
|
|
@@ -5801,7 +5893,7 @@ var YieldseekerAgent = class {
|
|
|
5801
5893
|
if (typeof idle !== "bigint" || idle < 0n || !isAddress3(feeTracker) || /^0x0{40}$/i.test(feeTracker)) throw unavailable();
|
|
5802
5894
|
assertReadCurrent();
|
|
5803
5895
|
const fees = await client.readContract({
|
|
5804
|
-
address:
|
|
5896
|
+
address: getAddress5(feeTracker),
|
|
5805
5897
|
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
5806
5898
|
functionName: "getFeesOwed",
|
|
5807
5899
|
args: [wallet],
|
|
@@ -5812,9 +5904,15 @@ var YieldseekerAgent = class {
|
|
|
5812
5904
|
const verifiedVaults = [];
|
|
5813
5905
|
let deployed = 0n;
|
|
5814
5906
|
const collect = (options2, results) => {
|
|
5907
|
+
assertReadCurrent();
|
|
5908
|
+
const known = this.balanceVaults.get(contextKey) ?? /* @__PURE__ */ new Set();
|
|
5909
|
+
this.balanceVaults.set(contextKey, known);
|
|
5815
5910
|
let valid2 = true;
|
|
5816
5911
|
options2.forEach((option, index) => {
|
|
5817
5912
|
const group = results.slice(index * 3, index * 3 + 3);
|
|
5913
|
+
const shareProbe = group[1];
|
|
5914
|
+
if (shareProbe?.status === "success" && typeof shareProbe.result === "bigint" && shareProbe.result > 0n)
|
|
5915
|
+
known.add(option.address.toLowerCase());
|
|
5818
5916
|
if (group.length !== 3 || group.some((value) => value.status !== "success")) {
|
|
5819
5917
|
valid2 = false;
|
|
5820
5918
|
return;
|
|
@@ -5893,7 +5991,59 @@ var YieldseekerAgent = class {
|
|
|
5893
5991
|
async getBalances(state, chainId, asset) {
|
|
5894
5992
|
this.assertChain(chainId);
|
|
5895
5993
|
if (asset !== void 0) this.assertAsset(asset);
|
|
5896
|
-
|
|
5994
|
+
const contexts = await this.loadPortfolio(state, chainId, { asset, allowMissingPositions: true });
|
|
5995
|
+
const balance = mapYieldseekerBalances(contexts);
|
|
5996
|
+
for (const context of contexts) {
|
|
5997
|
+
const read2 = balance.readMetadata.find((item) => item.asset === context.asset);
|
|
5998
|
+
this.balanceContexts.set(read2, { context, generation: this.readGeneration });
|
|
5999
|
+
const key2 = this.contextKey(state, chainId, context.asset);
|
|
6000
|
+
const known = this.balanceVaults.get(key2) ?? /* @__PURE__ */ new Set();
|
|
6001
|
+
for (const position2 of context.positions) known.add(position2.yieldOption.address.toLowerCase());
|
|
6002
|
+
this.balanceVaults.set(key2, known);
|
|
6003
|
+
}
|
|
6004
|
+
return balance;
|
|
6005
|
+
}
|
|
6006
|
+
async verifyWithdrawalBalance(state, evidence, balance) {
|
|
6007
|
+
this.assertAsset(evidence.token);
|
|
6008
|
+
this.assertChain(evidence.chainId);
|
|
6009
|
+
const read2 = balance.readMetadata?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
|
|
6010
|
+
const cached = read2 && this.balanceContexts.get(read2);
|
|
6011
|
+
const context = cached?.generation === this.readGeneration ? cached.context : void 0;
|
|
6012
|
+
if (!context || context.positionsUnavailable || !read2 || !evidence.blockNumber || !evidence.txHash || context.wallet.walletAddress.toLowerCase() !== evidence.agentWallet?.toLowerCase()) return void 0;
|
|
6013
|
+
const key2 = this.contextKey(state, evidence.chainId, evidence.token);
|
|
6014
|
+
const generation = this.readGeneration, version = this.portfolioVersion(key2);
|
|
6015
|
+
if (read2.readVersion !== version) return void 0;
|
|
6016
|
+
const wallet = getAddress5(context.wallet.walletAddress);
|
|
6017
|
+
const asset = YIELDSEEKER_ASSET_METADATA[evidence.token];
|
|
6018
|
+
const client = this.getReceiptClient();
|
|
6019
|
+
const blockNumber = await client.getBlockNumber({ cacheTime: 0 });
|
|
6020
|
+
if (blockNumber < BigInt(evidence.blockNumber)) return void 0;
|
|
6021
|
+
const vaults = [...this.balanceVaults.get(key2) ?? []];
|
|
6022
|
+
const [invested, idle, tracker] = await Promise.all([
|
|
6023
|
+
remainingVaultBalance(client, wallet, asset.address, vaults, blockNumber),
|
|
6024
|
+
client.readContract({ address: asset.address, abi: erc20Abi4, functionName: "balanceOf", args: [wallet], blockNumber }),
|
|
6025
|
+
client.readContract({ address: wallet, abi: YIELDSEEKER_AGENT_WALLET_ABI, functionName: "feeTracker", blockNumber })
|
|
6026
|
+
]);
|
|
6027
|
+
if (invested === void 0 || typeof idle !== "bigint" || idle < 0n || !isAddress3(tracker) || /^0x0{40}$/i.test(tracker)) return void 0;
|
|
6028
|
+
const fees = await client.readContract({
|
|
6029
|
+
address: tracker,
|
|
6030
|
+
abi: YIELDSEEKER_FEE_TRACKER_ABI,
|
|
6031
|
+
functionName: "getFeesOwed",
|
|
6032
|
+
args: [wallet],
|
|
6033
|
+
blockNumber
|
|
6034
|
+
});
|
|
6035
|
+
this.assertSession(generation, evidence.chainId, evidence.token);
|
|
6036
|
+
if (version !== this.portfolioVersion(key2) || typeof fees !== "bigint" || fees < 0n) return void 0;
|
|
6037
|
+
const total = idle + invested > fees ? idle + invested - fees : 0n;
|
|
6038
|
+
const displayed = balance.assetBalances?.find((item) => item.chainId === evidence.chainId && item.asset === evidence.token);
|
|
6039
|
+
if (!displayed || !evidence.confirmedAmount || !/^\d+$/.test(evidence.confirmedAmount)) return void 0;
|
|
6040
|
+
const amount = parseUnits(displayed.amount, asset.decimals);
|
|
6041
|
+
if (amount < 0n) return void 0;
|
|
6042
|
+
const displayUnit = evidence.token === "USDC" ? 5000n : 500000000000n;
|
|
6043
|
+
const movementUnit = BigInt(evidence.confirmedAmount) / 1000n;
|
|
6044
|
+
const tolerance = movementUnit < displayUnit ? movementUnit : displayUnit;
|
|
6045
|
+
if ((total > amount ? total - amount : amount - total) > tolerance) return void 0;
|
|
6046
|
+
return { ...read2, withdrawalCheck: { txHash: evidence.txHash, blockNumber: blockNumber.toString() } };
|
|
5897
6047
|
}
|
|
5898
6048
|
invalidateFundingRead(state, chainId, asset, refreshUntil = Date.now() + YIELDSEEKER_SETTLEMENT_WINDOW_MS) {
|
|
5899
6049
|
this.assertAsset(asset);
|
|
@@ -5933,9 +6083,9 @@ var YieldseekerAgent = class {
|
|
|
5933
6083
|
if (!context) return void 0;
|
|
5934
6084
|
const idle = await withPaidRpcDiagnostics(() => this.getReceiptClient().readContract({
|
|
5935
6085
|
address: YIELDSEEKER_ASSET_METADATA[asset].address,
|
|
5936
|
-
abi:
|
|
6086
|
+
abi: erc20Abi4,
|
|
5937
6087
|
functionName: "balanceOf",
|
|
5938
|
-
args: [
|
|
6088
|
+
args: [getAddress5(context.wallet.walletAddress)]
|
|
5939
6089
|
}), chainId, "eth_call", this.id);
|
|
5940
6090
|
this.assertSession(generation, chainId, asset);
|
|
5941
6091
|
if (typeof idle !== "bigint" || idle < 0n) throw this.invalidResponse("wallet deposit balance");
|
|
@@ -6047,11 +6197,13 @@ var YieldseekerAgent = class {
|
|
|
6047
6197
|
const pending = this.pendingReads.get(key2);
|
|
6048
6198
|
if (pending) return pending;
|
|
6049
6199
|
const generation = this.readGeneration;
|
|
6200
|
+
const requestedAt = Date.now();
|
|
6050
6201
|
const request = Promise.resolve().then(read2).then((value) => {
|
|
6051
6202
|
if (this.readGeneration === generation && this.pendingReads.get(key2) === request) {
|
|
6052
6203
|
this.readCache.set(key2, {
|
|
6053
6204
|
expiresAt: Date.now() + ttlMs,
|
|
6054
6205
|
fetchedAt: Date.now(),
|
|
6206
|
+
requestedAt,
|
|
6055
6207
|
value
|
|
6056
6208
|
});
|
|
6057
6209
|
}
|
|
@@ -6128,7 +6280,7 @@ var YieldseekerAgent = class {
|
|
|
6128
6280
|
this.users.set(key2, persisted);
|
|
6129
6281
|
return persisted;
|
|
6130
6282
|
}
|
|
6131
|
-
const walletAddress =
|
|
6283
|
+
const walletAddress = getAddress5(state.walletAddress);
|
|
6132
6284
|
const generation = this.readGeneration;
|
|
6133
6285
|
let user = null;
|
|
6134
6286
|
try {
|
|
@@ -6420,6 +6572,7 @@ var YieldseekerAgent = class {
|
|
|
6420
6572
|
...context,
|
|
6421
6573
|
snapshot: snapshot.agentSnapshot,
|
|
6422
6574
|
fetchedAt: this.readCache.get(`snapshot:${contextKey}`)?.fetchedAt,
|
|
6575
|
+
requestedAt: this.readCache.get(`snapshot:${contextKey}`)?.requestedAt,
|
|
6423
6576
|
readVersion: version,
|
|
6424
6577
|
positionsUnavailable,
|
|
6425
6578
|
...portfolioParts
|
|
@@ -6619,7 +6772,7 @@ var YieldseekerAgent = class {
|
|
|
6619
6772
|
return hash2;
|
|
6620
6773
|
}
|
|
6621
6774
|
this.assertTransaction(transaction, state, chainId);
|
|
6622
|
-
const account =
|
|
6775
|
+
const account = getAddress5(state.walletAddress);
|
|
6623
6776
|
const walletClient = createWalletClient3({
|
|
6624
6777
|
account,
|
|
6625
6778
|
chain: base4,
|
|
@@ -6637,7 +6790,7 @@ var YieldseekerAgent = class {
|
|
|
6637
6790
|
const hash = await walletClient.sendTransaction({
|
|
6638
6791
|
account,
|
|
6639
6792
|
chain: base4,
|
|
6640
|
-
to:
|
|
6793
|
+
to: getAddress5(transaction.to),
|
|
6641
6794
|
data: transaction.data,
|
|
6642
6795
|
value: BigInt(transaction.value)
|
|
6643
6796
|
});
|
|
@@ -6741,7 +6894,7 @@ var YieldseekerAgent = class {
|
|
|
6741
6894
|
return receipt;
|
|
6742
6895
|
}
|
|
6743
6896
|
assertTransaction(transaction, state, chainId) {
|
|
6744
|
-
if (!transaction || typeof transaction.from !== "string" || !isAddress3(transaction.from) || typeof transaction.to !== "string" || !isAddress3(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 ||
|
|
6897
|
+
if (!transaction || typeof transaction.from !== "string" || !isAddress3(transaction.from) || typeof transaction.to !== "string" || !isAddress3(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 || getAddress5(transaction.from) !== getAddress5(state.walletAddress)) {
|
|
6745
6898
|
throw this.invalidResponse("transaction");
|
|
6746
6899
|
}
|
|
6747
6900
|
}
|
|
@@ -6900,7 +7053,7 @@ async function withFailureReporting(apiKey, agentType, fn, baseUrl) {
|
|
|
6900
7053
|
}
|
|
6901
7054
|
|
|
6902
7055
|
// src/lib/helpers/withdraw-helper.ts
|
|
6903
|
-
import { parseUnits } from "viem";
|
|
7056
|
+
import { parseUnits as parseUnits2 } from "viem";
|
|
6904
7057
|
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
6905
7058
|
const target = asset.toUpperCase();
|
|
6906
7059
|
return agents.map((agent) => {
|
|
@@ -6908,7 +7061,7 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
6908
7061
|
const tokenBalance = agentBalance?.tokens.find(
|
|
6909
7062
|
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
6910
7063
|
);
|
|
6911
|
-
let balance = tokenBalance ?
|
|
7064
|
+
let balance = tokenBalance ? parseUnits2(tokenBalance.amount, decimals) : 0n;
|
|
6912
7065
|
if (agent.balanceComposition === "tokens-plus-positions") {
|
|
6913
7066
|
const chainNameById = {
|
|
6914
7067
|
1: "ETHEREUM",
|
|
@@ -6920,14 +7073,14 @@ function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decima
|
|
|
6920
7073
|
const positionChain = position2.chain.trim().toUpperCase();
|
|
6921
7074
|
const matchesChain = positionChain === String(chainId) || targetChain !== void 0 && positionChain === targetChain;
|
|
6922
7075
|
if (!matchesChain || position2.asset.toUpperCase() !== target) continue;
|
|
6923
|
-
balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) :
|
|
7076
|
+
balance += position2.withdrawableAmountRaw !== void 0 ? BigInt(position2.withdrawableAmountRaw) : parseUnits2(position2.amount, decimals);
|
|
6924
7077
|
}
|
|
6925
7078
|
}
|
|
6926
7079
|
const assetTotal = agentBalance?.assetBalances?.find(
|
|
6927
7080
|
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
6928
7081
|
);
|
|
6929
7082
|
if (assetTotal) {
|
|
6930
|
-
const total =
|
|
7083
|
+
const total = parseUnits2(assetTotal.amount, decimals);
|
|
6931
7084
|
if (total < balance) balance = total > 0n ? total : 0n;
|
|
6932
7085
|
}
|
|
6933
7086
|
return { agent, balance };
|
|
@@ -7087,7 +7240,7 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
7087
7240
|
|
|
7088
7241
|
// src/client.ts
|
|
7089
7242
|
import {
|
|
7090
|
-
parseUnits as
|
|
7243
|
+
parseUnits as parseUnits3,
|
|
7091
7244
|
createPublicClient as createPublicClient4,
|
|
7092
7245
|
createWalletClient as createWalletClient4,
|
|
7093
7246
|
custom as custom4
|
|
@@ -7247,7 +7400,40 @@ async function execute(i, key2, plan) {
|
|
|
7247
7400
|
const send = async (initial) => {
|
|
7248
7401
|
let body = initial;
|
|
7249
7402
|
save(key2, body);
|
|
7403
|
+
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);
|
|
7250
7404
|
try {
|
|
7405
|
+
const post = () => postSponsorBatchTransfer({ apiKey: i.apiKey, baseUrl: i.baseUrl, body });
|
|
7406
|
+
const pendingError = (phase, txHash) => new OwneyError(
|
|
7407
|
+
"DEPOSIT_IN_PROGRESS",
|
|
7408
|
+
phase === "approval" ? "Deposit approval is awaiting confirmation. Retry the same amount to continue it." : "Deposit is awaiting confirmation. Its transaction is still being checked.",
|
|
7409
|
+
{ sponsorPending: true, phase, txHash, safeToFallback: false }
|
|
7410
|
+
);
|
|
7411
|
+
const assertReceipt = (receipt, phase) => {
|
|
7412
|
+
if (receipt.status !== "success") throw new OwneyError(
|
|
7413
|
+
"SPONSOR_REQUEST_FAILED",
|
|
7414
|
+
`Sponsored ${phase} transaction reverted. Please retry.`,
|
|
7415
|
+
{ notSubmitted: true, safeToFallback: false }
|
|
7416
|
+
);
|
|
7417
|
+
};
|
|
7418
|
+
const waitForConfirmation = async (phase, hash2) => {
|
|
7419
|
+
let receipt;
|
|
7420
|
+
try {
|
|
7421
|
+
receipt = await i.pub.waitForTransactionReceipt({ hash: hash2, confirmations: 1, timeout: 9e4, checkReplacement: false });
|
|
7422
|
+
} catch {
|
|
7423
|
+
receipt = await i.pub.getTransactionReceipt({ hash: hash2 }).catch(() => void 0);
|
|
7424
|
+
}
|
|
7425
|
+
if (!receipt) throw pendingError(phase, hash2);
|
|
7426
|
+
assertReceipt(receipt, phase);
|
|
7427
|
+
};
|
|
7428
|
+
const postSigned = async (phase, hash2) => {
|
|
7429
|
+
try {
|
|
7430
|
+
return await post();
|
|
7431
|
+
} catch (error) {
|
|
7432
|
+
if (rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true) throw error;
|
|
7433
|
+
await waitForConfirmation(phase, hash2);
|
|
7434
|
+
return void 0;
|
|
7435
|
+
}
|
|
7436
|
+
};
|
|
7251
7437
|
if (body.erc2612Permit && !body.serializedPermitTransaction) {
|
|
7252
7438
|
const preparedPermit = await postSponsorBatchTransfer({
|
|
7253
7439
|
apiKey: i.apiKey,
|
|
@@ -7265,11 +7451,17 @@ async function execute(i, key2, plan) {
|
|
|
7265
7451
|
save(key2, body);
|
|
7266
7452
|
}
|
|
7267
7453
|
if (!body.serializedTransaction) {
|
|
7268
|
-
const
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7454
|
+
const permitHash = body.serializedPermitTransaction ? keccak256(body.serializedPermitTransaction) : void 0;
|
|
7455
|
+
let prepared = permitHash ? await postSigned("approval", permitHash) : await post();
|
|
7456
|
+
if (prepared?.status === "pending") {
|
|
7457
|
+
if (!permitHash || prepared.phase !== "approval" || prepared.txHash !== permitHash)
|
|
7458
|
+
throw new Error("Sponsorship approval does not match the pending transaction.");
|
|
7459
|
+
await waitForConfirmation("approval", permitHash);
|
|
7460
|
+
prepared = void 0;
|
|
7461
|
+
}
|
|
7462
|
+
if (!prepared) prepared = await post();
|
|
7463
|
+
if (prepared.status === "pending" && permitHash && prepared.phase === "approval" && prepared.txHash === permitHash)
|
|
7464
|
+
throw pendingError("approval", permitHash);
|
|
7273
7465
|
if (!prepared.serializedTransaction || keccak256(prepared.serializedTransaction) !== prepared.txHash)
|
|
7274
7466
|
throw new Error(
|
|
7275
7467
|
"Sponsorship API did not return a valid prepared transaction."
|
|
@@ -7284,19 +7476,30 @@ async function execute(i, key2, plan) {
|
|
|
7284
7476
|
i.onSubmitted?.(keccak256(body.serializedTransaction));
|
|
7285
7477
|
} catch {
|
|
7286
7478
|
}
|
|
7287
|
-
const
|
|
7288
|
-
|
|
7289
|
-
|
|
7290
|
-
|
|
7291
|
-
|
|
7292
|
-
|
|
7293
|
-
|
|
7294
|
-
|
|
7295
|
-
|
|
7479
|
+
const hash = keccak256(body.serializedTransaction);
|
|
7480
|
+
const existing = await i.pub.getTransactionReceipt({ hash }).catch(() => void 0);
|
|
7481
|
+
if (existing) {
|
|
7482
|
+
assertReceipt(existing, "deposit");
|
|
7483
|
+
void post().catch(() => void 0);
|
|
7484
|
+
clear(key2);
|
|
7485
|
+
return hash;
|
|
7486
|
+
}
|
|
7487
|
+
let result = await postSigned("deposit", hash);
|
|
7488
|
+
if (result?.status === "pending" && result.phase === "approval" && body.serializedPermitTransaction && result.txHash === keccak256(body.serializedPermitTransaction)) {
|
|
7489
|
+
await waitForConfirmation("approval", result.txHash);
|
|
7490
|
+
result = await postSigned("deposit", hash);
|
|
7491
|
+
if (result?.status === "pending" && result.phase === "approval" && result.txHash === keccak256(body.serializedPermitTransaction)) throw pendingError("approval", result.txHash);
|
|
7492
|
+
}
|
|
7493
|
+
if (result) {
|
|
7494
|
+
if (result.txHash !== hash || result.status === "pending" && result.phase !== "deposit")
|
|
7495
|
+
throw new Error("Sponsorship receipt does not match the pending transaction.");
|
|
7496
|
+
if (result.status === "pending") await waitForConfirmation("deposit", hash);
|
|
7497
|
+
}
|
|
7498
|
+
if (!result || result.status === "pending") void post().catch(() => void 0);
|
|
7296
7499
|
clear(key2);
|
|
7297
|
-
return
|
|
7500
|
+
return hash;
|
|
7298
7501
|
} catch (error) {
|
|
7299
|
-
if (!body.serializedTransaction || error instanceof OwneyError && error.details?.notSubmitted === true)
|
|
7502
|
+
if (!body.serializedTransaction && !body.serializedPermitTransaction || rejectedPreparation(error) || error instanceof OwneyError && error.details?.notSubmitted === true)
|
|
7300
7503
|
clear(key2);
|
|
7301
7504
|
throw error;
|
|
7302
7505
|
}
|
|
@@ -7502,7 +7705,7 @@ async function runAgentDepositBatch(chainId, legs, transfer) {
|
|
|
7502
7705
|
}
|
|
7503
7706
|
|
|
7504
7707
|
// src/lib/sponsored-calls-deposit.ts
|
|
7505
|
-
import { encodeFunctionData as encodeFunctionData2, erc20Abi as
|
|
7708
|
+
import { encodeFunctionData as encodeFunctionData2, erc20Abi as erc20Abi5, toHex as toHex2 } from "viem";
|
|
7506
7709
|
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
7507
7710
|
var DEFAULT_MAX_POLLS = 30;
|
|
7508
7711
|
async function paymasterSupported(provider, owner, chainId) {
|
|
@@ -7548,7 +7751,7 @@ function makeSponsoredCallsCallback(deps) {
|
|
|
7548
7751
|
to: token,
|
|
7549
7752
|
value: "0x0",
|
|
7550
7753
|
data: encodeFunctionData2({
|
|
7551
|
-
abi:
|
|
7754
|
+
abi: erc20Abi5,
|
|
7552
7755
|
functionName: "transfer",
|
|
7553
7756
|
args: [transfer.to, BigInt(transfer.amount)]
|
|
7554
7757
|
})
|
|
@@ -7749,6 +7952,7 @@ var OwneySDK = class {
|
|
|
7749
7952
|
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
7750
7953
|
agentReads = new AgentReads();
|
|
7751
7954
|
recoveredFundingReads = /* @__PURE__ */ new Set();
|
|
7955
|
+
fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
|
|
7752
7956
|
activationChecks = /* @__PURE__ */ new Map();
|
|
7753
7957
|
readAgent(agent, method, fetch2, params = null) {
|
|
7754
7958
|
const key2 = JSON.stringify([
|
|
@@ -7794,6 +7998,7 @@ var OwneySDK = class {
|
|
|
7794
7998
|
}
|
|
7795
7999
|
this.agentReads.clearInFlight();
|
|
7796
8000
|
this.activationChecks.clear();
|
|
8001
|
+
this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
|
|
7797
8002
|
this.state = { provider, walletAddress, chainId: null };
|
|
7798
8003
|
this.cachedSponsoredCallback = null;
|
|
7799
8004
|
this.cachedWethSponsoredCallback = null;
|
|
@@ -7805,6 +8010,7 @@ var OwneySDK = class {
|
|
|
7805
8010
|
*/
|
|
7806
8011
|
async disconnect() {
|
|
7807
8012
|
this.state = null;
|
|
8013
|
+
this.fundingBalanceChecks = /* @__PURE__ */ new WeakMap();
|
|
7808
8014
|
for (const agent of this.agents.values()) {
|
|
7809
8015
|
await agent.disconnect();
|
|
7810
8016
|
}
|
|
@@ -8705,9 +8911,8 @@ var OwneySDK = class {
|
|
|
8705
8911
|
verified = inspectFundingReceipt(receipt, { ...evidence, agentWallet, intendedAmount: "MAX" }, token.address, direction);
|
|
8706
8912
|
}
|
|
8707
8913
|
const key2 = `${state.walletAddress.toLowerCase()}:${chainId}:${evidence.agentId}:${evidence.token}:${evidence.txHash}`;
|
|
8708
|
-
if ((verified.transfer === "confirmed" || verified.transfer === "failed" && verified.confirmedAmount === "0") && !this.recoveredFundingReads.has(key2)) {
|
|
8709
|
-
|
|
8710
|
-
agent.invalidateFundingRead?.(state, chainId, evidence.token, options.balanceRefreshUntil);
|
|
8914
|
+
if (options.refreshBalance !== false && (verified.transfer === "confirmed" || verified.transfer === "failed" && verified.confirmedAmount === "0") && !this.recoveredFundingReads.has(key2)) {
|
|
8915
|
+
agent.invalidateFundingRead?.(state, chainId, evidence.token, options.balanceRefreshUntil);
|
|
8711
8916
|
this.recoveredFundingReads.add(key2);
|
|
8712
8917
|
if (this.recoveredFundingReads.size > 256) this.recoveredFundingReads.delete(this.recoveredFundingReads.values().next().value);
|
|
8713
8918
|
}
|
|
@@ -8815,6 +9020,44 @@ var OwneySDK = class {
|
|
|
8815
9020
|
assertCurrent();
|
|
8816
9021
|
return true;
|
|
8817
9022
|
}
|
|
9023
|
+
/** Optional post-payout display proof; receipt verification and the provider
|
|
9024
|
+
* adapter must agree before attaching it to this exact balance object. */
|
|
9025
|
+
async verifyWithdrawalBalance(evidence, balance) {
|
|
9026
|
+
const { state, chainId, assertCurrent } = this.captureReadScope(evidence.chainId);
|
|
9027
|
+
const agent = this.getAgent(evidence.agentId);
|
|
9028
|
+
if (!agent.verifyWithdrawalBalance || !evidence.txHash || state.walletAddress.toLowerCase() !== evidence.walletAddress.toLowerCase()) return balance;
|
|
9029
|
+
const key2 = `${state.walletAddress.toLowerCase()}:${chainId}:${evidence.agentId}:${evidence.token}:${evidence.txHash}:${evidence.intendedAmount}`;
|
|
9030
|
+
const checks = this.fundingBalanceChecks.get(balance) ?? /* @__PURE__ */ new Map();
|
|
9031
|
+
this.fundingBalanceChecks.set(balance, checks);
|
|
9032
|
+
const previous = checks.get(key2);
|
|
9033
|
+
if (previous) {
|
|
9034
|
+
const result2 = await previous;
|
|
9035
|
+
assertCurrent();
|
|
9036
|
+
return result2;
|
|
9037
|
+
}
|
|
9038
|
+
let timer;
|
|
9039
|
+
const read2 = async () => {
|
|
9040
|
+
const verified = await this.inspectFunding(evidence, "withdraw", { refreshBalance: false });
|
|
9041
|
+
assertCurrent();
|
|
9042
|
+
if (verified.transfer !== "confirmed" || verified.delivery !== "confirmed" || !verified.blockNumber) return balance;
|
|
9043
|
+
const metadata = await agent.verifyWithdrawalBalance(state, verified, balance);
|
|
9044
|
+
assertCurrent();
|
|
9045
|
+
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;
|
|
9046
|
+
return { ...balance, readMetadata: [
|
|
9047
|
+
...(balance.readMetadata ?? []).filter((item) => !(item.chainId === chainId && item.asset.toUpperCase() === evidence.token)),
|
|
9048
|
+
metadata
|
|
9049
|
+
] };
|
|
9050
|
+
};
|
|
9051
|
+
const pending = Promise.race([read2(), new Promise((resolve) => {
|
|
9052
|
+
timer = setTimeout(() => resolve(balance), 2e3);
|
|
9053
|
+
})]).catch(() => balance).finally(() => {
|
|
9054
|
+
if (timer) clearTimeout(timer);
|
|
9055
|
+
});
|
|
9056
|
+
checks.set(key2, pending);
|
|
9057
|
+
const result = await pending;
|
|
9058
|
+
assertCurrent();
|
|
9059
|
+
return result;
|
|
9060
|
+
}
|
|
8818
9061
|
/** A display acknowledgement controls polling only; it never confirms a financial outcome. */
|
|
8819
9062
|
endFundingBalanceRefresh(evidence, read2) {
|
|
8820
9063
|
const { state, chainId } = this.captureReadScope(evidence.chainId);
|
|
@@ -9083,7 +9326,7 @@ var OwneySDK = class {
|
|
|
9083
9326
|
if (this.isUserRejectedWithdrawal(originalFailure)) throw originalFailure;
|
|
9084
9327
|
if (entry.balance !== 0n && entry.agent.id !== "yieldseeker") {
|
|
9085
9328
|
const total = aggregated.agentBalances[entry.agent.id]?.assetBalances?.find((value) => value.chainId === chainId && value.asset.toUpperCase() === token);
|
|
9086
|
-
if (!total ||
|
|
9329
|
+
if (!total || parseUnits3(total.amount, assetInfo.decimals) <= entry.balance) return;
|
|
9087
9330
|
}
|
|
9088
9331
|
try {
|
|
9089
9332
|
const otherAvailable = indexedAvailable - entry.balance;
|
|
@@ -9858,7 +10101,7 @@ var OwneySDK = class {
|
|
|
9858
10101
|
};
|
|
9859
10102
|
|
|
9860
10103
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
9861
|
-
import { getAddress as
|
|
10104
|
+
import { getAddress as getAddress6 } from "viem";
|
|
9862
10105
|
import { SiweMessage as SiweMessage2 } from "siwe";
|
|
9863
10106
|
import { ZyfaiSDK as ZyfaiSDK2 } from "@zyfai/sdk";
|
|
9864
10107
|
|
|
@@ -9985,7 +10228,7 @@ function buildSIWXConfig(deps) {
|
|
|
9985
10228
|
issuedAt,
|
|
9986
10229
|
toString() {
|
|
9987
10230
|
return new SiweMessage2({
|
|
9988
|
-
address:
|
|
10231
|
+
address: getAddress6(accountAddress),
|
|
9989
10232
|
chainId: numericChainId(chainId),
|
|
9990
10233
|
domain,
|
|
9991
10234
|
uri,
|