@owney/sdk 0.6.0-beta.0 → 0.6.0-beta.1
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 +20 -67
- package/dist/index.cjs +355 -57
- package/dist/index.d.cts +136 -104
- package/dist/index.d.ts +136 -104
- package/dist/index.js +357 -55
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ var P_SUPPORTED_CHAINS = {
|
|
|
6
6
|
chainIds: [8453, 42161],
|
|
7
7
|
chains: ["BASE", "ARBITRUM"]
|
|
8
8
|
};
|
|
9
|
-
var SUPPORTED_TOKENS = ["USDC", "USDT"];
|
|
9
|
+
var SUPPORTED_TOKENS = ["USDC", "USDT", "WETH"];
|
|
10
10
|
var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
|
|
11
11
|
var SUPPORTED_CHAINS = P_SUPPORTED_CHAINS.chains;
|
|
12
12
|
var SupportedAssets = [
|
|
@@ -27,6 +27,18 @@ var SupportedAssets = [
|
|
|
27
27
|
symbol: "USDT",
|
|
28
28
|
chainId: 42161,
|
|
29
29
|
decimals: 6
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
address: `0x4200000000000000000000000000000000000006`,
|
|
33
|
+
symbol: "WETH",
|
|
34
|
+
chainId: 8453,
|
|
35
|
+
decimals: 18
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
address: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`,
|
|
39
|
+
symbol: "WETH",
|
|
40
|
+
chainId: 42161,
|
|
41
|
+
decimals: 18
|
|
30
42
|
}
|
|
31
43
|
];
|
|
32
44
|
|
|
@@ -125,6 +137,18 @@ var CHAIN_ID_TO_NAME = {
|
|
|
125
137
|
8453: "BASE",
|
|
126
138
|
42161: "ARBITRUM"
|
|
127
139
|
};
|
|
140
|
+
var NAME_TO_CHAIN_ID = Object.entries(
|
|
141
|
+
CHAIN_ID_TO_NAME
|
|
142
|
+
).reduce((acc, [id, name]) => {
|
|
143
|
+
acc[name.toLowerCase()] = Number(id);
|
|
144
|
+
return acc;
|
|
145
|
+
}, {});
|
|
146
|
+
function resolveChainId(chain) {
|
|
147
|
+
const asNum = Number(chain);
|
|
148
|
+
if (Number.isFinite(asNum) && asNum > 0)
|
|
149
|
+
return asNum;
|
|
150
|
+
return NAME_TO_CHAIN_ID[chain.trim().toLowerCase()] ?? NaN;
|
|
151
|
+
}
|
|
128
152
|
function mapBalances(raw, _chainId, smartWallet) {
|
|
129
153
|
const portfolio = raw.portfolio;
|
|
130
154
|
const portfolioByChain = portfolio.portfolioByChain ?? {};
|
|
@@ -145,10 +169,27 @@ function mapBalances(raw, _chainId, smartWallet) {
|
|
|
145
169
|
});
|
|
146
170
|
}
|
|
147
171
|
}
|
|
172
|
+
const positions = (portfolio.positions ?? []).map((p) => ({
|
|
173
|
+
chain: p.chain ?? "",
|
|
174
|
+
protocol: p.protocol_name ?? p.protocol_id ?? "",
|
|
175
|
+
protocolId: p.protocol_id,
|
|
176
|
+
pool: p.pool,
|
|
177
|
+
asset: p.token_symbol ?? "",
|
|
178
|
+
// Position amount is hex-encoded base units (like the token balances
|
|
179
|
+
// above). Supported assets (USDC/USDT) are 6-decimal — hexToDecimal's
|
|
180
|
+
// default — so no per-token decimals lookup is needed.
|
|
181
|
+
amount: String(hexToDecimal(p.amount || "0")),
|
|
182
|
+
apy: p.pool_apy,
|
|
183
|
+
tvl: p.pool_tvl,
|
|
184
|
+
// PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
|
|
185
|
+
// structural read keeps it undefined today and auto-populates later.
|
|
186
|
+
liquidity: p.liquidity
|
|
187
|
+
}));
|
|
148
188
|
return {
|
|
149
189
|
smartWallet,
|
|
150
190
|
totalBalance: String(totalBalance),
|
|
151
|
-
tokens
|
|
191
|
+
tokens,
|
|
192
|
+
positions
|
|
152
193
|
};
|
|
153
194
|
}
|
|
154
195
|
function sumTokenValues(tokens) {
|
|
@@ -256,13 +297,6 @@ function mapEntries(rawEntries, chainId) {
|
|
|
256
297
|
};
|
|
257
298
|
});
|
|
258
299
|
}
|
|
259
|
-
function mapAgentStatus(raw) {
|
|
260
|
-
return {
|
|
261
|
-
success: raw.success,
|
|
262
|
-
strategy: raw.strategy,
|
|
263
|
-
protocols: raw.protocols
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
300
|
function mapUserProfile(raw, userAddress) {
|
|
267
301
|
return {
|
|
268
302
|
address: userAddress,
|
|
@@ -298,6 +332,46 @@ function mapApyByStrategy(raw) {
|
|
|
298
332
|
detailedApys: hasDetails ? { apyPerAsset } : void 0
|
|
299
333
|
};
|
|
300
334
|
}
|
|
335
|
+
function computeAllocationApy(positions) {
|
|
336
|
+
let weightedSum = 0;
|
|
337
|
+
let totalValue = 0;
|
|
338
|
+
const buckets = {};
|
|
339
|
+
for (const p of positions) {
|
|
340
|
+
const apy = p.apy;
|
|
341
|
+
const value = Number(p.amount);
|
|
342
|
+
if (typeof apy !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
weightedSum += apy * value;
|
|
346
|
+
totalValue += value;
|
|
347
|
+
const chainId = resolveChainId(p.chain);
|
|
348
|
+
const token = p.asset;
|
|
349
|
+
if (!SUPPORTED_CHAIN_IDS.includes(chainId))
|
|
350
|
+
continue;
|
|
351
|
+
if (!SUPPORTED_TOKENS.includes(token))
|
|
352
|
+
continue;
|
|
353
|
+
const perAsset = buckets[chainId] ?? {};
|
|
354
|
+
const cell = perAsset[token] ?? { weightedSum: 0, value: 0 };
|
|
355
|
+
cell.weightedSum += apy * value;
|
|
356
|
+
cell.value += value;
|
|
357
|
+
perAsset[token] = cell;
|
|
358
|
+
buckets[chainId] = perAsset;
|
|
359
|
+
}
|
|
360
|
+
const apyByChainAndAsset = {};
|
|
361
|
+
for (const [chainKey, perAsset] of Object.entries(buckets)) {
|
|
362
|
+
const chainId = Number(chainKey);
|
|
363
|
+
const out = {};
|
|
364
|
+
for (const [token, cell] of Object.entries(perAsset ?? {})) {
|
|
365
|
+
if (cell && cell.value > 0) {
|
|
366
|
+
out[token] = cell.weightedSum / cell.value;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (Object.keys(out).length > 0)
|
|
370
|
+
apyByChainAndAsset[chainId] = out;
|
|
371
|
+
}
|
|
372
|
+
const totalApy = totalValue > 0 ? String(weightedSum / totalValue) : "0";
|
|
373
|
+
return { totalApy, apyByChainAndAsset };
|
|
374
|
+
}
|
|
301
375
|
|
|
302
376
|
// src/agents/zyfai/zyfai.history-cursor.ts
|
|
303
377
|
var InvalidHistoryCursorError = class extends Error {
|
|
@@ -397,6 +471,10 @@ var DEFAULT_ZYFAI_RPC_URLS = {
|
|
|
397
471
|
8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
398
472
|
42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
|
|
399
473
|
};
|
|
474
|
+
var WETH_ADDRESS_BY_CHAIN = {
|
|
475
|
+
8453: "0x4200000000000000000000000000000000000006",
|
|
476
|
+
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
|
|
477
|
+
};
|
|
400
478
|
var ZyfaiAgent = class {
|
|
401
479
|
id = "zyfai";
|
|
402
480
|
supportedChainIds = [8453, 42161];
|
|
@@ -404,12 +482,18 @@ var ZyfaiAgent = class {
|
|
|
404
482
|
{
|
|
405
483
|
chainId: 8453,
|
|
406
484
|
chain: "BASE",
|
|
407
|
-
assets: [
|
|
485
|
+
assets: [
|
|
486
|
+
{ symbol: "USDC", minDepositAmount: "1500000" },
|
|
487
|
+
{ symbol: "WETH", minDepositAmount: "500000000000000" }
|
|
488
|
+
]
|
|
408
489
|
},
|
|
409
490
|
{
|
|
410
491
|
chainId: 42161,
|
|
411
492
|
chain: "ARBITRUM",
|
|
412
|
-
assets: [
|
|
493
|
+
assets: [
|
|
494
|
+
{ symbol: "USDC", minDepositAmount: "1500000" },
|
|
495
|
+
{ symbol: "WETH", minDepositAmount: "500000000000000" }
|
|
496
|
+
]
|
|
413
497
|
}
|
|
414
498
|
];
|
|
415
499
|
sdk;
|
|
@@ -575,7 +659,7 @@ var ZyfaiAgent = class {
|
|
|
575
659
|
throw error;
|
|
576
660
|
}
|
|
577
661
|
}
|
|
578
|
-
async deposit(state, chainId, amount, depositCallback) {
|
|
662
|
+
async deposit(state, chainId, amount, asset, depositCallback) {
|
|
579
663
|
try {
|
|
580
664
|
await this.connectFull(state, chainId);
|
|
581
665
|
const validChainId = isValidChainId(chainId);
|
|
@@ -589,13 +673,15 @@ var ZyfaiAgent = class {
|
|
|
589
673
|
validChainId,
|
|
590
674
|
amount
|
|
591
675
|
);
|
|
592
|
-
|
|
676
|
+
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
677
|
+
await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
|
|
593
678
|
return { txHash, smartWallet: wallet.address, amount };
|
|
594
679
|
}
|
|
595
680
|
const raw = await this.sdk.depositFunds(
|
|
596
681
|
this.getAddress(),
|
|
597
682
|
validChainId,
|
|
598
|
-
amount
|
|
683
|
+
amount,
|
|
684
|
+
asset
|
|
599
685
|
);
|
|
600
686
|
return mapDeposit(raw);
|
|
601
687
|
} catch (error) {
|
|
@@ -680,17 +766,6 @@ var ZyfaiAgent = class {
|
|
|
680
766
|
nextCursor
|
|
681
767
|
};
|
|
682
768
|
}
|
|
683
|
-
// --- IAgent: Agent control ---
|
|
684
|
-
async pause(state, chainId) {
|
|
685
|
-
await this.connectAuth(state, chainId);
|
|
686
|
-
const raw = await this.sdk.pauseAgent();
|
|
687
|
-
return mapAgentStatus(raw);
|
|
688
|
-
}
|
|
689
|
-
async resume(state, chainId) {
|
|
690
|
-
await this.connectAuth(state, chainId);
|
|
691
|
-
const raw = await this.sdk.resumeAgent();
|
|
692
|
-
return mapAgentStatus(raw);
|
|
693
|
-
}
|
|
694
769
|
async getUserProfile(state, chainId) {
|
|
695
770
|
await this.connectAuth(state, chainId);
|
|
696
771
|
const validChainId = isValidChainId(chainId);
|
|
@@ -902,6 +977,134 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
902
977
|
return out;
|
|
903
978
|
}
|
|
904
979
|
|
|
980
|
+
// src/client.ts
|
|
981
|
+
import {
|
|
982
|
+
createPublicClient,
|
|
983
|
+
createWalletClient,
|
|
984
|
+
custom
|
|
985
|
+
} from "viem";
|
|
986
|
+
import { base, arbitrum } from "viem/chains";
|
|
987
|
+
|
|
988
|
+
// src/lib/transfer-auth.ts
|
|
989
|
+
import { bytesToHex } from "viem";
|
|
990
|
+
var ERC20_META_ABI = [
|
|
991
|
+
{ type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
|
|
992
|
+
{ type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
|
|
993
|
+
];
|
|
994
|
+
function buildTransferWithAuthorizationTypedData(input) {
|
|
995
|
+
return {
|
|
996
|
+
domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
|
|
997
|
+
types: {
|
|
998
|
+
TransferWithAuthorization: [
|
|
999
|
+
{ name: "from", type: "address" },
|
|
1000
|
+
{ name: "to", type: "address" },
|
|
1001
|
+
{ name: "value", type: "uint256" },
|
|
1002
|
+
{ name: "validAfter", type: "uint256" },
|
|
1003
|
+
{ name: "validBefore", type: "uint256" },
|
|
1004
|
+
{ name: "nonce", type: "bytes32" }
|
|
1005
|
+
]
|
|
1006
|
+
},
|
|
1007
|
+
primaryType: "TransferWithAuthorization",
|
|
1008
|
+
message: input.message
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
async function readTokenMeta(publicClient, token) {
|
|
1012
|
+
const [tokenName, tokenVersion] = await Promise.all([
|
|
1013
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
|
|
1014
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
|
|
1015
|
+
]);
|
|
1016
|
+
return { tokenName, tokenVersion };
|
|
1017
|
+
}
|
|
1018
|
+
function randomAuthNonce() {
|
|
1019
|
+
const bytes = new Uint8Array(32);
|
|
1020
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
1021
|
+
return bytesToHex(bytes);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// src/lib/sponsor-client.ts
|
|
1025
|
+
var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
1026
|
+
async function postSponsorTransferAuth(input) {
|
|
1027
|
+
const base2 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
1028
|
+
let res;
|
|
1029
|
+
try {
|
|
1030
|
+
res = await fetch(`${base2}/api/v1/sponsor/erc20-transfer-auth`, {
|
|
1031
|
+
method: "POST",
|
|
1032
|
+
headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey },
|
|
1033
|
+
body: JSON.stringify(input.body)
|
|
1034
|
+
});
|
|
1035
|
+
} catch (networkError) {
|
|
1036
|
+
throw new OwneyError(
|
|
1037
|
+
"SPONSOR_REQUEST_FAILED",
|
|
1038
|
+
`Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
|
|
1039
|
+
{ cause: String(networkError) }
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
const text = await res.text();
|
|
1043
|
+
let parsed = null;
|
|
1044
|
+
try {
|
|
1045
|
+
parsed = JSON.parse(text);
|
|
1046
|
+
} catch {
|
|
1047
|
+
}
|
|
1048
|
+
if (!res.ok || !parsed?.success || !parsed.data) {
|
|
1049
|
+
throw new OwneyError(
|
|
1050
|
+
"SPONSOR_REQUEST_FAILED",
|
|
1051
|
+
`Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
|
|
1052
|
+
{ statusCode: res.status, responseBody: text.slice(0, 500) }
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
return parsed.data;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// src/lib/sponsored-deposit.ts
|
|
1059
|
+
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1060
|
+
function makeSponsoredDepositCallback(deps) {
|
|
1061
|
+
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
1062
|
+
return async (smartWallet, chainId, amount) => {
|
|
1063
|
+
const cid = chainId;
|
|
1064
|
+
const token = deps.tokenAddressByChain[cid];
|
|
1065
|
+
if (!token) {
|
|
1066
|
+
throw new OwneyError(
|
|
1067
|
+
"CHAIN_UNSUPPORTED",
|
|
1068
|
+
`No sponsored token configured for chain ${chainId}`
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
const pub = deps.getPublicClient(cid);
|
|
1072
|
+
const wallet = deps.getWalletClient(cid);
|
|
1073
|
+
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1074
|
+
const validAfter = 0n;
|
|
1075
|
+
const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
|
|
1076
|
+
const nonce = randomAuthNonce();
|
|
1077
|
+
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1078
|
+
token,
|
|
1079
|
+
chainId: cid,
|
|
1080
|
+
tokenName,
|
|
1081
|
+
tokenVersion,
|
|
1082
|
+
message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
|
|
1083
|
+
});
|
|
1084
|
+
const authSignature = await wallet.signTypedData(
|
|
1085
|
+
{ account: deps.ownerAddress, ...typedData }
|
|
1086
|
+
);
|
|
1087
|
+
const result = await post({
|
|
1088
|
+
baseUrl: deps.baseUrl,
|
|
1089
|
+
apiKey: deps.apiKey,
|
|
1090
|
+
body: {
|
|
1091
|
+
chainId: cid,
|
|
1092
|
+
token,
|
|
1093
|
+
from: deps.ownerAddress,
|
|
1094
|
+
to: smartWallet,
|
|
1095
|
+
value: amount,
|
|
1096
|
+
validAfter: validAfter.toString(),
|
|
1097
|
+
validBefore: validBefore.toString(),
|
|
1098
|
+
nonce,
|
|
1099
|
+
authSignature,
|
|
1100
|
+
tokenName,
|
|
1101
|
+
tokenVersion
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
1104
|
+
return result.txHash;
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
|
|
905
1108
|
// src/client.ts
|
|
906
1109
|
function encodeMultiAgentCursor(map) {
|
|
907
1110
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -923,6 +1126,14 @@ function decodeMultiAgentCursor(token) {
|
|
|
923
1126
|
}
|
|
924
1127
|
return parsed;
|
|
925
1128
|
}
|
|
1129
|
+
var SPONSORED_USDC_BY_CHAIN = {
|
|
1130
|
+
8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
1131
|
+
42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
|
|
1132
|
+
};
|
|
1133
|
+
var VIEM_CHAIN = {
|
|
1134
|
+
8453: base,
|
|
1135
|
+
42161: arbitrum
|
|
1136
|
+
};
|
|
926
1137
|
var OwneySDK = class {
|
|
927
1138
|
agents = /* @__PURE__ */ new Map();
|
|
928
1139
|
activeAgents = /* @__PURE__ */ new Set();
|
|
@@ -935,6 +1146,7 @@ var OwneySDK = class {
|
|
|
935
1146
|
state = null;
|
|
936
1147
|
apiKey;
|
|
937
1148
|
zyfaiRpcUrls;
|
|
1149
|
+
cachedSponsoredCallback = null;
|
|
938
1150
|
initializingAgentsPromise = null;
|
|
939
1151
|
constructor(config) {
|
|
940
1152
|
this.apiKey = config.apiKey;
|
|
@@ -958,6 +1170,7 @@ var OwneySDK = class {
|
|
|
958
1170
|
);
|
|
959
1171
|
}
|
|
960
1172
|
this.state = { provider, walletAddress, chainId: null };
|
|
1173
|
+
this.cachedSponsoredCallback = null;
|
|
961
1174
|
}
|
|
962
1175
|
/**
|
|
963
1176
|
* Disconnect from all agents and clear connection state.
|
|
@@ -970,6 +1183,7 @@ var OwneySDK = class {
|
|
|
970
1183
|
this.activeAgents.clear();
|
|
971
1184
|
this.disabledAgents.clear();
|
|
972
1185
|
this.state = null;
|
|
1186
|
+
this.cachedSponsoredCallback = null;
|
|
973
1187
|
}
|
|
974
1188
|
isAgentDisabled(agentId) {
|
|
975
1189
|
return this.disabledAgents.has(agentId);
|
|
@@ -1003,6 +1217,46 @@ var OwneySDK = class {
|
|
|
1003
1217
|
}
|
|
1004
1218
|
return chainId;
|
|
1005
1219
|
}
|
|
1220
|
+
requireConnectedProvider() {
|
|
1221
|
+
if (!this.state?.provider) {
|
|
1222
|
+
throw new OwneyError(
|
|
1223
|
+
"NOT_CONNECTED",
|
|
1224
|
+
"connect(provider) must be called before deposit",
|
|
1225
|
+
{}
|
|
1226
|
+
);
|
|
1227
|
+
}
|
|
1228
|
+
return this.state.provider;
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Lazily builds (and caches) the default EIP-3009 sponsored deposit callback
|
|
1232
|
+
* used when the caller omits `depositCallback`. Wraps the connected EIP-1193
|
|
1233
|
+
* provider with viem `custom(provider)` to read token meta and sign the
|
|
1234
|
+
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
1235
|
+
*/
|
|
1236
|
+
getDefaultSponsoredCallback() {
|
|
1237
|
+
if (this.cachedSponsoredCallback)
|
|
1238
|
+
return this.cachedSponsoredCallback;
|
|
1239
|
+
const provider = this.requireConnectedProvider();
|
|
1240
|
+
const owner = this.state.walletAddress;
|
|
1241
|
+
this.cachedSponsoredCallback = makeSponsoredDepositCallback({
|
|
1242
|
+
apiKey: this.apiKey,
|
|
1243
|
+
ownerAddress: owner,
|
|
1244
|
+
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
1245
|
+
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1246
|
+
// PublicClient/WalletClient param types — structurally identical at
|
|
1247
|
+
// runtime, but the two share a name TS treats as unrelated.
|
|
1248
|
+
getPublicClient: (cid) => createPublicClient({
|
|
1249
|
+
chain: VIEM_CHAIN[cid],
|
|
1250
|
+
transport: custom(provider)
|
|
1251
|
+
}),
|
|
1252
|
+
getWalletClient: (cid) => createWalletClient({
|
|
1253
|
+
account: owner,
|
|
1254
|
+
chain: VIEM_CHAIN[cid],
|
|
1255
|
+
transport: custom(provider)
|
|
1256
|
+
})
|
|
1257
|
+
});
|
|
1258
|
+
return this.cachedSponsoredCallback;
|
|
1259
|
+
}
|
|
1006
1260
|
getAgent(agentId) {
|
|
1007
1261
|
const agent = this.agents.get(agentId);
|
|
1008
1262
|
if (!agent) {
|
|
@@ -1156,6 +1410,7 @@ var OwneySDK = class {
|
|
|
1156
1410
|
}
|
|
1157
1411
|
const state = this.requireState();
|
|
1158
1412
|
const chainId = this.requireChainId();
|
|
1413
|
+
const effectiveCallback = depositCallback ?? (asset === "WETH" ? void 0 : this.getDefaultSponsoredCallback());
|
|
1159
1414
|
if (agentId) {
|
|
1160
1415
|
if (this.isAgentDisabled(agentId)) {
|
|
1161
1416
|
throw new OwneyError(
|
|
@@ -1170,7 +1425,13 @@ var OwneySDK = class {
|
|
|
1170
1425
|
return withFailureReporting(
|
|
1171
1426
|
this.apiKey,
|
|
1172
1427
|
agent.id,
|
|
1173
|
-
() => agent.deposit(
|
|
1428
|
+
() => agent.deposit(
|
|
1429
|
+
state,
|
|
1430
|
+
chainId,
|
|
1431
|
+
amount,
|
|
1432
|
+
asset,
|
|
1433
|
+
effectiveCallback
|
|
1434
|
+
)
|
|
1174
1435
|
);
|
|
1175
1436
|
}
|
|
1176
1437
|
const totalAmount = BigInt(amount);
|
|
@@ -1204,7 +1465,13 @@ var OwneySDK = class {
|
|
|
1204
1465
|
agentResults[agent.id] = await withFailureReporting(
|
|
1205
1466
|
this.apiKey,
|
|
1206
1467
|
agent.id,
|
|
1207
|
-
() => agent.deposit(
|
|
1468
|
+
() => agent.deposit(
|
|
1469
|
+
state,
|
|
1470
|
+
chainId,
|
|
1471
|
+
agentAmount,
|
|
1472
|
+
asset,
|
|
1473
|
+
effectiveCallback
|
|
1474
|
+
)
|
|
1208
1475
|
);
|
|
1209
1476
|
}
|
|
1210
1477
|
return { agentResults };
|
|
@@ -1398,10 +1665,7 @@ var OwneySDK = class {
|
|
|
1398
1665
|
disabledBalances,
|
|
1399
1666
|
requested
|
|
1400
1667
|
);
|
|
1401
|
-
const enabledTotal = enabledBalances.reduce(
|
|
1402
|
-
(s, b) => s + b.balance,
|
|
1403
|
-
0n
|
|
1404
|
-
);
|
|
1668
|
+
const enabledTotal = enabledBalances.reduce((s, b) => s + b.balance, 0n);
|
|
1405
1669
|
const enabledPlans = afterDrain > 0n ? planProportionalShares(enabledBalances, afterDrain, enabledTotal) : enabledBalances.map(({ agent, balance }) => ({
|
|
1406
1670
|
agent,
|
|
1407
1671
|
balance,
|
|
@@ -1672,27 +1936,6 @@ var OwneySDK = class {
|
|
|
1672
1936
|
nextCursor: hasMore ? encodeMultiAgentCursor(nextCursorMap) : void 0
|
|
1673
1937
|
};
|
|
1674
1938
|
}
|
|
1675
|
-
// --- Agent control ---
|
|
1676
|
-
/**
|
|
1677
|
-
* Pause an agent's automated operations. The agent will stop rebalancing until resumed.
|
|
1678
|
-
* @param agentId - The agent to pause (e.g. "zyfai")
|
|
1679
|
-
* @returns OwneyAgentStatus with success flag
|
|
1680
|
-
*/
|
|
1681
|
-
async pauseAgent(agentId) {
|
|
1682
|
-
const state = this.requireState();
|
|
1683
|
-
const chainId = this.requireChainId();
|
|
1684
|
-
return this.getAgent(agentId).pause(state, chainId);
|
|
1685
|
-
}
|
|
1686
|
-
/**
|
|
1687
|
-
* Resume an agent's automated operations.
|
|
1688
|
-
* @param agentId - The agent to resume (e.g. "zyfai")
|
|
1689
|
-
* @returns OwneyAgentStatus with success flag
|
|
1690
|
-
*/
|
|
1691
|
-
async resumeAgent(agentId) {
|
|
1692
|
-
const state = this.requireState();
|
|
1693
|
-
const chainId = this.requireChainId();
|
|
1694
|
-
return this.getAgent(agentId).resume(state, chainId);
|
|
1695
|
-
}
|
|
1696
1939
|
/**
|
|
1697
1940
|
* Get the user's profile for a specific agent, or all agents.
|
|
1698
1941
|
* @param agentId - Optional. Agent to query. Omit for all agents.
|
|
@@ -1767,12 +2010,13 @@ var OwneySDK = class {
|
|
|
1767
2010
|
const chainId = this.requireChainId();
|
|
1768
2011
|
const activeAgents = this.getActiveAgents();
|
|
1769
2012
|
const balances = {};
|
|
2013
|
+
const positionsByAgent = {};
|
|
1770
2014
|
let totalBalance = 0;
|
|
1771
2015
|
const entries = [...activeAgents.entries()];
|
|
1772
2016
|
const balanceResults = await Promise.allSettled(
|
|
1773
2017
|
entries.map(async ([id, agent]) => {
|
|
1774
2018
|
const b = await agent.getBalances(state, chainId);
|
|
1775
|
-
return [id, Number(b.totalBalance)];
|
|
2019
|
+
return [id, Number(b.totalBalance), b.positions ?? []];
|
|
1776
2020
|
})
|
|
1777
2021
|
);
|
|
1778
2022
|
let successCount = 0;
|
|
@@ -1781,8 +2025,9 @@ var OwneySDK = class {
|
|
|
1781
2025
|
const settledResult = balanceResults[i];
|
|
1782
2026
|
const [agentId] = entries[i];
|
|
1783
2027
|
if (settledResult.status === "fulfilled") {
|
|
1784
|
-
const [id, bal] = settledResult.value;
|
|
2028
|
+
const [id, bal, agentPositions] = settledResult.value;
|
|
1785
2029
|
balances[id] = bal;
|
|
2030
|
+
positionsByAgent[id] = agentPositions;
|
|
1786
2031
|
totalBalance += bal;
|
|
1787
2032
|
successCount += 1;
|
|
1788
2033
|
} else {
|
|
@@ -1816,7 +2061,64 @@ var OwneySDK = class {
|
|
|
1816
2061
|
}
|
|
1817
2062
|
}
|
|
1818
2063
|
return {
|
|
1819
|
-
agentAllocation: allocation
|
|
2064
|
+
agentAllocation: allocation,
|
|
2065
|
+
agentPositions: positionsByAgent
|
|
2066
|
+
};
|
|
2067
|
+
}
|
|
2068
|
+
/**
|
|
2069
|
+
* Allocation-weighted APY from the current portfolio: each pool's APY
|
|
2070
|
+
* weighted by the user's position value in it. More accurate per-user than
|
|
2071
|
+
* the historical 30D APY. (ROUT-228)
|
|
2072
|
+
* @param options.agentId - Optional. Scope to one agent. Omit to aggregate
|
|
2073
|
+
* positions across all active agents.
|
|
2074
|
+
*/
|
|
2075
|
+
async getAllocationApy({
|
|
2076
|
+
agentId
|
|
2077
|
+
} = {}) {
|
|
2078
|
+
const state = this.requireState();
|
|
2079
|
+
const chainId = this.requireChainId();
|
|
2080
|
+
const activeAgents = agentId ? /* @__PURE__ */ new Map([[agentId, this.getAgent(agentId)]]) : this.getActiveAgents();
|
|
2081
|
+
const entries = [...activeAgents.entries()];
|
|
2082
|
+
const balanceResults = await Promise.allSettled(
|
|
2083
|
+
entries.map(async ([id, agent]) => {
|
|
2084
|
+
const b = await agent.getBalances(state, chainId);
|
|
2085
|
+
return [id, b.positions ?? []];
|
|
2086
|
+
})
|
|
2087
|
+
);
|
|
2088
|
+
const agentApy = {};
|
|
2089
|
+
const allPositions = [];
|
|
2090
|
+
let successCount = 0;
|
|
2091
|
+
const agentErrors = {};
|
|
2092
|
+
for (let i = 0; i < balanceResults.length; i++) {
|
|
2093
|
+
const settled = balanceResults[i];
|
|
2094
|
+
const [aid] = entries[i];
|
|
2095
|
+
if (settled.status === "fulfilled") {
|
|
2096
|
+
const [id, positions] = settled.value;
|
|
2097
|
+
const per = computeAllocationApy(positions);
|
|
2098
|
+
agentApy[id] = {
|
|
2099
|
+
totalApy: per.totalApy,
|
|
2100
|
+
apyByChainAndAsset: per.apyByChainAndAsset
|
|
2101
|
+
};
|
|
2102
|
+
allPositions.push(...positions);
|
|
2103
|
+
successCount += 1;
|
|
2104
|
+
} else {
|
|
2105
|
+
const reason = settled.reason;
|
|
2106
|
+
agentErrors[aid] = reason instanceof Error ? reason.message : String(reason);
|
|
2107
|
+
console.error(`getAllocationApy agent "${aid}" failed:`, reason);
|
|
2108
|
+
}
|
|
2109
|
+
}
|
|
2110
|
+
if (successCount === 0) {
|
|
2111
|
+
throw new OwneyError(
|
|
2112
|
+
"ALLOCATION_ALL_FAILED",
|
|
2113
|
+
"Failed to fetch allocation APY: all agents failed.",
|
|
2114
|
+
{ agentErrors }
|
|
2115
|
+
);
|
|
2116
|
+
}
|
|
2117
|
+
const overall = computeAllocationApy(allPositions);
|
|
2118
|
+
return {
|
|
2119
|
+
totalApy: overall.totalApy,
|
|
2120
|
+
apyByChainAndAsset: overall.apyByChainAndAsset,
|
|
2121
|
+
agentApy
|
|
1820
2122
|
};
|
|
1821
2123
|
}
|
|
1822
2124
|
};
|