@owney/sdk 0.7.16-beta.4 → 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 +132 -22
- package/dist/index.d.cts +15 -6
- package/dist/index.d.ts +15 -6
- package/dist/index.js +132 -22
- 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"),
|
|
@@ -4661,17 +4675,25 @@ var OwneySDK = class {
|
|
|
4661
4675
|
* at a time anyway.
|
|
4662
4676
|
*
|
|
4663
4677
|
* Every agent is attempted even if an earlier one fails, so one declined
|
|
4664
|
-
* signature can't deny the remaining agents their turn.
|
|
4665
|
-
*
|
|
4666
|
-
*
|
|
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.
|
|
4667
4681
|
*/
|
|
4668
4682
|
async activateAgentsInTurn(agents, state, chainId, asset) {
|
|
4669
4683
|
let firstError = null;
|
|
4684
|
+
const activatedAgentIds = [];
|
|
4685
|
+
const failedAgents = [];
|
|
4670
4686
|
for (const agent of agents) {
|
|
4671
4687
|
try {
|
|
4672
4688
|
await agent.activateAgent(state, chainId, asset);
|
|
4673
4689
|
await this.applyOrgPolicyTo(agent, state, chainId);
|
|
4690
|
+
activatedAgentIds.push(agent.id);
|
|
4674
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
|
+
});
|
|
4675
4697
|
if (firstError === null) {
|
|
4676
4698
|
firstError = error;
|
|
4677
4699
|
} else {
|
|
@@ -4679,10 +4701,19 @@ var OwneySDK = class {
|
|
|
4679
4701
|
}
|
|
4680
4702
|
}
|
|
4681
4703
|
}
|
|
4682
|
-
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
|
+
);
|
|
4683
4714
|
}
|
|
4684
4715
|
/**
|
|
4685
|
-
* Deposit funds into a specific agent, or
|
|
4716
|
+
* Deposit funds into a specific agent, or distribute across all agents if agentId is omitted.
|
|
4686
4717
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
4687
4718
|
* @param options - Deposit parameters
|
|
4688
4719
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -4690,7 +4721,8 @@ var OwneySDK = class {
|
|
|
4690
4721
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
4691
4722
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
4692
4723
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
4693
|
-
* @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.
|
|
4694
4726
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
4695
4727
|
*/
|
|
4696
4728
|
async deposit(options) {
|
|
@@ -4742,10 +4774,35 @@ var OwneySDK = class {
|
|
|
4742
4774
|
exempt
|
|
4743
4775
|
);
|
|
4744
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);
|
|
4745
4788
|
throw new OwneyError(
|
|
4746
4789
|
"DEPOSIT_AMOUNT_BELOW_MINIMUM",
|
|
4747
|
-
`Amount "${amount}" cannot
|
|
4748
|
-
{
|
|
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
|
+
}
|
|
4749
4806
|
);
|
|
4750
4807
|
}
|
|
4751
4808
|
const agentResults = {};
|
|
@@ -4831,6 +4888,20 @@ var OwneySDK = class {
|
|
|
4831
4888
|
}
|
|
4832
4889
|
splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
|
|
4833
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
|
+
}
|
|
4834
4905
|
const perAgent = totalAmount / BigInt(agents.length);
|
|
4835
4906
|
const remainder = totalAmount % BigInt(agents.length);
|
|
4836
4907
|
const splits = agents.map((agent, i) => ({
|
|
@@ -4843,13 +4914,29 @@ var OwneySDK = class {
|
|
|
4843
4914
|
if (valid2.length === agents.length) {
|
|
4844
4915
|
return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
|
|
4845
4916
|
}
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
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
|
|
4852
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;
|
|
4853
4940
|
}
|
|
4854
4941
|
async validateMinDepositAmount(agent, state, chainId, asset, amount) {
|
|
4855
4942
|
const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
|
|
@@ -4881,7 +4968,20 @@ var OwneySDK = class {
|
|
|
4881
4968
|
const token = balance.tokens.find(
|
|
4882
4969
|
(t) => t.chainId === chainId && t.asset.toLowerCase() === target
|
|
4883
4970
|
);
|
|
4884
|
-
|
|
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;
|
|
4885
4985
|
} catch {
|
|
4886
4986
|
return false;
|
|
4887
4987
|
}
|
|
@@ -5104,8 +5204,12 @@ var OwneySDK = class {
|
|
|
5104
5204
|
const state = this.requireState();
|
|
5105
5205
|
const chainId = this.requireChainId();
|
|
5106
5206
|
if (agentId) {
|
|
5107
|
-
const
|
|
5108
|
-
|
|
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
|
+
};
|
|
5109
5213
|
}
|
|
5110
5214
|
let totalBalance = 0;
|
|
5111
5215
|
const results = {};
|
|
@@ -5113,7 +5217,13 @@ var OwneySDK = class {
|
|
|
5113
5217
|
const balanceResults = await Promise.allSettled(
|
|
5114
5218
|
entries.map(async ([id, agent]) => {
|
|
5115
5219
|
const b = await agent.getBalances(state, chainId);
|
|
5116
|
-
return [
|
|
5220
|
+
return [
|
|
5221
|
+
id,
|
|
5222
|
+
{
|
|
5223
|
+
...b,
|
|
5224
|
+
balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
|
|
5225
|
+
}
|
|
5226
|
+
];
|
|
5117
5227
|
})
|
|
5118
5228
|
);
|
|
5119
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"),
|
|
@@ -4644,17 +4658,25 @@ var OwneySDK = class {
|
|
|
4644
4658
|
* at a time anyway.
|
|
4645
4659
|
*
|
|
4646
4660
|
* 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
|
-
*
|
|
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.
|
|
4650
4664
|
*/
|
|
4651
4665
|
async activateAgentsInTurn(agents, state, chainId, asset) {
|
|
4652
4666
|
let firstError = null;
|
|
4667
|
+
const activatedAgentIds = [];
|
|
4668
|
+
const failedAgents = [];
|
|
4653
4669
|
for (const agent of agents) {
|
|
4654
4670
|
try {
|
|
4655
4671
|
await agent.activateAgent(state, chainId, asset);
|
|
4656
4672
|
await this.applyOrgPolicyTo(agent, state, chainId);
|
|
4673
|
+
activatedAgentIds.push(agent.id);
|
|
4657
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
|
+
});
|
|
4658
4680
|
if (firstError === null) {
|
|
4659
4681
|
firstError = error;
|
|
4660
4682
|
} else {
|
|
@@ -4662,10 +4684,19 @@ var OwneySDK = class {
|
|
|
4662
4684
|
}
|
|
4663
4685
|
}
|
|
4664
4686
|
}
|
|
4665
|
-
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
|
+
);
|
|
4666
4697
|
}
|
|
4667
4698
|
/**
|
|
4668
|
-
* Deposit funds into a specific agent, or
|
|
4699
|
+
* Deposit funds into a specific agent, or distribute across all agents if agentId is omitted.
|
|
4669
4700
|
* Validates that the asset is supported and amount meets minimums for the target agent(s).
|
|
4670
4701
|
* @param options - Deposit parameters
|
|
4671
4702
|
* @param options.amount - Amount to deposit in smallest unit (e.g. "100000000" for 100 USDC)
|
|
@@ -4673,7 +4704,8 @@ var OwneySDK = class {
|
|
|
4673
4704
|
* @param options.depositCallback - Callback that performs the token transfer and returns a tx hash.
|
|
4674
4705
|
* When agentId is omitted, this callback is invoked once per eligible agent with that agent's
|
|
4675
4706
|
* split amount and smart wallet address — expect multiple wallet prompts.
|
|
4676
|
-
* @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.
|
|
4677
4709
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
4678
4710
|
*/
|
|
4679
4711
|
async deposit(options) {
|
|
@@ -4725,10 +4757,35 @@ var OwneySDK = class {
|
|
|
4725
4757
|
exempt
|
|
4726
4758
|
);
|
|
4727
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);
|
|
4728
4771
|
throw new OwneyError(
|
|
4729
4772
|
"DEPOSIT_AMOUNT_BELOW_MINIMUM",
|
|
4730
|
-
`Amount "${amount}" cannot
|
|
4731
|
-
{
|
|
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
|
+
}
|
|
4732
4789
|
);
|
|
4733
4790
|
}
|
|
4734
4791
|
const agentResults = {};
|
|
@@ -4814,6 +4871,20 @@ var OwneySDK = class {
|
|
|
4814
4871
|
}
|
|
4815
4872
|
splitDepositAmount(totalAmount, agents, chainId, asset, exempt = /* @__PURE__ */ new Set()) {
|
|
4816
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
|
+
}
|
|
4817
4888
|
const perAgent = totalAmount / BigInt(agents.length);
|
|
4818
4889
|
const remainder = totalAmount % BigInt(agents.length);
|
|
4819
4890
|
const splits = agents.map((agent, i) => ({
|
|
@@ -4826,13 +4897,29 @@ var OwneySDK = class {
|
|
|
4826
4897
|
if (valid2.length === agents.length) {
|
|
4827
4898
|
return splits.map((s) => ({ agent: s.agent, amount: String(s.amount) }));
|
|
4828
4899
|
}
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
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
|
|
4835
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;
|
|
4836
4923
|
}
|
|
4837
4924
|
async validateMinDepositAmount(agent, state, chainId, asset, amount) {
|
|
4838
4925
|
const minDepositAmount = this.getMinDepositAmount(agent, chainId, asset);
|
|
@@ -4864,7 +4951,20 @@ var OwneySDK = class {
|
|
|
4864
4951
|
const token = balance.tokens.find(
|
|
4865
4952
|
(t) => t.chainId === chainId && t.asset.toLowerCase() === target
|
|
4866
4953
|
);
|
|
4867
|
-
|
|
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;
|
|
4868
4968
|
} catch {
|
|
4869
4969
|
return false;
|
|
4870
4970
|
}
|
|
@@ -5087,8 +5187,12 @@ var OwneySDK = class {
|
|
|
5087
5187
|
const state = this.requireState();
|
|
5088
5188
|
const chainId = this.requireChainId();
|
|
5089
5189
|
if (agentId) {
|
|
5090
|
-
const
|
|
5091
|
-
|
|
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
|
+
};
|
|
5092
5196
|
}
|
|
5093
5197
|
let totalBalance = 0;
|
|
5094
5198
|
const results = {};
|
|
@@ -5096,7 +5200,13 @@ var OwneySDK = class {
|
|
|
5096
5200
|
const balanceResults = await Promise.allSettled(
|
|
5097
5201
|
entries.map(async ([id, agent]) => {
|
|
5098
5202
|
const b = await agent.getBalances(state, chainId);
|
|
5099
|
-
return [
|
|
5203
|
+
return [
|
|
5204
|
+
id,
|
|
5205
|
+
{
|
|
5206
|
+
...b,
|
|
5207
|
+
balanceComposition: agent.balanceComposition ?? "tokens-include-positions"
|
|
5208
|
+
}
|
|
5209
|
+
];
|
|
5100
5210
|
})
|
|
5101
5211
|
);
|
|
5102
5212
|
let successCount = 0;
|