@owney/sdk 0.2.18 → 0.3.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -12
- package/dist/index.cjs +106 -85
- package/dist/index.d.cts +9 -5
- package/dist/index.d.ts +9 -5
- package/dist/index.js +106 -85
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -280,18 +280,12 @@ console.log(apy.walletAddress); // "0x..."
|
|
|
280
280
|
console.log(apy.weightedApyAfterFee); // 5.2
|
|
281
281
|
// Per chain + token breakdown, when the agent reports it
|
|
282
282
|
console.log(apy.weightedApyAfterFeeDetails?.apyPerAsset[8453]?.USDC); // 5.4
|
|
283
|
-
// Same per-(chain, asset) breakdown surfaced under a unified key
|
|
284
|
-
console.log(apy.apyByChainAndAsset?.[8453]?.USDC); // 5.4
|
|
285
283
|
|
|
286
284
|
// All agents (balance-weighted)
|
|
287
285
|
const allApy = await sdk.getAccountApy({ days: "30D" });
|
|
288
286
|
console.log(allApy.totalApy); // "5.6"
|
|
289
287
|
console.log(allApy.agentApy.zyfai.weightedApyAfterFee); // 6.0
|
|
290
288
|
console.log(allApy.agentApy.sail.weightedApyAfterFee); // 4.0
|
|
291
|
-
// Per (chain, asset), balance-weighted across all agents.
|
|
292
|
-
// Cells with 0/missing APY for a given agent are excluded from that cell.
|
|
293
|
-
console.log(allApy.apyByChainAndAsset[8453]?.USDC); // 5.3
|
|
294
|
-
console.log(allApy.apyByChainAndAsset[42161]?.USDT); // 4.7
|
|
295
289
|
```
|
|
296
290
|
|
|
297
291
|
### `getHistory({ agentId?, filters? })`
|
|
@@ -566,21 +560,15 @@ interface OwneyEarnings {
|
|
|
566
560
|
agentEarnings: Record<AgentId, AgentEarnings>;
|
|
567
561
|
}
|
|
568
562
|
|
|
569
|
-
type ApyByChainAndAsset = Partial<
|
|
570
|
-
Record<OwneySupportedChainId, Partial<Record<OwneySupportedTokens, number>>>
|
|
571
|
-
>;
|
|
572
|
-
|
|
573
563
|
interface AccountAgentApy {
|
|
574
564
|
walletAddress: string;
|
|
575
565
|
weightedApyAfterFee?: number;
|
|
576
566
|
weightedApyAfterFeeDetails?: AgentApyDetails;
|
|
577
|
-
apyByChainAndAsset?: ApyByChainAndAsset;
|
|
578
567
|
}
|
|
579
568
|
|
|
580
569
|
interface OwneyAccountApy {
|
|
581
570
|
totalApy: string;
|
|
582
571
|
agentApy: Record<AgentId, AccountAgentApy>;
|
|
583
|
-
apyByChainAndAsset: ApyByChainAndAsset;
|
|
584
572
|
}
|
|
585
573
|
|
|
586
574
|
type HistoryAction = "Rebalance" | "Deposit" | "Top up" | "Withdraw" | "Earned";
|
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,6 @@ var P_SUPPORTED_CHAINS = {
|
|
|
36
36
|
chainIds: [8453, 42161],
|
|
37
37
|
chains: ["BASE", "ARBITRUM"]
|
|
38
38
|
};
|
|
39
|
-
var SUPPORTED_TOKENS = ["USDC", "USDT"];
|
|
40
39
|
var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
|
|
41
40
|
var SUPPORTED_CHAINS = P_SUPPORTED_CHAINS.chains;
|
|
42
41
|
var SupportedAssets = [
|
|
@@ -210,31 +209,10 @@ function mapEarnings(raw, smartWallet) {
|
|
|
210
209
|
tokens
|
|
211
210
|
};
|
|
212
211
|
}
|
|
213
|
-
function mapWeightedApyByChain(raw) {
|
|
214
|
-
if (!raw)
|
|
215
|
-
return void 0;
|
|
216
|
-
const out = {};
|
|
217
|
-
for (const [chainKey, tokenApy] of Object.entries(raw)) {
|
|
218
|
-
const chainId = Number(chainKey);
|
|
219
|
-
if (!SUPPORTED_CHAIN_IDS.includes(chainId))
|
|
220
|
-
continue;
|
|
221
|
-
const perAsset = {};
|
|
222
|
-
for (const [symbol, apy] of Object.entries(tokenApy)) {
|
|
223
|
-
const token = symbol;
|
|
224
|
-
if (!SUPPORTED_TOKENS.includes(token))
|
|
225
|
-
continue;
|
|
226
|
-
perAsset[token] = apy;
|
|
227
|
-
}
|
|
228
|
-
if (Object.keys(perAsset).length > 0)
|
|
229
|
-
out[chainId] = perAsset;
|
|
230
|
-
}
|
|
231
|
-
return Object.keys(out).length > 0 ? out : void 0;
|
|
232
|
-
}
|
|
233
212
|
function mapApyHistory(raw) {
|
|
234
213
|
return {
|
|
235
214
|
walletAddress: raw.walletAddress,
|
|
236
|
-
weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0
|
|
237
|
-
apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain)
|
|
215
|
+
weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0
|
|
238
216
|
};
|
|
239
217
|
}
|
|
240
218
|
function mapHistory(raw, chainId) {
|
|
@@ -578,6 +556,19 @@ async function fetchAgentKeys(apiKey) {
|
|
|
578
556
|
}
|
|
579
557
|
|
|
580
558
|
// src/lib/helpers/withdraw-helper.ts
|
|
559
|
+
var import_viem = require("viem");
|
|
560
|
+
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
561
|
+
const target = asset.toUpperCase();
|
|
562
|
+
return agents.map((agent) => {
|
|
563
|
+
const agentBalance = aggregated[agent.id];
|
|
564
|
+
const tokenBalance = agentBalance?.tokens.find(
|
|
565
|
+
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
566
|
+
);
|
|
567
|
+
if (!tokenBalance)
|
|
568
|
+
return { agent, balance: 0n };
|
|
569
|
+
return { agent, balance: (0, import_viem.parseUnits)(tokenBalance.amount, decimals) };
|
|
570
|
+
});
|
|
571
|
+
}
|
|
581
572
|
function planProportionalShares(balances, requested, totalAvailable) {
|
|
582
573
|
const plans = balances.map(({ agent, balance }) => ({
|
|
583
574
|
agent,
|
|
@@ -602,8 +593,24 @@ function planProportionalShares(balances, requested, totalAvailable) {
|
|
|
602
593
|
}
|
|
603
594
|
return plans;
|
|
604
595
|
}
|
|
605
|
-
function
|
|
606
|
-
const
|
|
596
|
+
function planDisabledDrain(disabled, requested) {
|
|
597
|
+
const sorted = [...disabled].filter((d) => d.balance > 0n).sort((a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0);
|
|
598
|
+
const plans = [];
|
|
599
|
+
let remaining = requested;
|
|
600
|
+
for (const { agent, balance } of sorted) {
|
|
601
|
+
if (remaining === 0n) {
|
|
602
|
+
plans.push({ agent, balance, planned: 0n });
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
const take = balance < remaining ? balance : remaining;
|
|
606
|
+
plans.push({ agent, balance, planned: take });
|
|
607
|
+
remaining -= take;
|
|
608
|
+
}
|
|
609
|
+
return { plans, remaining };
|
|
610
|
+
}
|
|
611
|
+
function redistributeShare(plans, fromIndex, amount, candidatePool) {
|
|
612
|
+
const pool = candidatePool ?? plans.slice(fromIndex + 1);
|
|
613
|
+
const candidates = pool.filter((c) => c.balance - c.planned > 0n);
|
|
607
614
|
const totalHeadroom = candidates.reduce(
|
|
608
615
|
(s, c) => s + (c.balance - c.planned),
|
|
609
616
|
0n
|
|
@@ -634,51 +641,16 @@ function sumWithdrawnAmount(results) {
|
|
|
634
641
|
return Object.values(results).reduce((sum, r) => sum + BigInt(r.amount), 0n);
|
|
635
642
|
}
|
|
636
643
|
|
|
637
|
-
// src/lib/helpers/account-apy-helper.ts
|
|
638
|
-
function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
639
|
-
const sums = {};
|
|
640
|
-
const weights = {};
|
|
641
|
-
for (const id of Object.keys(agentApys)) {
|
|
642
|
-
const cells = agentApys[id].apyByChainAndAsset;
|
|
643
|
-
const balance = agentBalances[id] ?? 0;
|
|
644
|
-
if (!cells || balance <= 0)
|
|
645
|
-
continue;
|
|
646
|
-
for (const [chainKey, perAsset] of Object.entries(cells)) {
|
|
647
|
-
if (!perAsset)
|
|
648
|
-
continue;
|
|
649
|
-
const chainId = Number(chainKey);
|
|
650
|
-
for (const [asset, apyValue] of Object.entries(perAsset)) {
|
|
651
|
-
const apy = Number(apyValue ?? 0);
|
|
652
|
-
if (apy === 0)
|
|
653
|
-
continue;
|
|
654
|
-
sums[chainId] ??= {};
|
|
655
|
-
weights[chainId] ??= {};
|
|
656
|
-
sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
|
|
657
|
-
weights[chainId][asset] = (weights[chainId][asset] ?? 0) + balance;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
}
|
|
661
|
-
const out = {};
|
|
662
|
-
for (const chainKey of Object.keys(sums)) {
|
|
663
|
-
const chainId = Number(chainKey);
|
|
664
|
-
const perAssetOut = {};
|
|
665
|
-
for (const asset of Object.keys(sums[chainId])) {
|
|
666
|
-
const w = weights[chainId][asset];
|
|
667
|
-
if (w > 0)
|
|
668
|
-
perAssetOut[asset] = sums[chainId][asset] / w;
|
|
669
|
-
}
|
|
670
|
-
if (Object.keys(perAssetOut).length > 0) {
|
|
671
|
-
out[chainId] = perAssetOut;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
return out;
|
|
675
|
-
}
|
|
676
|
-
|
|
677
644
|
// src/client.ts
|
|
678
|
-
var import_viem = require("viem");
|
|
679
645
|
var OwneySDK = class {
|
|
680
646
|
agents = /* @__PURE__ */ new Map();
|
|
681
647
|
activeAgents = /* @__PURE__ */ new Set();
|
|
648
|
+
/**
|
|
649
|
+
* Agents whose routing flag is_enabled === false. They remain in
|
|
650
|
+
* `this.agents` and may still be added to `activeAgents` for read +
|
|
651
|
+
* withdraw, but they are excluded from new deposits / activations.
|
|
652
|
+
*/
|
|
653
|
+
disabledAgents = /* @__PURE__ */ new Set();
|
|
682
654
|
state = null;
|
|
683
655
|
apiKey;
|
|
684
656
|
zyfaiRpcUrls;
|
|
@@ -715,8 +687,12 @@ var OwneySDK = class {
|
|
|
715
687
|
await agent.disconnect();
|
|
716
688
|
}
|
|
717
689
|
this.activeAgents.clear();
|
|
690
|
+
this.disabledAgents.clear();
|
|
718
691
|
this.state = null;
|
|
719
692
|
}
|
|
693
|
+
isAgentDisabled(agentId) {
|
|
694
|
+
return this.disabledAgents.has(agentId);
|
|
695
|
+
}
|
|
720
696
|
/**
|
|
721
697
|
* Check if the SDK has an active connection state.
|
|
722
698
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -768,11 +744,15 @@ var OwneySDK = class {
|
|
|
768
744
|
if (!this.initializingAgentsPromise) {
|
|
769
745
|
this.initializingAgentsPromise = (async () => {
|
|
770
746
|
const agentKeys = await fetchAgentKeys(this.apiKey);
|
|
771
|
-
|
|
747
|
+
this.disabledAgents.clear();
|
|
748
|
+
for (const { key, agent_type, is_enabled } of agentKeys) {
|
|
772
749
|
const agent = this.createAgent(agent_type, key);
|
|
773
750
|
if (!agent)
|
|
774
751
|
continue;
|
|
775
752
|
this.agents.set(agent_type, agent);
|
|
753
|
+
if (is_enabled === false) {
|
|
754
|
+
this.disabledAgents.add(agent_type);
|
|
755
|
+
}
|
|
776
756
|
}
|
|
777
757
|
if (this.agents.size === 0) {
|
|
778
758
|
throw new OwneyError(
|
|
@@ -817,6 +797,16 @@ var OwneySDK = class {
|
|
|
817
797
|
}
|
|
818
798
|
const uniqueIds = [...new Set(agentId)];
|
|
819
799
|
const agents = uniqueIds.map((id) => this.getAgent(id));
|
|
800
|
+
const disabledRequested = uniqueIds.filter(
|
|
801
|
+
(id) => this.isAgentDisabled(id)
|
|
802
|
+
);
|
|
803
|
+
if (disabledRequested.length > 0) {
|
|
804
|
+
throw new OwneyError(
|
|
805
|
+
"AGENT_DISABLED",
|
|
806
|
+
`Cannot activate disabled agent(s): ${disabledRequested.join(", ")}.`,
|
|
807
|
+
{ agentIds: disabledRequested }
|
|
808
|
+
);
|
|
809
|
+
}
|
|
820
810
|
const incompatibleAgents = agents.filter(
|
|
821
811
|
(agent) => !agent.supportedChainIds.includes(chainId)
|
|
822
812
|
).map((agent) => ({
|
|
@@ -855,8 +845,11 @@ var OwneySDK = class {
|
|
|
855
845
|
this.activeAgents.add(agent.id);
|
|
856
846
|
}
|
|
857
847
|
state.chainId = chainId;
|
|
848
|
+
const enabledCompatible = compatible.filter(
|
|
849
|
+
(agent) => !this.isAgentDisabled(agent.id)
|
|
850
|
+
);
|
|
858
851
|
Promise.all(
|
|
859
|
-
|
|
852
|
+
enabledCompatible.map(async (agent) => {
|
|
860
853
|
await agent.activateAgent(state, chainId);
|
|
861
854
|
})
|
|
862
855
|
).catch((error) => {
|
|
@@ -883,13 +876,22 @@ var OwneySDK = class {
|
|
|
883
876
|
const state = this.requireState();
|
|
884
877
|
const chainId = this.requireChainId();
|
|
885
878
|
if (agentId) {
|
|
879
|
+
if (this.isAgentDisabled(agentId)) {
|
|
880
|
+
throw new OwneyError(
|
|
881
|
+
"AGENT_DISABLED",
|
|
882
|
+
`Cannot deposit into disabled agent "${agentId}". Existing balances remain visible and withdrawable.`,
|
|
883
|
+
{ agentId }
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
886
|
const agent = this.getAgent(agentId);
|
|
887
887
|
this.validateAssetSupport(agent, chainId, asset);
|
|
888
888
|
this.validateMinDepositAmount(agent, chainId, asset, amount);
|
|
889
889
|
return agent.deposit(state, chainId, amount, depositCallback);
|
|
890
890
|
}
|
|
891
891
|
const totalAmount = BigInt(amount);
|
|
892
|
-
const eligibleAgents = this.getEligibleAgents(chainId, asset
|
|
892
|
+
const eligibleAgents = this.getEligibleAgents(chainId, asset, {
|
|
893
|
+
excludeDisabled: true
|
|
894
|
+
});
|
|
893
895
|
const agentAmounts = this.splitDepositAmount(
|
|
894
896
|
totalAmount,
|
|
895
897
|
eligibleAgents,
|
|
@@ -973,8 +975,11 @@ var OwneySDK = class {
|
|
|
973
975
|
);
|
|
974
976
|
}
|
|
975
977
|
}
|
|
976
|
-
getEligibleAgents(chainId, asset) {
|
|
978
|
+
getEligibleAgents(chainId, asset, opts) {
|
|
977
979
|
const eligible = [...this.agents.values()].filter((agent) => {
|
|
980
|
+
if (opts?.excludeDisabled && this.isAgentDisabled(agent.id)) {
|
|
981
|
+
return false;
|
|
982
|
+
}
|
|
978
983
|
const chainAssets = agent.supportedAssets.find(
|
|
979
984
|
(sa) => sa.chainId === chainId
|
|
980
985
|
);
|
|
@@ -1041,16 +1046,13 @@ var OwneySDK = class {
|
|
|
1041
1046
|
}
|
|
1042
1047
|
const requested = BigInt(amount);
|
|
1043
1048
|
const aggregated = await this.getBalances();
|
|
1044
|
-
const balances =
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
const balance = (0, import_viem.parseUnits)(tokenBalance.amount, assetInfo.decimals);
|
|
1052
|
-
return { agent, balance };
|
|
1053
|
-
});
|
|
1049
|
+
const balances = projectAgentBalancesForAsset(
|
|
1050
|
+
eligibleAgents,
|
|
1051
|
+
aggregated.agentBalances,
|
|
1052
|
+
chainId,
|
|
1053
|
+
asset,
|
|
1054
|
+
assetInfo.decimals
|
|
1055
|
+
);
|
|
1054
1056
|
const totalAvailable = balances.reduce((sum, x) => sum + x.balance, 0n);
|
|
1055
1057
|
if (totalAvailable < requested) {
|
|
1056
1058
|
throw new OwneyError(
|
|
@@ -1063,7 +1065,26 @@ var OwneySDK = class {
|
|
|
1063
1065
|
}
|
|
1064
1066
|
);
|
|
1065
1067
|
}
|
|
1066
|
-
const
|
|
1068
|
+
const disabledBalances = balances.filter(
|
|
1069
|
+
(b) => this.isAgentDisabled(b.agent.id)
|
|
1070
|
+
);
|
|
1071
|
+
const enabledBalances = balances.filter(
|
|
1072
|
+
(b) => !this.isAgentDisabled(b.agent.id)
|
|
1073
|
+
);
|
|
1074
|
+
const { plans: disabledPlans, remaining: afterDrain } = planDisabledDrain(
|
|
1075
|
+
disabledBalances,
|
|
1076
|
+
requested
|
|
1077
|
+
);
|
|
1078
|
+
const enabledTotal = enabledBalances.reduce(
|
|
1079
|
+
(s, b) => s + b.balance,
|
|
1080
|
+
0n
|
|
1081
|
+
);
|
|
1082
|
+
const enabledPlans = afterDrain > 0n ? planProportionalShares(enabledBalances, afterDrain, enabledTotal) : enabledBalances.map(({ agent, balance }) => ({
|
|
1083
|
+
agent,
|
|
1084
|
+
balance,
|
|
1085
|
+
planned: 0n
|
|
1086
|
+
}));
|
|
1087
|
+
const plans = [...disabledPlans, ...enabledPlans];
|
|
1067
1088
|
const results = {};
|
|
1068
1089
|
const agentErrors = {};
|
|
1069
1090
|
for (let i = 0; i < plans.length; i++) {
|
|
@@ -1080,7 +1101,9 @@ var OwneySDK = class {
|
|
|
1080
1101
|
} catch (err) {
|
|
1081
1102
|
console.error(`withdraw failed for agent "${p.agent.id}":`, err);
|
|
1082
1103
|
agentErrors[p.agent.id] = err instanceof Error ? err.message : String(err);
|
|
1083
|
-
|
|
1104
|
+
const failedAmount = p.planned;
|
|
1105
|
+
p.planned = 0n;
|
|
1106
|
+
redistributeShare(plans, i, failedAmount);
|
|
1084
1107
|
}
|
|
1085
1108
|
}
|
|
1086
1109
|
if (Object.keys(results).length === 0) {
|
|
@@ -1246,11 +1269,9 @@ var OwneySDK = class {
|
|
|
1246
1269
|
totalApy += agentApy * weight;
|
|
1247
1270
|
}
|
|
1248
1271
|
}
|
|
1249
|
-
const apyByChainAndAsset = aggregateApyByChainAndAsset(results, balances);
|
|
1250
1272
|
return {
|
|
1251
1273
|
totalApy: String(totalApy),
|
|
1252
|
-
agentApy: results
|
|
1253
|
-
apyByChainAndAsset
|
|
1274
|
+
agentApy: results
|
|
1254
1275
|
};
|
|
1255
1276
|
}
|
|
1256
1277
|
/**
|
package/dist/index.d.cts
CHANGED
|
@@ -139,17 +139,14 @@ interface OwneyEarnings {
|
|
|
139
139
|
totalEarnings: string;
|
|
140
140
|
agentEarnings: Record<AgentId, AgentEarnings>;
|
|
141
141
|
}
|
|
142
|
-
type ApyByChainAndAsset = Partial<Record<OwneySupportedChainId, Partial<Record<OwneySupportedTokens, number>>>>;
|
|
143
142
|
interface AccountAgentApy {
|
|
144
143
|
walletAddress: string;
|
|
145
144
|
weightedApyAfterFee?: number;
|
|
146
145
|
weightedApyAfterFeeDetails?: AgentApyDetails;
|
|
147
|
-
apyByChainAndAsset?: ApyByChainAndAsset;
|
|
148
146
|
}
|
|
149
147
|
interface OwneyAccountApy {
|
|
150
148
|
totalApy: string;
|
|
151
149
|
agentApy: Record<AgentId, AccountAgentApy>;
|
|
152
|
-
apyByChainAndAsset: ApyByChainAndAsset;
|
|
153
150
|
}
|
|
154
151
|
type HistoryAction = "Rebalance" | "Deposit" | "Top up" | "Withdraw" | "Earned";
|
|
155
152
|
interface HistoryTransaction {
|
|
@@ -211,6 +208,12 @@ interface OwneyAgentAllocation {
|
|
|
211
208
|
declare class OwneySDK {
|
|
212
209
|
private agents;
|
|
213
210
|
private activeAgents;
|
|
211
|
+
/**
|
|
212
|
+
* Agents whose routing flag is_enabled === false. They remain in
|
|
213
|
+
* `this.agents` and may still be added to `activeAgents` for read +
|
|
214
|
+
* withdraw, but they are excluded from new deposits / activations.
|
|
215
|
+
*/
|
|
216
|
+
private disabledAgents;
|
|
214
217
|
private state;
|
|
215
218
|
private apiKey;
|
|
216
219
|
private zyfaiRpcUrls?;
|
|
@@ -227,6 +230,7 @@ declare class OwneySDK {
|
|
|
227
230
|
* After calling this, `connect()` must be called again before using agent methods.
|
|
228
231
|
*/
|
|
229
232
|
disconnect(): Promise<void>;
|
|
233
|
+
private isAgentDisabled;
|
|
230
234
|
/**
|
|
231
235
|
* Check if the SDK has an active connection state.
|
|
232
236
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -349,7 +353,7 @@ declare class OwneySDK {
|
|
|
349
353
|
getAgentAllocation(): Promise<OwneyAgentAllocation>;
|
|
350
354
|
}
|
|
351
355
|
|
|
352
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
356
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
353
357
|
declare class OwneyError extends Error {
|
|
354
358
|
readonly code: OwneyErrorCode;
|
|
355
359
|
readonly details?: Record<string, unknown>;
|
|
@@ -374,4 +378,4 @@ declare class AgentChainIncompatibleError extends OwneyError {
|
|
|
374
378
|
}>, connectedChainId: number);
|
|
375
379
|
}
|
|
376
380
|
|
|
377
|
-
export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions,
|
|
381
|
+
export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAgentStatus, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneySDK, OwneySDKConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -139,17 +139,14 @@ interface OwneyEarnings {
|
|
|
139
139
|
totalEarnings: string;
|
|
140
140
|
agentEarnings: Record<AgentId, AgentEarnings>;
|
|
141
141
|
}
|
|
142
|
-
type ApyByChainAndAsset = Partial<Record<OwneySupportedChainId, Partial<Record<OwneySupportedTokens, number>>>>;
|
|
143
142
|
interface AccountAgentApy {
|
|
144
143
|
walletAddress: string;
|
|
145
144
|
weightedApyAfterFee?: number;
|
|
146
145
|
weightedApyAfterFeeDetails?: AgentApyDetails;
|
|
147
|
-
apyByChainAndAsset?: ApyByChainAndAsset;
|
|
148
146
|
}
|
|
149
147
|
interface OwneyAccountApy {
|
|
150
148
|
totalApy: string;
|
|
151
149
|
agentApy: Record<AgentId, AccountAgentApy>;
|
|
152
|
-
apyByChainAndAsset: ApyByChainAndAsset;
|
|
153
150
|
}
|
|
154
151
|
type HistoryAction = "Rebalance" | "Deposit" | "Top up" | "Withdraw" | "Earned";
|
|
155
152
|
interface HistoryTransaction {
|
|
@@ -211,6 +208,12 @@ interface OwneyAgentAllocation {
|
|
|
211
208
|
declare class OwneySDK {
|
|
212
209
|
private agents;
|
|
213
210
|
private activeAgents;
|
|
211
|
+
/**
|
|
212
|
+
* Agents whose routing flag is_enabled === false. They remain in
|
|
213
|
+
* `this.agents` and may still be added to `activeAgents` for read +
|
|
214
|
+
* withdraw, but they are excluded from new deposits / activations.
|
|
215
|
+
*/
|
|
216
|
+
private disabledAgents;
|
|
214
217
|
private state;
|
|
215
218
|
private apiKey;
|
|
216
219
|
private zyfaiRpcUrls?;
|
|
@@ -227,6 +230,7 @@ declare class OwneySDK {
|
|
|
227
230
|
* After calling this, `connect()` must be called again before using agent methods.
|
|
228
231
|
*/
|
|
229
232
|
disconnect(): Promise<void>;
|
|
233
|
+
private isAgentDisabled;
|
|
230
234
|
/**
|
|
231
235
|
* Check if the SDK has an active connection state.
|
|
232
236
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -349,7 +353,7 @@ declare class OwneySDK {
|
|
|
349
353
|
getAgentAllocation(): Promise<OwneyAgentAllocation>;
|
|
350
354
|
}
|
|
351
355
|
|
|
352
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
356
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
353
357
|
declare class OwneyError extends Error {
|
|
354
358
|
readonly code: OwneyErrorCode;
|
|
355
359
|
readonly details?: Record<string, unknown>;
|
|
@@ -374,4 +378,4 @@ declare class AgentChainIncompatibleError extends OwneyError {
|
|
|
374
378
|
}>, connectedChainId: number);
|
|
375
379
|
}
|
|
376
380
|
|
|
377
|
-
export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions,
|
|
381
|
+
export { AccountAgentApy, AccountApyOptions, AgentApy, AgentApyDetails, AgentBalance, AgentChainIncompatibleError, AgentEarnings, AgentHistoryEntry, AgentId, AgentNotFoundError, AgentSupportedAsset, AgentSupportedAssets, AgentUserProfile, AgentWithdrawResult, AgentsApyOptions, Asset, ConnectionState, DailyApyDays, DepositCallback, DepositOptions, HistoryAction, HistoryFilters, HistoryOptions, HistoryTransaction, IAgent, NotConnectedError, OwneyAccountApy, OwneyAgentAllocation, OwneyAgentApy, OwneyAgentHistory, OwneyAgentStatus, OwneyBalances, OwneyDepositResult, OwneyEarnings, OwneyError, OwneyErrorCode, OwneyMultiDepositResult, OwneySDK, OwneySDKConfig, OwneySupportedChainId, OwneySupportedChains, OwneySupportedTokens, OwneyToken, OwneyUserProfile, OwneyWithdrawResult, RebalanceLog, WithdrawOptions };
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,6 @@ var P_SUPPORTED_CHAINS = {
|
|
|
6
6
|
chainIds: [8453, 42161],
|
|
7
7
|
chains: ["BASE", "ARBITRUM"]
|
|
8
8
|
};
|
|
9
|
-
var SUPPORTED_TOKENS = ["USDC", "USDT"];
|
|
10
9
|
var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
|
|
11
10
|
var SUPPORTED_CHAINS = P_SUPPORTED_CHAINS.chains;
|
|
12
11
|
var SupportedAssets = [
|
|
@@ -180,31 +179,10 @@ function mapEarnings(raw, smartWallet) {
|
|
|
180
179
|
tokens
|
|
181
180
|
};
|
|
182
181
|
}
|
|
183
|
-
function mapWeightedApyByChain(raw) {
|
|
184
|
-
if (!raw)
|
|
185
|
-
return void 0;
|
|
186
|
-
const out = {};
|
|
187
|
-
for (const [chainKey, tokenApy] of Object.entries(raw)) {
|
|
188
|
-
const chainId = Number(chainKey);
|
|
189
|
-
if (!SUPPORTED_CHAIN_IDS.includes(chainId))
|
|
190
|
-
continue;
|
|
191
|
-
const perAsset = {};
|
|
192
|
-
for (const [symbol, apy] of Object.entries(tokenApy)) {
|
|
193
|
-
const token = symbol;
|
|
194
|
-
if (!SUPPORTED_TOKENS.includes(token))
|
|
195
|
-
continue;
|
|
196
|
-
perAsset[token] = apy;
|
|
197
|
-
}
|
|
198
|
-
if (Object.keys(perAsset).length > 0)
|
|
199
|
-
out[chainId] = perAsset;
|
|
200
|
-
}
|
|
201
|
-
return Object.keys(out).length > 0 ? out : void 0;
|
|
202
|
-
}
|
|
203
182
|
function mapApyHistory(raw) {
|
|
204
183
|
return {
|
|
205
184
|
walletAddress: raw.walletAddress,
|
|
206
|
-
weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0
|
|
207
|
-
apyByChainAndAsset: mapWeightedApyByChain(raw.weightedApyAfterFeeByChain)
|
|
185
|
+
weightedApyAfterFee: raw.weightedApyAfterFee ? sumTokenValues(raw.weightedApyAfterFee) : void 0
|
|
208
186
|
};
|
|
209
187
|
}
|
|
210
188
|
function mapHistory(raw, chainId) {
|
|
@@ -548,6 +526,19 @@ async function fetchAgentKeys(apiKey) {
|
|
|
548
526
|
}
|
|
549
527
|
|
|
550
528
|
// src/lib/helpers/withdraw-helper.ts
|
|
529
|
+
import { parseUnits } from "viem";
|
|
530
|
+
function projectAgentBalancesForAsset(agents, aggregated, chainId, asset, decimals) {
|
|
531
|
+
const target = asset.toUpperCase();
|
|
532
|
+
return agents.map((agent) => {
|
|
533
|
+
const agentBalance = aggregated[agent.id];
|
|
534
|
+
const tokenBalance = agentBalance?.tokens.find(
|
|
535
|
+
(t) => t.chainId === chainId && t.asset.toUpperCase() === target
|
|
536
|
+
);
|
|
537
|
+
if (!tokenBalance)
|
|
538
|
+
return { agent, balance: 0n };
|
|
539
|
+
return { agent, balance: parseUnits(tokenBalance.amount, decimals) };
|
|
540
|
+
});
|
|
541
|
+
}
|
|
551
542
|
function planProportionalShares(balances, requested, totalAvailable) {
|
|
552
543
|
const plans = balances.map(({ agent, balance }) => ({
|
|
553
544
|
agent,
|
|
@@ -572,8 +563,24 @@ function planProportionalShares(balances, requested, totalAvailable) {
|
|
|
572
563
|
}
|
|
573
564
|
return plans;
|
|
574
565
|
}
|
|
575
|
-
function
|
|
576
|
-
const
|
|
566
|
+
function planDisabledDrain(disabled, requested) {
|
|
567
|
+
const sorted = [...disabled].filter((d) => d.balance > 0n).sort((a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0);
|
|
568
|
+
const plans = [];
|
|
569
|
+
let remaining = requested;
|
|
570
|
+
for (const { agent, balance } of sorted) {
|
|
571
|
+
if (remaining === 0n) {
|
|
572
|
+
plans.push({ agent, balance, planned: 0n });
|
|
573
|
+
continue;
|
|
574
|
+
}
|
|
575
|
+
const take = balance < remaining ? balance : remaining;
|
|
576
|
+
plans.push({ agent, balance, planned: take });
|
|
577
|
+
remaining -= take;
|
|
578
|
+
}
|
|
579
|
+
return { plans, remaining };
|
|
580
|
+
}
|
|
581
|
+
function redistributeShare(plans, fromIndex, amount, candidatePool) {
|
|
582
|
+
const pool = candidatePool ?? plans.slice(fromIndex + 1);
|
|
583
|
+
const candidates = pool.filter((c) => c.balance - c.planned > 0n);
|
|
577
584
|
const totalHeadroom = candidates.reduce(
|
|
578
585
|
(s, c) => s + (c.balance - c.planned),
|
|
579
586
|
0n
|
|
@@ -604,51 +611,16 @@ function sumWithdrawnAmount(results) {
|
|
|
604
611
|
return Object.values(results).reduce((sum, r) => sum + BigInt(r.amount), 0n);
|
|
605
612
|
}
|
|
606
613
|
|
|
607
|
-
// src/lib/helpers/account-apy-helper.ts
|
|
608
|
-
function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
609
|
-
const sums = {};
|
|
610
|
-
const weights = {};
|
|
611
|
-
for (const id of Object.keys(agentApys)) {
|
|
612
|
-
const cells = agentApys[id].apyByChainAndAsset;
|
|
613
|
-
const balance = agentBalances[id] ?? 0;
|
|
614
|
-
if (!cells || balance <= 0)
|
|
615
|
-
continue;
|
|
616
|
-
for (const [chainKey, perAsset] of Object.entries(cells)) {
|
|
617
|
-
if (!perAsset)
|
|
618
|
-
continue;
|
|
619
|
-
const chainId = Number(chainKey);
|
|
620
|
-
for (const [asset, apyValue] of Object.entries(perAsset)) {
|
|
621
|
-
const apy = Number(apyValue ?? 0);
|
|
622
|
-
if (apy === 0)
|
|
623
|
-
continue;
|
|
624
|
-
sums[chainId] ??= {};
|
|
625
|
-
weights[chainId] ??= {};
|
|
626
|
-
sums[chainId][asset] = (sums[chainId][asset] ?? 0) + apy * balance;
|
|
627
|
-
weights[chainId][asset] = (weights[chainId][asset] ?? 0) + balance;
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
const out = {};
|
|
632
|
-
for (const chainKey of Object.keys(sums)) {
|
|
633
|
-
const chainId = Number(chainKey);
|
|
634
|
-
const perAssetOut = {};
|
|
635
|
-
for (const asset of Object.keys(sums[chainId])) {
|
|
636
|
-
const w = weights[chainId][asset];
|
|
637
|
-
if (w > 0)
|
|
638
|
-
perAssetOut[asset] = sums[chainId][asset] / w;
|
|
639
|
-
}
|
|
640
|
-
if (Object.keys(perAssetOut).length > 0) {
|
|
641
|
-
out[chainId] = perAssetOut;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
return out;
|
|
645
|
-
}
|
|
646
|
-
|
|
647
614
|
// src/client.ts
|
|
648
|
-
import { parseUnits } from "viem";
|
|
649
615
|
var OwneySDK = class {
|
|
650
616
|
agents = /* @__PURE__ */ new Map();
|
|
651
617
|
activeAgents = /* @__PURE__ */ new Set();
|
|
618
|
+
/**
|
|
619
|
+
* Agents whose routing flag is_enabled === false. They remain in
|
|
620
|
+
* `this.agents` and may still be added to `activeAgents` for read +
|
|
621
|
+
* withdraw, but they are excluded from new deposits / activations.
|
|
622
|
+
*/
|
|
623
|
+
disabledAgents = /* @__PURE__ */ new Set();
|
|
652
624
|
state = null;
|
|
653
625
|
apiKey;
|
|
654
626
|
zyfaiRpcUrls;
|
|
@@ -685,8 +657,12 @@ var OwneySDK = class {
|
|
|
685
657
|
await agent.disconnect();
|
|
686
658
|
}
|
|
687
659
|
this.activeAgents.clear();
|
|
660
|
+
this.disabledAgents.clear();
|
|
688
661
|
this.state = null;
|
|
689
662
|
}
|
|
663
|
+
isAgentDisabled(agentId) {
|
|
664
|
+
return this.disabledAgents.has(agentId);
|
|
665
|
+
}
|
|
690
666
|
/**
|
|
691
667
|
* Check if the SDK has an active connection state.
|
|
692
668
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -738,11 +714,15 @@ var OwneySDK = class {
|
|
|
738
714
|
if (!this.initializingAgentsPromise) {
|
|
739
715
|
this.initializingAgentsPromise = (async () => {
|
|
740
716
|
const agentKeys = await fetchAgentKeys(this.apiKey);
|
|
741
|
-
|
|
717
|
+
this.disabledAgents.clear();
|
|
718
|
+
for (const { key, agent_type, is_enabled } of agentKeys) {
|
|
742
719
|
const agent = this.createAgent(agent_type, key);
|
|
743
720
|
if (!agent)
|
|
744
721
|
continue;
|
|
745
722
|
this.agents.set(agent_type, agent);
|
|
723
|
+
if (is_enabled === false) {
|
|
724
|
+
this.disabledAgents.add(agent_type);
|
|
725
|
+
}
|
|
746
726
|
}
|
|
747
727
|
if (this.agents.size === 0) {
|
|
748
728
|
throw new OwneyError(
|
|
@@ -787,6 +767,16 @@ var OwneySDK = class {
|
|
|
787
767
|
}
|
|
788
768
|
const uniqueIds = [...new Set(agentId)];
|
|
789
769
|
const agents = uniqueIds.map((id) => this.getAgent(id));
|
|
770
|
+
const disabledRequested = uniqueIds.filter(
|
|
771
|
+
(id) => this.isAgentDisabled(id)
|
|
772
|
+
);
|
|
773
|
+
if (disabledRequested.length > 0) {
|
|
774
|
+
throw new OwneyError(
|
|
775
|
+
"AGENT_DISABLED",
|
|
776
|
+
`Cannot activate disabled agent(s): ${disabledRequested.join(", ")}.`,
|
|
777
|
+
{ agentIds: disabledRequested }
|
|
778
|
+
);
|
|
779
|
+
}
|
|
790
780
|
const incompatibleAgents = agents.filter(
|
|
791
781
|
(agent) => !agent.supportedChainIds.includes(chainId)
|
|
792
782
|
).map((agent) => ({
|
|
@@ -825,8 +815,11 @@ var OwneySDK = class {
|
|
|
825
815
|
this.activeAgents.add(agent.id);
|
|
826
816
|
}
|
|
827
817
|
state.chainId = chainId;
|
|
818
|
+
const enabledCompatible = compatible.filter(
|
|
819
|
+
(agent) => !this.isAgentDisabled(agent.id)
|
|
820
|
+
);
|
|
828
821
|
Promise.all(
|
|
829
|
-
|
|
822
|
+
enabledCompatible.map(async (agent) => {
|
|
830
823
|
await agent.activateAgent(state, chainId);
|
|
831
824
|
})
|
|
832
825
|
).catch((error) => {
|
|
@@ -853,13 +846,22 @@ var OwneySDK = class {
|
|
|
853
846
|
const state = this.requireState();
|
|
854
847
|
const chainId = this.requireChainId();
|
|
855
848
|
if (agentId) {
|
|
849
|
+
if (this.isAgentDisabled(agentId)) {
|
|
850
|
+
throw new OwneyError(
|
|
851
|
+
"AGENT_DISABLED",
|
|
852
|
+
`Cannot deposit into disabled agent "${agentId}". Existing balances remain visible and withdrawable.`,
|
|
853
|
+
{ agentId }
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
856
|
const agent = this.getAgent(agentId);
|
|
857
857
|
this.validateAssetSupport(agent, chainId, asset);
|
|
858
858
|
this.validateMinDepositAmount(agent, chainId, asset, amount);
|
|
859
859
|
return agent.deposit(state, chainId, amount, depositCallback);
|
|
860
860
|
}
|
|
861
861
|
const totalAmount = BigInt(amount);
|
|
862
|
-
const eligibleAgents = this.getEligibleAgents(chainId, asset
|
|
862
|
+
const eligibleAgents = this.getEligibleAgents(chainId, asset, {
|
|
863
|
+
excludeDisabled: true
|
|
864
|
+
});
|
|
863
865
|
const agentAmounts = this.splitDepositAmount(
|
|
864
866
|
totalAmount,
|
|
865
867
|
eligibleAgents,
|
|
@@ -943,8 +945,11 @@ var OwneySDK = class {
|
|
|
943
945
|
);
|
|
944
946
|
}
|
|
945
947
|
}
|
|
946
|
-
getEligibleAgents(chainId, asset) {
|
|
948
|
+
getEligibleAgents(chainId, asset, opts) {
|
|
947
949
|
const eligible = [...this.agents.values()].filter((agent) => {
|
|
950
|
+
if (opts?.excludeDisabled && this.isAgentDisabled(agent.id)) {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
948
953
|
const chainAssets = agent.supportedAssets.find(
|
|
949
954
|
(sa) => sa.chainId === chainId
|
|
950
955
|
);
|
|
@@ -1011,16 +1016,13 @@ var OwneySDK = class {
|
|
|
1011
1016
|
}
|
|
1012
1017
|
const requested = BigInt(amount);
|
|
1013
1018
|
const aggregated = await this.getBalances();
|
|
1014
|
-
const balances =
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
const balance = parseUnits(tokenBalance.amount, assetInfo.decimals);
|
|
1022
|
-
return { agent, balance };
|
|
1023
|
-
});
|
|
1019
|
+
const balances = projectAgentBalancesForAsset(
|
|
1020
|
+
eligibleAgents,
|
|
1021
|
+
aggregated.agentBalances,
|
|
1022
|
+
chainId,
|
|
1023
|
+
asset,
|
|
1024
|
+
assetInfo.decimals
|
|
1025
|
+
);
|
|
1024
1026
|
const totalAvailable = balances.reduce((sum, x) => sum + x.balance, 0n);
|
|
1025
1027
|
if (totalAvailable < requested) {
|
|
1026
1028
|
throw new OwneyError(
|
|
@@ -1033,7 +1035,26 @@ var OwneySDK = class {
|
|
|
1033
1035
|
}
|
|
1034
1036
|
);
|
|
1035
1037
|
}
|
|
1036
|
-
const
|
|
1038
|
+
const disabledBalances = balances.filter(
|
|
1039
|
+
(b) => this.isAgentDisabled(b.agent.id)
|
|
1040
|
+
);
|
|
1041
|
+
const enabledBalances = balances.filter(
|
|
1042
|
+
(b) => !this.isAgentDisabled(b.agent.id)
|
|
1043
|
+
);
|
|
1044
|
+
const { plans: disabledPlans, remaining: afterDrain } = planDisabledDrain(
|
|
1045
|
+
disabledBalances,
|
|
1046
|
+
requested
|
|
1047
|
+
);
|
|
1048
|
+
const enabledTotal = enabledBalances.reduce(
|
|
1049
|
+
(s, b) => s + b.balance,
|
|
1050
|
+
0n
|
|
1051
|
+
);
|
|
1052
|
+
const enabledPlans = afterDrain > 0n ? planProportionalShares(enabledBalances, afterDrain, enabledTotal) : enabledBalances.map(({ agent, balance }) => ({
|
|
1053
|
+
agent,
|
|
1054
|
+
balance,
|
|
1055
|
+
planned: 0n
|
|
1056
|
+
}));
|
|
1057
|
+
const plans = [...disabledPlans, ...enabledPlans];
|
|
1037
1058
|
const results = {};
|
|
1038
1059
|
const agentErrors = {};
|
|
1039
1060
|
for (let i = 0; i < plans.length; i++) {
|
|
@@ -1050,7 +1071,9 @@ var OwneySDK = class {
|
|
|
1050
1071
|
} catch (err) {
|
|
1051
1072
|
console.error(`withdraw failed for agent "${p.agent.id}":`, err);
|
|
1052
1073
|
agentErrors[p.agent.id] = err instanceof Error ? err.message : String(err);
|
|
1053
|
-
|
|
1074
|
+
const failedAmount = p.planned;
|
|
1075
|
+
p.planned = 0n;
|
|
1076
|
+
redistributeShare(plans, i, failedAmount);
|
|
1054
1077
|
}
|
|
1055
1078
|
}
|
|
1056
1079
|
if (Object.keys(results).length === 0) {
|
|
@@ -1216,11 +1239,9 @@ var OwneySDK = class {
|
|
|
1216
1239
|
totalApy += agentApy * weight;
|
|
1217
1240
|
}
|
|
1218
1241
|
}
|
|
1219
|
-
const apyByChainAndAsset = aggregateApyByChainAndAsset(results, balances);
|
|
1220
1242
|
return {
|
|
1221
1243
|
totalApy: String(totalApy),
|
|
1222
|
-
agentApy: results
|
|
1223
|
-
apyByChainAndAsset
|
|
1244
|
+
agentApy: results
|
|
1224
1245
|
};
|
|
1225
1246
|
}
|
|
1226
1247
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owney/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-beta.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -17,16 +17,19 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsup",
|
|
20
|
-
"dev": "tsup --watch"
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest"
|
|
21
23
|
},
|
|
22
24
|
"dependencies": {
|
|
23
|
-
"@zyfai/sdk": "^0.2.
|
|
25
|
+
"@zyfai/sdk": "^0.2.33",
|
|
24
26
|
"viem": "^2.48.1"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
29
|
"dotenv": "^17.3.1",
|
|
28
30
|
"tsup": "^7.0.0",
|
|
29
|
-
"typescript": "^5.0.0"
|
|
31
|
+
"typescript": "^5.0.0",
|
|
32
|
+
"vitest": "^4.1.5"
|
|
30
33
|
},
|
|
31
34
|
"publishConfig": {
|
|
32
35
|
"access": "public"
|