@owney/sdk 0.2.17 → 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/dist/index.cjs +104 -19
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +104 -19
- package/package.json +7 -4
package/dist/index.cjs
CHANGED
|
@@ -556,6 +556,19 @@ async function fetchAgentKeys(apiKey) {
|
|
|
556
556
|
}
|
|
557
557
|
|
|
558
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
|
+
}
|
|
559
572
|
function planProportionalShares(balances, requested, totalAvailable) {
|
|
560
573
|
const plans = balances.map(({ agent, balance }) => ({
|
|
561
574
|
agent,
|
|
@@ -580,8 +593,24 @@ function planProportionalShares(balances, requested, totalAvailable) {
|
|
|
580
593
|
}
|
|
581
594
|
return plans;
|
|
582
595
|
}
|
|
583
|
-
function
|
|
584
|
-
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);
|
|
585
614
|
const totalHeadroom = candidates.reduce(
|
|
586
615
|
(s, c) => s + (c.balance - c.planned),
|
|
587
616
|
0n
|
|
@@ -613,10 +642,15 @@ function sumWithdrawnAmount(results) {
|
|
|
613
642
|
}
|
|
614
643
|
|
|
615
644
|
// src/client.ts
|
|
616
|
-
var import_viem = require("viem");
|
|
617
645
|
var OwneySDK = class {
|
|
618
646
|
agents = /* @__PURE__ */ new Map();
|
|
619
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();
|
|
620
654
|
state = null;
|
|
621
655
|
apiKey;
|
|
622
656
|
zyfaiRpcUrls;
|
|
@@ -653,8 +687,12 @@ var OwneySDK = class {
|
|
|
653
687
|
await agent.disconnect();
|
|
654
688
|
}
|
|
655
689
|
this.activeAgents.clear();
|
|
690
|
+
this.disabledAgents.clear();
|
|
656
691
|
this.state = null;
|
|
657
692
|
}
|
|
693
|
+
isAgentDisabled(agentId) {
|
|
694
|
+
return this.disabledAgents.has(agentId);
|
|
695
|
+
}
|
|
658
696
|
/**
|
|
659
697
|
* Check if the SDK has an active connection state.
|
|
660
698
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -706,11 +744,15 @@ var OwneySDK = class {
|
|
|
706
744
|
if (!this.initializingAgentsPromise) {
|
|
707
745
|
this.initializingAgentsPromise = (async () => {
|
|
708
746
|
const agentKeys = await fetchAgentKeys(this.apiKey);
|
|
709
|
-
|
|
747
|
+
this.disabledAgents.clear();
|
|
748
|
+
for (const { key, agent_type, is_enabled } of agentKeys) {
|
|
710
749
|
const agent = this.createAgent(agent_type, key);
|
|
711
750
|
if (!agent)
|
|
712
751
|
continue;
|
|
713
752
|
this.agents.set(agent_type, agent);
|
|
753
|
+
if (is_enabled === false) {
|
|
754
|
+
this.disabledAgents.add(agent_type);
|
|
755
|
+
}
|
|
714
756
|
}
|
|
715
757
|
if (this.agents.size === 0) {
|
|
716
758
|
throw new OwneyError(
|
|
@@ -755,6 +797,16 @@ var OwneySDK = class {
|
|
|
755
797
|
}
|
|
756
798
|
const uniqueIds = [...new Set(agentId)];
|
|
757
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
|
+
}
|
|
758
810
|
const incompatibleAgents = agents.filter(
|
|
759
811
|
(agent) => !agent.supportedChainIds.includes(chainId)
|
|
760
812
|
).map((agent) => ({
|
|
@@ -793,8 +845,11 @@ var OwneySDK = class {
|
|
|
793
845
|
this.activeAgents.add(agent.id);
|
|
794
846
|
}
|
|
795
847
|
state.chainId = chainId;
|
|
848
|
+
const enabledCompatible = compatible.filter(
|
|
849
|
+
(agent) => !this.isAgentDisabled(agent.id)
|
|
850
|
+
);
|
|
796
851
|
Promise.all(
|
|
797
|
-
|
|
852
|
+
enabledCompatible.map(async (agent) => {
|
|
798
853
|
await agent.activateAgent(state, chainId);
|
|
799
854
|
})
|
|
800
855
|
).catch((error) => {
|
|
@@ -821,13 +876,22 @@ var OwneySDK = class {
|
|
|
821
876
|
const state = this.requireState();
|
|
822
877
|
const chainId = this.requireChainId();
|
|
823
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
|
+
}
|
|
824
886
|
const agent = this.getAgent(agentId);
|
|
825
887
|
this.validateAssetSupport(agent, chainId, asset);
|
|
826
888
|
this.validateMinDepositAmount(agent, chainId, asset, amount);
|
|
827
889
|
return agent.deposit(state, chainId, amount, depositCallback);
|
|
828
890
|
}
|
|
829
891
|
const totalAmount = BigInt(amount);
|
|
830
|
-
const eligibleAgents = this.getEligibleAgents(chainId, asset
|
|
892
|
+
const eligibleAgents = this.getEligibleAgents(chainId, asset, {
|
|
893
|
+
excludeDisabled: true
|
|
894
|
+
});
|
|
831
895
|
const agentAmounts = this.splitDepositAmount(
|
|
832
896
|
totalAmount,
|
|
833
897
|
eligibleAgents,
|
|
@@ -911,8 +975,11 @@ var OwneySDK = class {
|
|
|
911
975
|
);
|
|
912
976
|
}
|
|
913
977
|
}
|
|
914
|
-
getEligibleAgents(chainId, asset) {
|
|
978
|
+
getEligibleAgents(chainId, asset, opts) {
|
|
915
979
|
const eligible = [...this.agents.values()].filter((agent) => {
|
|
980
|
+
if (opts?.excludeDisabled && this.isAgentDisabled(agent.id)) {
|
|
981
|
+
return false;
|
|
982
|
+
}
|
|
916
983
|
const chainAssets = agent.supportedAssets.find(
|
|
917
984
|
(sa) => sa.chainId === chainId
|
|
918
985
|
);
|
|
@@ -979,16 +1046,13 @@ var OwneySDK = class {
|
|
|
979
1046
|
}
|
|
980
1047
|
const requested = BigInt(amount);
|
|
981
1048
|
const aggregated = await this.getBalances();
|
|
982
|
-
const balances =
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
const balance = (0, import_viem.parseUnits)(tokenBalance.amount, assetInfo.decimals);
|
|
990
|
-
return { agent, balance };
|
|
991
|
-
});
|
|
1049
|
+
const balances = projectAgentBalancesForAsset(
|
|
1050
|
+
eligibleAgents,
|
|
1051
|
+
aggregated.agentBalances,
|
|
1052
|
+
chainId,
|
|
1053
|
+
asset,
|
|
1054
|
+
assetInfo.decimals
|
|
1055
|
+
);
|
|
992
1056
|
const totalAvailable = balances.reduce((sum, x) => sum + x.balance, 0n);
|
|
993
1057
|
if (totalAvailable < requested) {
|
|
994
1058
|
throw new OwneyError(
|
|
@@ -1001,7 +1065,26 @@ var OwneySDK = class {
|
|
|
1001
1065
|
}
|
|
1002
1066
|
);
|
|
1003
1067
|
}
|
|
1004
|
-
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];
|
|
1005
1088
|
const results = {};
|
|
1006
1089
|
const agentErrors = {};
|
|
1007
1090
|
for (let i = 0; i < plans.length; i++) {
|
|
@@ -1018,7 +1101,9 @@ var OwneySDK = class {
|
|
|
1018
1101
|
} catch (err) {
|
|
1019
1102
|
console.error(`withdraw failed for agent "${p.agent.id}":`, err);
|
|
1020
1103
|
agentErrors[p.agent.id] = err instanceof Error ? err.message : String(err);
|
|
1021
|
-
|
|
1104
|
+
const failedAmount = p.planned;
|
|
1105
|
+
p.planned = 0n;
|
|
1106
|
+
redistributeShare(plans, i, failedAmount);
|
|
1022
1107
|
}
|
|
1023
1108
|
}
|
|
1024
1109
|
if (Object.keys(results).length === 0) {
|
package/dist/index.d.cts
CHANGED
|
@@ -208,6 +208,12 @@ interface OwneyAgentAllocation {
|
|
|
208
208
|
declare class OwneySDK {
|
|
209
209
|
private agents;
|
|
210
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;
|
|
211
217
|
private state;
|
|
212
218
|
private apiKey;
|
|
213
219
|
private zyfaiRpcUrls?;
|
|
@@ -224,6 +230,7 @@ declare class OwneySDK {
|
|
|
224
230
|
* After calling this, `connect()` must be called again before using agent methods.
|
|
225
231
|
*/
|
|
226
232
|
disconnect(): Promise<void>;
|
|
233
|
+
private isAgentDisabled;
|
|
227
234
|
/**
|
|
228
235
|
* Check if the SDK has an active connection state.
|
|
229
236
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -346,7 +353,7 @@ declare class OwneySDK {
|
|
|
346
353
|
getAgentAllocation(): Promise<OwneyAgentAllocation>;
|
|
347
354
|
}
|
|
348
355
|
|
|
349
|
-
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";
|
|
350
357
|
declare class OwneyError extends Error {
|
|
351
358
|
readonly code: OwneyErrorCode;
|
|
352
359
|
readonly details?: Record<string, unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -208,6 +208,12 @@ interface OwneyAgentAllocation {
|
|
|
208
208
|
declare class OwneySDK {
|
|
209
209
|
private agents;
|
|
210
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;
|
|
211
217
|
private state;
|
|
212
218
|
private apiKey;
|
|
213
219
|
private zyfaiRpcUrls?;
|
|
@@ -224,6 +230,7 @@ declare class OwneySDK {
|
|
|
224
230
|
* After calling this, `connect()` must be called again before using agent methods.
|
|
225
231
|
*/
|
|
226
232
|
disconnect(): Promise<void>;
|
|
233
|
+
private isAgentDisabled;
|
|
227
234
|
/**
|
|
228
235
|
* Check if the SDK has an active connection state.
|
|
229
236
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -346,7 +353,7 @@ declare class OwneySDK {
|
|
|
346
353
|
getAgentAllocation(): Promise<OwneyAgentAllocation>;
|
|
347
354
|
}
|
|
348
355
|
|
|
349
|
-
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";
|
|
350
357
|
declare class OwneyError extends Error {
|
|
351
358
|
readonly code: OwneyErrorCode;
|
|
352
359
|
readonly details?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -526,6 +526,19 @@ async function fetchAgentKeys(apiKey) {
|
|
|
526
526
|
}
|
|
527
527
|
|
|
528
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
|
+
}
|
|
529
542
|
function planProportionalShares(balances, requested, totalAvailable) {
|
|
530
543
|
const plans = balances.map(({ agent, balance }) => ({
|
|
531
544
|
agent,
|
|
@@ -550,8 +563,24 @@ function planProportionalShares(balances, requested, totalAvailable) {
|
|
|
550
563
|
}
|
|
551
564
|
return plans;
|
|
552
565
|
}
|
|
553
|
-
function
|
|
554
|
-
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);
|
|
555
584
|
const totalHeadroom = candidates.reduce(
|
|
556
585
|
(s, c) => s + (c.balance - c.planned),
|
|
557
586
|
0n
|
|
@@ -583,10 +612,15 @@ function sumWithdrawnAmount(results) {
|
|
|
583
612
|
}
|
|
584
613
|
|
|
585
614
|
// src/client.ts
|
|
586
|
-
import { parseUnits } from "viem";
|
|
587
615
|
var OwneySDK = class {
|
|
588
616
|
agents = /* @__PURE__ */ new Map();
|
|
589
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();
|
|
590
624
|
state = null;
|
|
591
625
|
apiKey;
|
|
592
626
|
zyfaiRpcUrls;
|
|
@@ -623,8 +657,12 @@ var OwneySDK = class {
|
|
|
623
657
|
await agent.disconnect();
|
|
624
658
|
}
|
|
625
659
|
this.activeAgents.clear();
|
|
660
|
+
this.disabledAgents.clear();
|
|
626
661
|
this.state = null;
|
|
627
662
|
}
|
|
663
|
+
isAgentDisabled(agentId) {
|
|
664
|
+
return this.disabledAgents.has(agentId);
|
|
665
|
+
}
|
|
628
666
|
/**
|
|
629
667
|
* Check if the SDK has an active connection state.
|
|
630
668
|
* @returns `true` if `connect()` has been called and `disconnect()` has not
|
|
@@ -676,11 +714,15 @@ var OwneySDK = class {
|
|
|
676
714
|
if (!this.initializingAgentsPromise) {
|
|
677
715
|
this.initializingAgentsPromise = (async () => {
|
|
678
716
|
const agentKeys = await fetchAgentKeys(this.apiKey);
|
|
679
|
-
|
|
717
|
+
this.disabledAgents.clear();
|
|
718
|
+
for (const { key, agent_type, is_enabled } of agentKeys) {
|
|
680
719
|
const agent = this.createAgent(agent_type, key);
|
|
681
720
|
if (!agent)
|
|
682
721
|
continue;
|
|
683
722
|
this.agents.set(agent_type, agent);
|
|
723
|
+
if (is_enabled === false) {
|
|
724
|
+
this.disabledAgents.add(agent_type);
|
|
725
|
+
}
|
|
684
726
|
}
|
|
685
727
|
if (this.agents.size === 0) {
|
|
686
728
|
throw new OwneyError(
|
|
@@ -725,6 +767,16 @@ var OwneySDK = class {
|
|
|
725
767
|
}
|
|
726
768
|
const uniqueIds = [...new Set(agentId)];
|
|
727
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
|
+
}
|
|
728
780
|
const incompatibleAgents = agents.filter(
|
|
729
781
|
(agent) => !agent.supportedChainIds.includes(chainId)
|
|
730
782
|
).map((agent) => ({
|
|
@@ -763,8 +815,11 @@ var OwneySDK = class {
|
|
|
763
815
|
this.activeAgents.add(agent.id);
|
|
764
816
|
}
|
|
765
817
|
state.chainId = chainId;
|
|
818
|
+
const enabledCompatible = compatible.filter(
|
|
819
|
+
(agent) => !this.isAgentDisabled(agent.id)
|
|
820
|
+
);
|
|
766
821
|
Promise.all(
|
|
767
|
-
|
|
822
|
+
enabledCompatible.map(async (agent) => {
|
|
768
823
|
await agent.activateAgent(state, chainId);
|
|
769
824
|
})
|
|
770
825
|
).catch((error) => {
|
|
@@ -791,13 +846,22 @@ var OwneySDK = class {
|
|
|
791
846
|
const state = this.requireState();
|
|
792
847
|
const chainId = this.requireChainId();
|
|
793
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
|
+
}
|
|
794
856
|
const agent = this.getAgent(agentId);
|
|
795
857
|
this.validateAssetSupport(agent, chainId, asset);
|
|
796
858
|
this.validateMinDepositAmount(agent, chainId, asset, amount);
|
|
797
859
|
return agent.deposit(state, chainId, amount, depositCallback);
|
|
798
860
|
}
|
|
799
861
|
const totalAmount = BigInt(amount);
|
|
800
|
-
const eligibleAgents = this.getEligibleAgents(chainId, asset
|
|
862
|
+
const eligibleAgents = this.getEligibleAgents(chainId, asset, {
|
|
863
|
+
excludeDisabled: true
|
|
864
|
+
});
|
|
801
865
|
const agentAmounts = this.splitDepositAmount(
|
|
802
866
|
totalAmount,
|
|
803
867
|
eligibleAgents,
|
|
@@ -881,8 +945,11 @@ var OwneySDK = class {
|
|
|
881
945
|
);
|
|
882
946
|
}
|
|
883
947
|
}
|
|
884
|
-
getEligibleAgents(chainId, asset) {
|
|
948
|
+
getEligibleAgents(chainId, asset, opts) {
|
|
885
949
|
const eligible = [...this.agents.values()].filter((agent) => {
|
|
950
|
+
if (opts?.excludeDisabled && this.isAgentDisabled(agent.id)) {
|
|
951
|
+
return false;
|
|
952
|
+
}
|
|
886
953
|
const chainAssets = agent.supportedAssets.find(
|
|
887
954
|
(sa) => sa.chainId === chainId
|
|
888
955
|
);
|
|
@@ -949,16 +1016,13 @@ var OwneySDK = class {
|
|
|
949
1016
|
}
|
|
950
1017
|
const requested = BigInt(amount);
|
|
951
1018
|
const aggregated = await this.getBalances();
|
|
952
|
-
const balances =
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
const balance = parseUnits(tokenBalance.amount, assetInfo.decimals);
|
|
960
|
-
return { agent, balance };
|
|
961
|
-
});
|
|
1019
|
+
const balances = projectAgentBalancesForAsset(
|
|
1020
|
+
eligibleAgents,
|
|
1021
|
+
aggregated.agentBalances,
|
|
1022
|
+
chainId,
|
|
1023
|
+
asset,
|
|
1024
|
+
assetInfo.decimals
|
|
1025
|
+
);
|
|
962
1026
|
const totalAvailable = balances.reduce((sum, x) => sum + x.balance, 0n);
|
|
963
1027
|
if (totalAvailable < requested) {
|
|
964
1028
|
throw new OwneyError(
|
|
@@ -971,7 +1035,26 @@ var OwneySDK = class {
|
|
|
971
1035
|
}
|
|
972
1036
|
);
|
|
973
1037
|
}
|
|
974
|
-
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];
|
|
975
1058
|
const results = {};
|
|
976
1059
|
const agentErrors = {};
|
|
977
1060
|
for (let i = 0; i < plans.length; i++) {
|
|
@@ -988,7 +1071,9 @@ var OwneySDK = class {
|
|
|
988
1071
|
} catch (err) {
|
|
989
1072
|
console.error(`withdraw failed for agent "${p.agent.id}":`, err);
|
|
990
1073
|
agentErrors[p.agent.id] = err instanceof Error ? err.message : String(err);
|
|
991
|
-
|
|
1074
|
+
const failedAmount = p.planned;
|
|
1075
|
+
p.planned = 0n;
|
|
1076
|
+
redistributeShare(plans, i, failedAmount);
|
|
992
1077
|
}
|
|
993
1078
|
}
|
|
994
1079
|
if (Object.keys(results).length === 0) {
|
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"
|