@owney/sdk 0.7.16-beta.3 → 0.7.16-beta.5
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 +163 -36
- package/dist/index.d.cts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.js +163 -36
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2673,19 +2673,27 @@ function assetAddressValue(record, address) {
|
|
|
2673
2673
|
);
|
|
2674
2674
|
return entry?.[1] ?? "0";
|
|
2675
2675
|
}
|
|
2676
|
-
function position(value, asset) {
|
|
2676
|
+
function position(value, asset, baseAssetDecimals) {
|
|
2677
2677
|
const option = value?.yieldOption;
|
|
2678
2678
|
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !(0, import_viem5.isAddress)(option.address)) {
|
|
2679
2679
|
return invalid("yield positions", "missing vault metadata");
|
|
2680
2680
|
}
|
|
2681
|
-
const decimals = YIELDSEEKER_ASSET_METADATA[asset].decimals;
|
|
2682
2681
|
return {
|
|
2683
2682
|
chain: "BASE",
|
|
2684
2683
|
protocol: option.provider,
|
|
2685
2684
|
protocolId: option.address,
|
|
2686
2685
|
pool: option.name,
|
|
2687
2686
|
asset,
|
|
2688
|
-
|
|
2687
|
+
// `assetsRaw` is the ERC-4626 vault-share quantity, whose decimals can
|
|
2688
|
+
// differ from the underlying asset. Yieldseeker already converts it to
|
|
2689
|
+
// underlying base-asset units in `assetsBase`; pair that value with the
|
|
2690
|
+
// snapshot's corresponding `baseAssetDecimals` for display. Keep the raw
|
|
2691
|
+
// share quantity separately because withdraw-from-position expects it.
|
|
2692
|
+
amount: decimal(
|
|
2693
|
+
value.assetsBase,
|
|
2694
|
+
baseAssetDecimals,
|
|
2695
|
+
"yield positions"
|
|
2696
|
+
),
|
|
2689
2697
|
amountRaw: String(value.assetsRaw),
|
|
2690
2698
|
apy: percent(option.riskAdjustedApy),
|
|
2691
2699
|
tvl: Number(option.totalDepositsUsd),
|
|
@@ -2709,7 +2717,13 @@ function mapYieldseekerBalances(contexts) {
|
|
|
2709
2717
|
amount: decimal(idle, metadata.decimals, "snapshot")
|
|
2710
2718
|
});
|
|
2711
2719
|
positions.push(
|
|
2712
|
-
...context.positions.map(
|
|
2720
|
+
...context.positions.map(
|
|
2721
|
+
(entry) => position(
|
|
2722
|
+
entry,
|
|
2723
|
+
context.asset,
|
|
2724
|
+
context.snapshot.baseAssetDecimals
|
|
2725
|
+
)
|
|
2726
|
+
)
|
|
2713
2727
|
);
|
|
2714
2728
|
totalUsd += usd(
|
|
2715
2729
|
raw(context.snapshot.totalValueBase, "snapshot"),
|
|
@@ -2956,6 +2970,18 @@ function mapYieldseekerAgentApy(options, days) {
|
|
|
2956
2970
|
|
|
2957
2971
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
2958
2972
|
var OWNEY_AGENT_NAME = "owney";
|
|
2973
|
+
var YIELDSEEKER_USERNAME_PREFIX = "owney_";
|
|
2974
|
+
var YIELDSEEKER_USERNAME_RANDOM_LENGTH = 14;
|
|
2975
|
+
var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
|
|
2976
|
+
function generateYieldseekerUsername() {
|
|
2977
|
+
const suffix = globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, YIELDSEEKER_USERNAME_RANDOM_LENGTH).toLowerCase();
|
|
2978
|
+
return `${YIELDSEEKER_USERNAME_PREFIX}${suffix}`;
|
|
2979
|
+
}
|
|
2980
|
+
function isUsernameConflict(error) {
|
|
2981
|
+
if (!(error instanceof YieldseekerApiError)) return false;
|
|
2982
|
+
const code = error.providerCode.toUpperCase();
|
|
2983
|
+
return code.includes("USERNAME") && (code.includes("TAKEN") || code.includes("EXIST") || code.includes("UNAVAILABLE") || code.includes("IN_USE"));
|
|
2984
|
+
}
|
|
2959
2985
|
var YIELDSEEKER_AGENT_WALLET_ABI = [
|
|
2960
2986
|
{
|
|
2961
2987
|
type: "function",
|
|
@@ -3295,21 +3321,26 @@ var YieldseekerAgent = class {
|
|
|
3295
3321
|
throw this.mapApiError(error);
|
|
3296
3322
|
}
|
|
3297
3323
|
let created;
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3324
|
+
for (let attempt = 0; attempt < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS; attempt += 1) {
|
|
3325
|
+
try {
|
|
3326
|
+
created = await this.providerRequest(
|
|
3327
|
+
state,
|
|
3328
|
+
chainId,
|
|
3329
|
+
"/users",
|
|
3330
|
+
{
|
|
3331
|
+
method: "POST",
|
|
3332
|
+
body: {
|
|
3333
|
+
walletAddress,
|
|
3334
|
+
username: generateYieldseekerUsername()
|
|
3335
|
+
}
|
|
3308
3336
|
}
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3337
|
+
);
|
|
3338
|
+
break;
|
|
3339
|
+
} catch (createError) {
|
|
3340
|
+
const canRetry = isUsernameConflict(createError) && attempt + 1 < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS;
|
|
3341
|
+
if (canRetry) continue;
|
|
3342
|
+
throw this.mapApiError(createError);
|
|
3343
|
+
}
|
|
3313
3344
|
}
|
|
3314
3345
|
user = created?.user ?? null;
|
|
3315
3346
|
}
|
|
@@ -4644,17 +4675,25 @@ var OwneySDK = class {
|
|
|
4644
4675
|
* at a time anyway.
|
|
4645
4676
|
*
|
|
4646
4677
|
* Every agent is attempted even if an earlier one fails, so one declined
|
|
4647
|
-
* signature can't deny the remaining agents their turn.
|
|
4648
|
-
*
|
|
4649
|
-
*
|
|
4678
|
+
* signature can't deny the remaining agents their turn. Once all agents have
|
|
4679
|
+
* had a chance, a partial failure identifies the agents that still need a
|
|
4680
|
+
* retry; if none activated, the original provider error is preserved.
|
|
4650
4681
|
*/
|
|
4651
4682
|
async activateAgentsInTurn(agents, state, chainId, asset) {
|
|
4652
4683
|
let firstError = null;
|
|
4684
|
+
const activatedAgentIds = [];
|
|
4685
|
+
const failedAgents = [];
|
|
4653
4686
|
for (const agent of agents) {
|
|
4654
4687
|
try {
|
|
4655
4688
|
await agent.activateAgent(state, chainId, asset);
|
|
4656
4689
|
await this.applyOrgPolicyTo(agent, state, chainId);
|
|
4690
|
+
activatedAgentIds.push(agent.id);
|
|
4657
4691
|
} catch (error) {
|
|
4692
|
+
failedAgents.push({
|
|
4693
|
+
agentId: agent.id,
|
|
4694
|
+
code: error instanceof OwneyError ? error.code : void 0,
|
|
4695
|
+
message: error instanceof Error ? error.message : String(error)
|
|
4696
|
+
});
|
|
4658
4697
|
if (firstError === null) {
|
|
4659
4698
|
firstError = error;
|
|
4660
4699
|
} else {
|
|
@@ -4662,10 +4701,19 @@ var OwneySDK = class {
|
|
|
4662
4701
|
}
|
|
4663
4702
|
}
|
|
4664
4703
|
}
|
|
4665
|
-
if (firstError
|
|
4704
|
+
if (firstError === null) return;
|
|
4705
|
+
if (activatedAgentIds.length === 0) throw firstError;
|
|
4706
|
+
const failedAgentIds = failedAgents.map(({ agentId }) => agentId);
|
|
4707
|
+
const activeNames = activatedAgentIds.map(this.formatAgentName).join(", ");
|
|
4708
|
+
const remainingNames = failedAgentIds.map(this.formatAgentName).join(", ");
|
|
4709
|
+
throw new OwneyError(
|
|
4710
|
+
"AGENT_ACTIVATION_PARTIAL_FAILURE",
|
|
4711
|
+
`${activeNames} activated, but ${remainingNames} still needs activation. Try again and approve the remaining wallet request.`,
|
|
4712
|
+
{ activatedAgentIds, failedAgentIds, failures: failedAgents }
|
|
4713
|
+
);
|
|
4666
4714
|
}
|
|
4667
4715
|
/**
|
|
4668
|
-
* Deposit funds into a specific agent, or
|
|
4716
|
+
* Deposit funds into a specific agent, or distribute across all agents if agentId is omitted.
|
|
4669
4717
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
4670
4718
|
* @param options - Deposit parameters
|
|
4671
4719
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -4673,7 +4721,8 @@ var OwneySDK = class {
|
|
|
4673
4721
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
4674
4722
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
4675
4723
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
4676
|
-
* @param options.agentId - Optional. Target agent. Omit to
|
|
4724
|
+
* @param options.agentId - Optional. Target agent. Omit to fund all eligible agents. Deposits
|
|
4725
|
+
* are equal once every agent is funded; first/recovery deposits also honor each agent's floor.
|
|
4677
4726
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
4678
4727
|
*/
|
|
4679
4728
|
async deposit(options) {
|
|
@@ -4725,10 +4774,35 @@ var OwneySDK = class {
|
|
|
4725
4774
|
exempt
|
|
4726
4775
|
);
|
|
4727
4776
|
if (agentAmounts.length === 0) {
|
|
4777
|
+
const agentsRequiringActivation = eligibleAgents.filter(
|
|
4778
|
+
(agent) => !exempt.has(agent.id)
|
|
4779
|
+
);
|
|
4780
|
+
const perAgentMinimum = agentsRequiringActivation.reduce(
|
|
4781
|
+
(highest, agent) => {
|
|
4782
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
4783
|
+
return minimum > highest ? minimum : highest;
|
|
4784
|
+
},
|
|
4785
|
+
0n
|
|
4786
|
+
);
|
|
4787
|
+
const minimumRequired = perAgentMinimum * BigInt(agentsRequiringActivation.length);
|
|
4728
4788
|
throw new OwneyError(
|
|
4729
4789
|
"DEPOSIT_AMOUNT_BELOW_MINIMUM",
|
|
4730
|
-
`Amount "${amount}" cannot
|
|
4731
|
-
{
|
|
4790
|
+
`Amount "${amount}" cannot activate every eligible agent. The combined minimum is "${minimumRequired.toString()}" for ${asset}.`,
|
|
4791
|
+
{
|
|
4792
|
+
amount,
|
|
4793
|
+
asset,
|
|
4794
|
+
chainId,
|
|
4795
|
+
minDepositAmount: minimumRequired.toString(),
|
|
4796
|
+
perAgentDepositAmount: perAgentMinimum.toString(),
|
|
4797
|
+
agentMinimums: agentsRequiringActivation.map((agent) => ({
|
|
4798
|
+
agentId: agent.id,
|
|
4799
|
+
minDepositAmount: this.getMinDepositAmount(
|
|
4800
|
+
agent,
|
|
4801
|
+
chainId,
|
|
4802
|
+
asset
|
|
4803
|
+
).toString()
|
|
4804
|
+
}))
|
|
4805
|
+
}
|
|
4732
4806
|
);
|
|
4733
4807
|
}
|
|
4734
4808
|
const agentResults = {};
|
|
@@ -4814,6 +4888,20 @@ var OwneySDK = class {
|
|
|
4814
4888
|
}
|
|
4815
4889
|
splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
|
|
4816
4890
|
if (agents.length === 0) return [];
|
|
4891
|
+
const agentsRequiringActivation = agents.filter(
|
|
4892
|
+
(agent) => !exempt.has(agent.id)
|
|
4893
|
+
);
|
|
4894
|
+
if (agentsRequiringActivation.length === agents.length) {
|
|
4895
|
+
const highestMinimum2 = agents.reduce(
|
|
4896
|
+
(highest, agent) => {
|
|
4897
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
4898
|
+
return minimum > highest ? minimum : highest;
|
|
4899
|
+
},
|
|
4900
|
+
0n
|
|
4901
|
+
);
|
|
4902
|
+
const minimumRequired2 = highestMinimum2 * BigInt(agents.length);
|
|
4903
|
+
if (totalAmount < minimumRequired2) return [];
|
|
4904
|
+
}
|
|
4817
4905
|
const perAgent = totalAmount / BigInt(agents.length);
|
|
4818
4906
|
const remainder = totalAmount % BigInt(agents.length);
|
|
4819
4907
|
const splits = agents.map((agent, i) => ({
|
|
@@ -4826,13 +4914,29 @@ var OwneySDK = class {
|
|
|
4826
4914
|
if (valid2.length === agents.length) {
|
|
4827
4915
|
return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
|
|
4828
4916
|
}
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
4917
|
+
const targets = agentsRequiringActivation.length > 0 ? agentsRequiringActivation : valid2.map((s) => s.agent);
|
|
4918
|
+
const highestMinimum = targets.reduce(
|
|
4919
|
+
(highest, agent) => {
|
|
4920
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
4921
|
+
return minimum > highest ? minimum : highest;
|
|
4922
|
+
},
|
|
4923
|
+
0n
|
|
4835
4924
|
);
|
|
4925
|
+
const minimumRequired = highestMinimum * BigInt(targets.length);
|
|
4926
|
+
if (totalAmount < minimumRequired) return [];
|
|
4927
|
+
const targetShare = totalAmount / BigInt(targets.length);
|
|
4928
|
+
const targetRemainder = totalAmount % BigInt(targets.length);
|
|
4929
|
+
return targets.map((agent, index) => ({
|
|
4930
|
+
agent,
|
|
4931
|
+
amount: String(
|
|
4932
|
+
targetShare + (index === targets.length - 1 ? targetRemainder : 0n)
|
|
4933
|
+
)
|
|
4934
|
+
}));
|
|
4935
|
+
}
|
|
4936
|
+
formatAgentName(agentId) {
|
|
4937
|
+
if (agentId === "zyfai") return "Zyfai";
|
|
4938
|
+
if (agentId === "yieldseeker") return "Yieldseeker";
|
|
4939
|
+
return agentId;
|
|
4836
4940
|
}
|
|
4837
4941
|
async validateMinDepositAmount(agent, state, chainId, asset, amount) {
|
|
4838
4942
|
const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
|
|
@@ -4864,7 +4968,20 @@ var OwneySDK = class {
|
|
|
4864
4968
|
const token = balance.tokens.find(
|
|
4865
4969
|
(t) => t.chainId === chainId && t.asset.toLowerCase() === target
|
|
4866
4970
|
);
|
|
4867
|
-
|
|
4971
|
+
const chainNameById = {
|
|
4972
|
+
1: "ETHEREUM",
|
|
4973
|
+
8453: "BASE",
|
|
4974
|
+
42161: "ARBITRUM"
|
|
4975
|
+
};
|
|
4976
|
+
const targetChainName = chainNameById[chainId];
|
|
4977
|
+
const position2 = (balance.positions ?? []).find(
|
|
4978
|
+
(p) => {
|
|
4979
|
+
const positionChain = p.chain.trim().toUpperCase();
|
|
4980
|
+
const matchesChain = positionChain === String(chainId) || targetChainName !== void 0 && positionChain === targetChainName;
|
|
4981
|
+
return matchesChain && p.asset.toLowerCase() === target && Number(p.amount) > 0;
|
|
4982
|
+
}
|
|
4983
|
+
);
|
|
4984
|
+
return !!token && Number(token.amount) > 0 || !!position2;
|
|
4868
4985
|
} catch {
|
|
4869
4986
|
return false;
|
|
4870
4987
|
}
|
|
@@ -5087,8 +5204,12 @@ var OwneySDK = class {
|
|
|
5087
5204
|
const state = this.requireState();
|
|
5088
5205
|
const chainId = this.requireChainId();
|
|
5089
5206
|
if (agentId) {
|
|
5090
|
-
const
|
|
5091
|
-
|
|
5207
|
+
const agent = this.getAgent(agentId);
|
|
5208
|
+
const result = await agent.getBalances(state, chainId);
|
|
5209
|
+
return {
|
|
5210
|
+
...result,
|
|
5211
|
+
balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
|
|
5212
|
+
};
|
|
5092
5213
|
}
|
|
5093
5214
|
let totalBalance = 0;
|
|
5094
5215
|
const results = {};
|
|
@@ -5096,7 +5217,13 @@ var OwneySDK = class {
|
|
|
5096
5217
|
const balanceResults = await Promise.allSettled(
|
|
5097
5218
|
entries.map(async ([id, agent]) => {
|
|
5098
5219
|
const b = await agent.getBalances(state, chainId);
|
|
5099
|
-
return [
|
|
5220
|
+
return [
|
|
5221
|
+
id,
|
|
5222
|
+
{
|
|
5223
|
+
...b,
|
|
5224
|
+
balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
|
|
5225
|
+
}
|
|
5226
|
+
];
|
|
5100
5227
|
})
|
|
5101
5228
|
);
|
|
5102
5229
|
let successCount = 0;
|
package/dist/index.d.cts
CHANGED
|
@@ -245,6 +245,13 @@ interface AgentBalance {
|
|
|
245
245
|
totalBalance: string;
|
|
246
246
|
/** Asset that `totalBalance` is denominated in. Currently always `"usdc"`. */
|
|
247
247
|
totalBalanceAsset: string;
|
|
248
|
+
/**
|
|
249
|
+
* Describes whether `tokens` already includes deployed `positions`.
|
|
250
|
+
* Consumers must add matching positions only for `tokens-plus-positions`;
|
|
251
|
+
* doing so for Zyfai would double-count, while omitting it for Yieldseeker
|
|
252
|
+
* makes its balance disappear as soon as idle funds enter a vault.
|
|
253
|
+
*/
|
|
254
|
+
balanceComposition?: "tokens-include-positions" | "tokens-plus-positions";
|
|
248
255
|
tokens: OwneyToken[];
|
|
249
256
|
/**
|
|
250
257
|
* Per-protocol/pool positions when the agent's portfolio payload includes
|
|
@@ -578,13 +585,13 @@ declare class OwneySDK {
|
|
|
578
585
|
* at a time anyway.
|
|
579
586
|
*
|
|
580
587
|
* Every agent is attempted even if an earlier one fails, so one declined
|
|
581
|
-
* signature can't deny the remaining agents their turn.
|
|
582
|
-
*
|
|
583
|
-
*
|
|
588
|
+
* signature can't deny the remaining agents their turn. Once all agents have
|
|
589
|
+
* had a chance, a partial failure identifies the agents that still need a
|
|
590
|
+
* retry; if none activated, the original provider error is preserved.
|
|
584
591
|
*/
|
|
585
592
|
private activateAgentsInTurn;
|
|
586
593
|
/**
|
|
587
|
-
* Deposit funds into a specific agent, or
|
|
594
|
+
* Deposit funds into a specific agent, or distribute across all agents if agentId is omitted.
|
|
588
595
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
589
596
|
* @param options - Deposit parameters
|
|
590
597
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -592,7 +599,8 @@ declare class OwneySDK {
|
|
|
592
599
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
593
600
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
594
601
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
595
|
-
* @param options.agentId - Optional. Target agent. Omit to
|
|
602
|
+
* @param options.agentId - Optional. Target agent. Omit to fund all eligible agents. Deposits
|
|
603
|
+
* are equal once every agent is funded; first/recovery deposits also honor each agent's floor.
|
|
596
604
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
597
605
|
*/
|
|
598
606
|
deposit(options: DepositOptions): Promise<OwneyDepositResult | OwneyMultiDepositResult>;
|
|
@@ -624,6 +632,7 @@ declare class OwneySDK {
|
|
|
624
632
|
private depositWithFallback;
|
|
625
633
|
private getMinDepositAmount;
|
|
626
634
|
private splitDepositAmount;
|
|
635
|
+
private formatAgentName;
|
|
627
636
|
private validateMinDepositAmount;
|
|
628
637
|
/**
|
|
629
638
|
* Whether the user already holds a non-zero balance with `agent` for the
|
|
@@ -819,7 +828,7 @@ declare class YieldseekerAgent implements IAgent {
|
|
|
819
828
|
private invalidResponse;
|
|
820
829
|
}
|
|
821
830
|
|
|
822
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_BALANCE_UNAVAILABLE" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "AGENT_API_ERROR" | "AGENT_AUTH_FAILED" | "AGENT_INVALID_RESPONSE" | "AGENT_TIMEOUT" | "AGENT_TRANSACTION_REVERTED" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
831
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "AGENT_ACTIVATION_PARTIAL_FAILURE" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_BALANCE_UNAVAILABLE" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "AGENT_API_ERROR" | "AGENT_AUTH_FAILED" | "AGENT_INVALID_RESPONSE" | "AGENT_TIMEOUT" | "AGENT_TRANSACTION_REVERTED" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
823
832
|
declare class OwneyError extends Error {
|
|
824
833
|
readonly code: OwneyErrorCode;
|
|
825
834
|
readonly details?: Record<string, unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -245,6 +245,13 @@ interface AgentBalance {
|
|
|
245
245
|
totalBalance: string;
|
|
246
246
|
/** Asset that `totalBalance` is denominated in. Currently always `"usdc"`. */
|
|
247
247
|
totalBalanceAsset: string;
|
|
248
|
+
/**
|
|
249
|
+
* Describes whether `tokens` already includes deployed `positions`.
|
|
250
|
+
* Consumers must add matching positions only for `tokens-plus-positions`;
|
|
251
|
+
* doing so for Zyfai would double-count, while omitting it for Yieldseeker
|
|
252
|
+
* makes its balance disappear as soon as idle funds enter a vault.
|
|
253
|
+
*/
|
|
254
|
+
balanceComposition?: "tokens-include-positions" | "tokens-plus-positions";
|
|
248
255
|
tokens: OwneyToken[];
|
|
249
256
|
/**
|
|
250
257
|
* Per-protocol/pool positions when the agent's portfolio payload includes
|
|
@@ -578,13 +585,13 @@ declare class OwneySDK {
|
|
|
578
585
|
* at a time anyway.
|
|
579
586
|
*
|
|
580
587
|
* Every agent is attempted even if an earlier one fails, so one declined
|
|
581
|
-
* signature can't deny the remaining agents their turn.
|
|
582
|
-
*
|
|
583
|
-
*
|
|
588
|
+
* signature can't deny the remaining agents their turn. Once all agents have
|
|
589
|
+
* had a chance, a partial failure identifies the agents that still need a
|
|
590
|
+
* retry; if none activated, the original provider error is preserved.
|
|
584
591
|
*/
|
|
585
592
|
private activateAgentsInTurn;
|
|
586
593
|
/**
|
|
587
|
-
* Deposit funds into a specific agent, or
|
|
594
|
+
* Deposit funds into a specific agent, or distribute across all agents if agentId is omitted.
|
|
588
595
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
589
596
|
* @param options - Deposit parameters
|
|
590
597
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -592,7 +599,8 @@ declare class OwneySDK {
|
|
|
592
599
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
593
600
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
594
601
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
595
|
-
* @param options.agentId - Optional. Target agent. Omit to
|
|
602
|
+
* @param options.agentId - Optional. Target agent. Omit to fund all eligible agents. Deposits
|
|
603
|
+
* are equal once every agent is funded; first/recovery deposits also honor each agent's floor.
|
|
596
604
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
597
605
|
*/
|
|
598
606
|
deposit(options: DepositOptions): Promise<OwneyDepositResult | OwneyMultiDepositResult>;
|
|
@@ -624,6 +632,7 @@ declare class OwneySDK {
|
|
|
624
632
|
private depositWithFallback;
|
|
625
633
|
private getMinDepositAmount;
|
|
626
634
|
private splitDepositAmount;
|
|
635
|
+
private formatAgentName;
|
|
627
636
|
private validateMinDepositAmount;
|
|
628
637
|
/**
|
|
629
638
|
* Whether the user already holds a non-zero balance with `agent` for the
|
|
@@ -819,7 +828,7 @@ declare class YieldseekerAgent implements IAgent {
|
|
|
819
828
|
private invalidResponse;
|
|
820
829
|
}
|
|
821
830
|
|
|
822
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_BALANCE_UNAVAILABLE" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "AGENT_API_ERROR" | "AGENT_AUTH_FAILED" | "AGENT_INVALID_RESPONSE" | "AGENT_TIMEOUT" | "AGENT_TRANSACTION_REVERTED" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
831
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "AGENT_ACTIVATION_PARTIAL_FAILURE" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_BALANCE_UNAVAILABLE" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_NO_AGENTS" | "AGENT_API_ERROR" | "AGENT_AUTH_FAILED" | "AGENT_INVALID_RESPONSE" | "AGENT_TIMEOUT" | "AGENT_TRANSACTION_REVERTED" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
823
832
|
declare class OwneyError extends Error {
|
|
824
833
|
readonly code: OwneyErrorCode;
|
|
825
834
|
readonly details?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -2652,19 +2652,27 @@ function assetAddressValue(record, address) {
|
|
|
2652
2652
|
);
|
|
2653
2653
|
return entry?.[1] ?? "0";
|
|
2654
2654
|
}
|
|
2655
|
-
function position(value, asset) {
|
|
2655
|
+
function position(value, asset, baseAssetDecimals) {
|
|
2656
2656
|
const option = value?.yieldOption;
|
|
2657
2657
|
if (!option || typeof option.provider !== "string" || typeof option.name !== "string" || typeof option.address !== "string" || !isAddress(option.address)) {
|
|
2658
2658
|
return invalid("yield positions", "missing vault metadata");
|
|
2659
2659
|
}
|
|
2660
|
-
const decimals = YIELDSEEKER_ASSET_METADATA[asset].decimals;
|
|
2661
2660
|
return {
|
|
2662
2661
|
chain: "BASE",
|
|
2663
2662
|
protocol: option.provider,
|
|
2664
2663
|
protocolId: option.address,
|
|
2665
2664
|
pool: option.name,
|
|
2666
2665
|
asset,
|
|
2667
|
-
|
|
2666
|
+
// `assetsRaw` is the ERC-4626 vault-share quantity, whose decimals can
|
|
2667
|
+
// differ from the underlying asset. Yieldseeker already converts it to
|
|
2668
|
+
// underlying base-asset units in `assetsBase`; pair that value with the
|
|
2669
|
+
// snapshot's corresponding `baseAssetDecimals` for display. Keep the raw
|
|
2670
|
+
// share quantity separately because withdraw-from-position expects it.
|
|
2671
|
+
amount: decimal(
|
|
2672
|
+
value.assetsBase,
|
|
2673
|
+
baseAssetDecimals,
|
|
2674
|
+
"yield positions"
|
|
2675
|
+
),
|
|
2668
2676
|
amountRaw: String(value.assetsRaw),
|
|
2669
2677
|
apy: percent(option.riskAdjustedApy),
|
|
2670
2678
|
tvl: Number(option.totalDepositsUsd),
|
|
@@ -2688,7 +2696,13 @@ function mapYieldseekerBalances(contexts) {
|
|
|
2688
2696
|
amount: decimal(idle, metadata.decimals, "snapshot")
|
|
2689
2697
|
});
|
|
2690
2698
|
positions.push(
|
|
2691
|
-
...context.positions.map(
|
|
2699
|
+
...context.positions.map(
|
|
2700
|
+
(entry) => position(
|
|
2701
|
+
entry,
|
|
2702
|
+
context.asset,
|
|
2703
|
+
context.snapshot.baseAssetDecimals
|
|
2704
|
+
)
|
|
2705
|
+
)
|
|
2692
2706
|
);
|
|
2693
2707
|
totalUsd += usd(
|
|
2694
2708
|
raw(context.snapshot.totalValueBase, "snapshot"),
|
|
@@ -2935,6 +2949,18 @@ function mapYieldseekerAgentApy(options, days) {
|
|
|
2935
2949
|
|
|
2936
2950
|
// src/agents/yieldseeker/yieldseeker.agent.ts
|
|
2937
2951
|
var OWNEY_AGENT_NAME = "owney";
|
|
2952
|
+
var YIELDSEEKER_USERNAME_PREFIX = "owney_";
|
|
2953
|
+
var YIELDSEEKER_USERNAME_RANDOM_LENGTH = 14;
|
|
2954
|
+
var YIELDSEEKER_USERNAME_CREATE_ATTEMPTS = 3;
|
|
2955
|
+
function generateYieldseekerUsername() {
|
|
2956
|
+
const suffix = globalThis.crypto.randomUUID().replaceAll("-", "").slice(0, YIELDSEEKER_USERNAME_RANDOM_LENGTH).toLowerCase();
|
|
2957
|
+
return `${YIELDSEEKER_USERNAME_PREFIX}${suffix}`;
|
|
2958
|
+
}
|
|
2959
|
+
function isUsernameConflict(error) {
|
|
2960
|
+
if (!(error instanceof YieldseekerApiError)) return false;
|
|
2961
|
+
const code = error.providerCode.toUpperCase();
|
|
2962
|
+
return code.includes("USERNAME") && (code.includes("TAKEN") || code.includes("EXIST") || code.includes("UNAVAILABLE") || code.includes("IN_USE"));
|
|
2963
|
+
}
|
|
2938
2964
|
var YIELDSEEKER_AGENT_WALLET_ABI = [
|
|
2939
2965
|
{
|
|
2940
2966
|
type: "function",
|
|
@@ -3274,21 +3300,26 @@ var YieldseekerAgent = class {
|
|
|
3274
3300
|
throw this.mapApiError(error);
|
|
3275
3301
|
}
|
|
3276
3302
|
let created;
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3303
|
+
for (let attempt = 0; attempt < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS; attempt += 1) {
|
|
3304
|
+
try {
|
|
3305
|
+
created = await this.providerRequest(
|
|
3306
|
+
state,
|
|
3307
|
+
chainId,
|
|
3308
|
+
"/users",
|
|
3309
|
+
{
|
|
3310
|
+
method: "POST",
|
|
3311
|
+
body: {
|
|
3312
|
+
walletAddress,
|
|
3313
|
+
username: generateYieldseekerUsername()
|
|
3314
|
+
}
|
|
3287
3315
|
}
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3316
|
+
);
|
|
3317
|
+
break;
|
|
3318
|
+
} catch (createError) {
|
|
3319
|
+
const canRetry = isUsernameConflict(createError) && attempt + 1 < YIELDSEEKER_USERNAME_CREATE_ATTEMPTS;
|
|
3320
|
+
if (canRetry) continue;
|
|
3321
|
+
throw this.mapApiError(createError);
|
|
3322
|
+
}
|
|
3292
3323
|
}
|
|
3293
3324
|
user = created?.user ?? null;
|
|
3294
3325
|
}
|
|
@@ -4627,17 +4658,25 @@ var OwneySDK = class {
|
|
|
4627
4658
|
* at a time anyway.
|
|
4628
4659
|
*
|
|
4629
4660
|
* Every agent is attempted even if an earlier one fails, so one declined
|
|
4630
|
-
* signature can't deny the remaining agents their turn.
|
|
4631
|
-
*
|
|
4632
|
-
*
|
|
4661
|
+
* signature can't deny the remaining agents their turn. Once all agents have
|
|
4662
|
+
* had a chance, a partial failure identifies the agents that still need a
|
|
4663
|
+
* retry; if none activated, the original provider error is preserved.
|
|
4633
4664
|
*/
|
|
4634
4665
|
async activateAgentsInTurn(agents, state, chainId, asset) {
|
|
4635
4666
|
let firstError = null;
|
|
4667
|
+
const activatedAgentIds = [];
|
|
4668
|
+
const failedAgents = [];
|
|
4636
4669
|
for (const agent of agents) {
|
|
4637
4670
|
try {
|
|
4638
4671
|
await agent.activateAgent(state, chainId, asset);
|
|
4639
4672
|
await this.applyOrgPolicyTo(agent, state, chainId);
|
|
4673
|
+
activatedAgentIds.push(agent.id);
|
|
4640
4674
|
} catch (error) {
|
|
4675
|
+
failedAgents.push({
|
|
4676
|
+
agentId: agent.id,
|
|
4677
|
+
code: error instanceof OwneyError ? error.code : void 0,
|
|
4678
|
+
message: error instanceof Error ? error.message : String(error)
|
|
4679
|
+
});
|
|
4641
4680
|
if (firstError === null) {
|
|
4642
4681
|
firstError = error;
|
|
4643
4682
|
} else {
|
|
@@ -4645,10 +4684,19 @@ var OwneySDK = class {
|
|
|
4645
4684
|
}
|
|
4646
4685
|
}
|
|
4647
4686
|
}
|
|
4648
|
-
if (firstError
|
|
4687
|
+
if (firstError === null) return;
|
|
4688
|
+
if (activatedAgentIds.length === 0) throw firstError;
|
|
4689
|
+
const failedAgentIds = failedAgents.map(({ agentId }) => agentId);
|
|
4690
|
+
const activeNames = activatedAgentIds.map(this.formatAgentName).join(", ");
|
|
4691
|
+
const remainingNames = failedAgentIds.map(this.formatAgentName).join(", ");
|
|
4692
|
+
throw new OwneyError(
|
|
4693
|
+
"AGENT_ACTIVATION_PARTIAL_FAILURE",
|
|
4694
|
+
`${activeNames} activated, but ${remainingNames} still needs activation. Try again and approve the remaining wallet request.`,
|
|
4695
|
+
{ activatedAgentIds, failedAgentIds, failures: failedAgents }
|
|
4696
|
+
);
|
|
4649
4697
|
}
|
|
4650
4698
|
/**
|
|
4651
|
-
* Deposit funds into a specific agent, or
|
|
4699
|
+
* Deposit funds into a specific agent, or distribute across all agents if agentId is omitted.
|
|
4652
4700
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
4653
4701
|
* @param options - Deposit parameters
|
|
4654
4702
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -4656,7 +4704,8 @@ var OwneySDK = class {
|
|
|
4656
4704
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
4657
4705
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
4658
4706
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
4659
|
-
* @param options.agentId - Optional. Target agent. Omit to
|
|
4707
|
+
* @param options.agentId - Optional. Target agent. Omit to fund all eligible agents. Deposits
|
|
4708
|
+
* are equal once every agent is funded; first/recovery deposits also honor each agent's floor.
|
|
4660
4709
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
4661
4710
|
*/
|
|
4662
4711
|
async deposit(options) {
|
|
@@ -4708,10 +4757,35 @@ var OwneySDK = class {
|
|
|
4708
4757
|
exempt
|
|
4709
4758
|
);
|
|
4710
4759
|
if (agentAmounts.length === 0) {
|
|
4760
|
+
const agentsRequiringActivation = eligibleAgents.filter(
|
|
4761
|
+
(agent) => !exempt.has(agent.id)
|
|
4762
|
+
);
|
|
4763
|
+
const perAgentMinimum = agentsRequiringActivation.reduce(
|
|
4764
|
+
(highest, agent) => {
|
|
4765
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
4766
|
+
return minimum > highest ? minimum : highest;
|
|
4767
|
+
},
|
|
4768
|
+
0n
|
|
4769
|
+
);
|
|
4770
|
+
const minimumRequired = perAgentMinimum * BigInt(agentsRequiringActivation.length);
|
|
4711
4771
|
throw new OwneyError(
|
|
4712
4772
|
"DEPOSIT_AMOUNT_BELOW_MINIMUM",
|
|
4713
|
-
`Amount "${amount}" cannot
|
|
4714
|
-
{
|
|
4773
|
+
`Amount "${amount}" cannot activate every eligible agent. The combined minimum is "${minimumRequired.toString()}" for ${asset}.`,
|
|
4774
|
+
{
|
|
4775
|
+
amount,
|
|
4776
|
+
asset,
|
|
4777
|
+
chainId,
|
|
4778
|
+
minDepositAmount: minimumRequired.toString(),
|
|
4779
|
+
perAgentDepositAmount: perAgentMinimum.toString(),
|
|
4780
|
+
agentMinimums: agentsRequiringActivation.map((agent) => ({
|
|
4781
|
+
agentId: agent.id,
|
|
4782
|
+
minDepositAmount: this.getMinDepositAmount(
|
|
4783
|
+
agent,
|
|
4784
|
+
chainId,
|
|
4785
|
+
asset
|
|
4786
|
+
).toString()
|
|
4787
|
+
}))
|
|
4788
|
+
}
|
|
4715
4789
|
);
|
|
4716
4790
|
}
|
|
4717
4791
|
const agentResults = {};
|
|
@@ -4797,6 +4871,20 @@ var OwneySDK = class {
|
|
|
4797
4871
|
}
|
|
4798
4872
|
splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
|
|
4799
4873
|
if (agents.length === 0) return [];
|
|
4874
|
+
const agentsRequiringActivation = agents.filter(
|
|
4875
|
+
(agent) => !exempt.has(agent.id)
|
|
4876
|
+
);
|
|
4877
|
+
if (agentsRequiringActivation.length === agents.length) {
|
|
4878
|
+
const highestMinimum2 = agents.reduce(
|
|
4879
|
+
(highest, agent) => {
|
|
4880
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
4881
|
+
return minimum > highest ? minimum : highest;
|
|
4882
|
+
},
|
|
4883
|
+
0n
|
|
4884
|
+
);
|
|
4885
|
+
const minimumRequired2 = highestMinimum2 * BigInt(agents.length);
|
|
4886
|
+
if (totalAmount < minimumRequired2) return [];
|
|
4887
|
+
}
|
|
4800
4888
|
const perAgent = totalAmount / BigInt(agents.length);
|
|
4801
4889
|
const remainder = totalAmount % BigInt(agents.length);
|
|
4802
4890
|
const splits = agents.map((agent, i) => ({
|
|
@@ -4809,13 +4897,29 @@ var OwneySDK = class {
|
|
|
4809
4897
|
if (valid2.length === agents.length) {
|
|
4810
4898
|
return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
|
|
4811
4899
|
}
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4900
|
+
const targets = agentsRequiringActivation.length > 0 ? agentsRequiringActivation : valid2.map((s) => s.agent);
|
|
4901
|
+
const highestMinimum = targets.reduce(
|
|
4902
|
+
(highest, agent) => {
|
|
4903
|
+
const minimum = this.getMinDepositAmount(agent, chainId, asset);
|
|
4904
|
+
return minimum > highest ? minimum : highest;
|
|
4905
|
+
},
|
|
4906
|
+
0n
|
|
4818
4907
|
);
|
|
4908
|
+
const minimumRequired = highestMinimum * BigInt(targets.length);
|
|
4909
|
+
if (totalAmount < minimumRequired) return [];
|
|
4910
|
+
const targetShare = totalAmount / BigInt(targets.length);
|
|
4911
|
+
const targetRemainder = totalAmount % BigInt(targets.length);
|
|
4912
|
+
return targets.map((agent, index) => ({
|
|
4913
|
+
agent,
|
|
4914
|
+
amount: String(
|
|
4915
|
+
targetShare + (index === targets.length - 1 ? targetRemainder : 0n)
|
|
4916
|
+
)
|
|
4917
|
+
}));
|
|
4918
|
+
}
|
|
4919
|
+
formatAgentName(agentId) {
|
|
4920
|
+
if (agentId === "zyfai") return "Zyfai";
|
|
4921
|
+
if (agentId === "yieldseeker") return "Yieldseeker";
|
|
4922
|
+
return agentId;
|
|
4819
4923
|
}
|
|
4820
4924
|
async validateMinDepositAmount(agent, state, chainId, asset, amount) {
|
|
4821
4925
|
const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
|
|
@@ -4847,7 +4951,20 @@ var OwneySDK = class {
|
|
|
4847
4951
|
const token = balance.tokens.find(
|
|
4848
4952
|
(t) => t.chainId === chainId && t.asset.toLowerCase() === target
|
|
4849
4953
|
);
|
|
4850
|
-
|
|
4954
|
+
const chainNameById = {
|
|
4955
|
+
1: "ETHEREUM",
|
|
4956
|
+
8453: "BASE",
|
|
4957
|
+
42161: "ARBITRUM"
|
|
4958
|
+
};
|
|
4959
|
+
const targetChainName = chainNameById[chainId];
|
|
4960
|
+
const position2 = (balance.positions ?? []).find(
|
|
4961
|
+
(p) => {
|
|
4962
|
+
const positionChain = p.chain.trim().toUpperCase();
|
|
4963
|
+
const matchesChain = positionChain === String(chainId) || targetChainName !== void 0 && positionChain === targetChainName;
|
|
4964
|
+
return matchesChain && p.asset.toLowerCase() === target && Number(p.amount) > 0;
|
|
4965
|
+
}
|
|
4966
|
+
);
|
|
4967
|
+
return !!token && Number(token.amount) > 0 || !!position2;
|
|
4851
4968
|
} catch {
|
|
4852
4969
|
return false;
|
|
4853
4970
|
}
|
|
@@ -5070,8 +5187,12 @@ var OwneySDK = class {
|
|
|
5070
5187
|
const state = this.requireState();
|
|
5071
5188
|
const chainId = this.requireChainId();
|
|
5072
5189
|
if (agentId) {
|
|
5073
|
-
const
|
|
5074
|
-
|
|
5190
|
+
const agent = this.getAgent(agentId);
|
|
5191
|
+
const result = await agent.getBalances(state, chainId);
|
|
5192
|
+
return {
|
|
5193
|
+
...result,
|
|
5194
|
+
balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
|
|
5195
|
+
};
|
|
5075
5196
|
}
|
|
5076
5197
|
let totalBalance = 0;
|
|
5077
5198
|
const results = {};
|
|
@@ -5079,7 +5200,13 @@ var OwneySDK = class {
|
|
|
5079
5200
|
const balanceResults = await Promise.allSettled(
|
|
5080
5201
|
entries.map(async ([id, agent]) => {
|
|
5081
5202
|
const b = await agent.getBalances(state, chainId);
|
|
5082
|
-
return [
|
|
5203
|
+
return [
|
|
5204
|
+
id,
|
|
5205
|
+
{
|
|
5206
|
+
...b,
|
|
5207
|
+
balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
|
|
5208
|
+
}
|
|
5209
|
+
];
|
|
5083
5210
|
})
|
|
5084
5211
|
);
|
|
5085
5212
|
let successCount = 0;
|