@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.cjs
CHANGED
|
@@ -38,7 +38,7 @@ var P_SUPPORTED_CHAINS = {
|
|
|
38
38
|
chainIds: [8453, 42161],
|
|
39
39
|
chains: ["BASE", "ARBITRUM"]
|
|
40
40
|
};
|
|
41
|
-
var SUPPORTED_TOKENS = ["USDC", "USDT"];
|
|
41
|
+
var SUPPORTED_TOKENS = ["USDC", "USDT", "WETH"];
|
|
42
42
|
var SUPPORTED_CHAIN_IDS = P_SUPPORTED_CHAINS.chainIds;
|
|
43
43
|
var SUPPORTED_CHAINS = P_SUPPORTED_CHAINS.chains;
|
|
44
44
|
var SupportedAssets = [
|
|
@@ -59,6 +59,18 @@ var SupportedAssets = [
|
|
|
59
59
|
symbol: "USDT",
|
|
60
60
|
chainId: 42161,
|
|
61
61
|
decimals: 6
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
address: `0x4200000000000000000000000000000000000006`,
|
|
65
|
+
symbol: "WETH",
|
|
66
|
+
chainId: 8453,
|
|
67
|
+
decimals: 18
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
address: `0x82aF49447D8a07e3bd95BD0d56f35241523fBab1`,
|
|
71
|
+
symbol: "WETH",
|
|
72
|
+
chainId: 42161,
|
|
73
|
+
decimals: 18
|
|
62
74
|
}
|
|
63
75
|
];
|
|
64
76
|
|
|
@@ -157,6 +169,18 @@ var CHAIN_ID_TO_NAME = {
|
|
|
157
169
|
8453: "BASE",
|
|
158
170
|
42161: "ARBITRUM"
|
|
159
171
|
};
|
|
172
|
+
var NAME_TO_CHAIN_ID = Object.entries(
|
|
173
|
+
CHAIN_ID_TO_NAME
|
|
174
|
+
).reduce((acc, [id, name]) => {
|
|
175
|
+
acc[name.toLowerCase()] = Number(id);
|
|
176
|
+
return acc;
|
|
177
|
+
}, {});
|
|
178
|
+
function resolveChainId(chain) {
|
|
179
|
+
const asNum = Number(chain);
|
|
180
|
+
if (Number.isFinite(asNum) && asNum > 0)
|
|
181
|
+
return asNum;
|
|
182
|
+
return NAME_TO_CHAIN_ID[chain.trim().toLowerCase()] ?? NaN;
|
|
183
|
+
}
|
|
160
184
|
function mapBalances(raw, _chainId, smartWallet) {
|
|
161
185
|
const portfolio = raw.portfolio;
|
|
162
186
|
const portfolioByChain = portfolio.portfolioByChain ?? {};
|
|
@@ -177,10 +201,27 @@ function mapBalances(raw, _chainId, smartWallet) {
|
|
|
177
201
|
});
|
|
178
202
|
}
|
|
179
203
|
}
|
|
204
|
+
const positions = (portfolio.positions ?? []).map((p) => ({
|
|
205
|
+
chain: p.chain ?? "",
|
|
206
|
+
protocol: p.protocol_name ?? p.protocol_id ?? "",
|
|
207
|
+
protocolId: p.protocol_id,
|
|
208
|
+
pool: p.pool,
|
|
209
|
+
asset: p.token_symbol ?? "",
|
|
210
|
+
// Position amount is hex-encoded base units (like the token balances
|
|
211
|
+
// above). Supported assets (USDC/USDT) are 6-decimal — hexToDecimal's
|
|
212
|
+
// default — so no per-token decimals lookup is needed.
|
|
213
|
+
amount: String(hexToDecimal(p.amount || "0")),
|
|
214
|
+
apy: p.pool_apy,
|
|
215
|
+
tvl: p.pool_tvl,
|
|
216
|
+
// PositionSlot has no `liquidity` field yet; Zyfai will add it. Narrow
|
|
217
|
+
// structural read keeps it undefined today and auto-populates later.
|
|
218
|
+
liquidity: p.liquidity
|
|
219
|
+
}));
|
|
180
220
|
return {
|
|
181
221
|
smartWallet,
|
|
182
222
|
totalBalance: String(totalBalance),
|
|
183
|
-
tokens
|
|
223
|
+
tokens,
|
|
224
|
+
positions
|
|
184
225
|
};
|
|
185
226
|
}
|
|
186
227
|
function sumTokenValues(tokens) {
|
|
@@ -288,13 +329,6 @@ function mapEntries(rawEntries, chainId) {
|
|
|
288
329
|
};
|
|
289
330
|
});
|
|
290
331
|
}
|
|
291
|
-
function mapAgentStatus(raw) {
|
|
292
|
-
return {
|
|
293
|
-
success: raw.success,
|
|
294
|
-
strategy: raw.strategy,
|
|
295
|
-
protocols: raw.protocols
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
332
|
function mapUserProfile(raw, userAddress) {
|
|
299
333
|
return {
|
|
300
334
|
address: userAddress,
|
|
@@ -330,6 +364,46 @@ function mapApyByStrategy(raw) {
|
|
|
330
364
|
detailedApys: hasDetails ? { apyPerAsset } : void 0
|
|
331
365
|
};
|
|
332
366
|
}
|
|
367
|
+
function computeAllocationApy(positions) {
|
|
368
|
+
let weightedSum = 0;
|
|
369
|
+
let totalValue = 0;
|
|
370
|
+
const buckets = {};
|
|
371
|
+
for (const p of positions) {
|
|
372
|
+
const apy = p.apy;
|
|
373
|
+
const value = Number(p.amount);
|
|
374
|
+
if (typeof apy !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
weightedSum += apy * value;
|
|
378
|
+
totalValue += value;
|
|
379
|
+
const chainId = resolveChainId(p.chain);
|
|
380
|
+
const token = p.asset;
|
|
381
|
+
if (!SUPPORTED_CHAIN_IDS.includes(chainId))
|
|
382
|
+
continue;
|
|
383
|
+
if (!SUPPORTED_TOKENS.includes(token))
|
|
384
|
+
continue;
|
|
385
|
+
const perAsset = buckets[chainId] ?? {};
|
|
386
|
+
const cell = perAsset[token] ?? { weightedSum: 0, value: 0 };
|
|
387
|
+
cell.weightedSum += apy * value;
|
|
388
|
+
cell.value += value;
|
|
389
|
+
perAsset[token] = cell;
|
|
390
|
+
buckets[chainId] = perAsset;
|
|
391
|
+
}
|
|
392
|
+
const apyByChainAndAsset = {};
|
|
393
|
+
for (const [chainKey, perAsset] of Object.entries(buckets)) {
|
|
394
|
+
const chainId = Number(chainKey);
|
|
395
|
+
const out = {};
|
|
396
|
+
for (const [token, cell] of Object.entries(perAsset ?? {})) {
|
|
397
|
+
if (cell && cell.value > 0) {
|
|
398
|
+
out[token] = cell.weightedSum / cell.value;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (Object.keys(out).length > 0)
|
|
402
|
+
apyByChainAndAsset[chainId] = out;
|
|
403
|
+
}
|
|
404
|
+
const totalApy = totalValue > 0 ? String(weightedSum / totalValue) : "0";
|
|
405
|
+
return { totalApy, apyByChainAndAsset };
|
|
406
|
+
}
|
|
333
407
|
|
|
334
408
|
// src/agents/zyfai/zyfai.history-cursor.ts
|
|
335
409
|
var InvalidHistoryCursorError = class extends Error {
|
|
@@ -429,6 +503,10 @@ var DEFAULT_ZYFAI_RPC_URLS = {
|
|
|
429
503
|
8453: "https://base-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V",
|
|
430
504
|
42161: "https://arb-mainnet.g.alchemy.com/v2/ZWyVU-9XfS3z8Rn-xkq7V"
|
|
431
505
|
};
|
|
506
|
+
var WETH_ADDRESS_BY_CHAIN = {
|
|
507
|
+
8453: "0x4200000000000000000000000000000000000006",
|
|
508
|
+
42161: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"
|
|
509
|
+
};
|
|
432
510
|
var ZyfaiAgent = class {
|
|
433
511
|
id = "zyfai";
|
|
434
512
|
supportedChainIds = [8453, 42161];
|
|
@@ -436,12 +514,18 @@ var ZyfaiAgent = class {
|
|
|
436
514
|
{
|
|
437
515
|
chainId: 8453,
|
|
438
516
|
chain: "BASE",
|
|
439
|
-
assets: [
|
|
517
|
+
assets: [
|
|
518
|
+
{ symbol: "USDC", minDepositAmount: "1500000" },
|
|
519
|
+
{ symbol: "WETH", minDepositAmount: "500000000000000" }
|
|
520
|
+
]
|
|
440
521
|
},
|
|
441
522
|
{
|
|
442
523
|
chainId: 42161,
|
|
443
524
|
chain: "ARBITRUM",
|
|
444
|
-
assets: [
|
|
525
|
+
assets: [
|
|
526
|
+
{ symbol: "USDC", minDepositAmount: "1500000" },
|
|
527
|
+
{ symbol: "WETH", minDepositAmount: "500000000000000" }
|
|
528
|
+
]
|
|
445
529
|
}
|
|
446
530
|
];
|
|
447
531
|
sdk;
|
|
@@ -607,7 +691,7 @@ var ZyfaiAgent = class {
|
|
|
607
691
|
throw error;
|
|
608
692
|
}
|
|
609
693
|
}
|
|
610
|
-
async deposit(state, chainId, amount, depositCallback) {
|
|
694
|
+
async deposit(state, chainId, amount, asset, depositCallback) {
|
|
611
695
|
try {
|
|
612
696
|
await this.connectFull(state, chainId);
|
|
613
697
|
const validChainId = isValidChainId(chainId);
|
|
@@ -621,13 +705,15 @@ var ZyfaiAgent = class {
|
|
|
621
705
|
validChainId,
|
|
622
706
|
amount
|
|
623
707
|
);
|
|
624
|
-
|
|
708
|
+
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
709
|
+
await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
|
|
625
710
|
return { txHash, smartWallet: wallet.address, amount };
|
|
626
711
|
}
|
|
627
712
|
const raw = await this.sdk.depositFunds(
|
|
628
713
|
this.getAddress(),
|
|
629
714
|
validChainId,
|
|
630
|
-
amount
|
|
715
|
+
amount,
|
|
716
|
+
asset
|
|
631
717
|
);
|
|
632
718
|
return mapDeposit(raw);
|
|
633
719
|
} catch (error) {
|
|
@@ -712,17 +798,6 @@ var ZyfaiAgent = class {
|
|
|
712
798
|
nextCursor
|
|
713
799
|
};
|
|
714
800
|
}
|
|
715
|
-
// --- IAgent: Agent control ---
|
|
716
|
-
async pause(state, chainId) {
|
|
717
|
-
await this.connectAuth(state, chainId);
|
|
718
|
-
const raw = await this.sdk.pauseAgent();
|
|
719
|
-
return mapAgentStatus(raw);
|
|
720
|
-
}
|
|
721
|
-
async resume(state, chainId) {
|
|
722
|
-
await this.connectAuth(state, chainId);
|
|
723
|
-
const raw = await this.sdk.resumeAgent();
|
|
724
|
-
return mapAgentStatus(raw);
|
|
725
|
-
}
|
|
726
801
|
async getUserProfile(state, chainId) {
|
|
727
802
|
await this.connectAuth(state, chainId);
|
|
728
803
|
const validChainId = isValidChainId(chainId);
|
|
@@ -934,6 +1009,130 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
934
1009
|
return out;
|
|
935
1010
|
}
|
|
936
1011
|
|
|
1012
|
+
// src/client.ts
|
|
1013
|
+
var import_viem3 = require("viem");
|
|
1014
|
+
var import_chains = require("viem/chains");
|
|
1015
|
+
|
|
1016
|
+
// src/lib/transfer-auth.ts
|
|
1017
|
+
var import_viem2 = require("viem");
|
|
1018
|
+
var ERC20_META_ABI = [
|
|
1019
|
+
{ type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
|
|
1020
|
+
{ type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
|
|
1021
|
+
];
|
|
1022
|
+
function buildTransferWithAuthorizationTypedData(input) {
|
|
1023
|
+
return {
|
|
1024
|
+
domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
|
|
1025
|
+
types: {
|
|
1026
|
+
TransferWithAuthorization: [
|
|
1027
|
+
{ name: "from", type: "address" },
|
|
1028
|
+
{ name: "to", type: "address" },
|
|
1029
|
+
{ name: "value", type: "uint256" },
|
|
1030
|
+
{ name: "validAfter", type: "uint256" },
|
|
1031
|
+
{ name: "validBefore", type: "uint256" },
|
|
1032
|
+
{ name: "nonce", type: "bytes32" }
|
|
1033
|
+
]
|
|
1034
|
+
},
|
|
1035
|
+
primaryType: "TransferWithAuthorization",
|
|
1036
|
+
message: input.message
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
async function readTokenMeta(publicClient, token) {
|
|
1040
|
+
const [tokenName, tokenVersion] = await Promise.all([
|
|
1041
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
|
|
1042
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
|
|
1043
|
+
]);
|
|
1044
|
+
return { tokenName, tokenVersion };
|
|
1045
|
+
}
|
|
1046
|
+
function randomAuthNonce() {
|
|
1047
|
+
const bytes = new Uint8Array(32);
|
|
1048
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
1049
|
+
return (0, import_viem2.bytesToHex)(bytes);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// src/lib/sponsor-client.ts
|
|
1053
|
+
var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
1054
|
+
async function postSponsorTransferAuth(input) {
|
|
1055
|
+
const base2 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
1056
|
+
let res;
|
|
1057
|
+
try {
|
|
1058
|
+
res = await fetch(`${base2}/api/v1/sponsor/erc20-transfer-auth`, {
|
|
1059
|
+
method: "POST",
|
|
1060
|
+
headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey },
|
|
1061
|
+
body: JSON.stringify(input.body)
|
|
1062
|
+
});
|
|
1063
|
+
} catch (networkError) {
|
|
1064
|
+
throw new OwneyError(
|
|
1065
|
+
"SPONSOR_REQUEST_FAILED",
|
|
1066
|
+
`Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
|
|
1067
|
+
{ cause: String(networkError) }
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
const text = await res.text();
|
|
1071
|
+
let parsed = null;
|
|
1072
|
+
try {
|
|
1073
|
+
parsed = JSON.parse(text);
|
|
1074
|
+
} catch {
|
|
1075
|
+
}
|
|
1076
|
+
if (!res.ok || !parsed?.success || !parsed.data) {
|
|
1077
|
+
throw new OwneyError(
|
|
1078
|
+
"SPONSOR_REQUEST_FAILED",
|
|
1079
|
+
`Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
|
|
1080
|
+
{ statusCode: res.status, responseBody: text.slice(0, 500) }
|
|
1081
|
+
);
|
|
1082
|
+
}
|
|
1083
|
+
return parsed.data;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/lib/sponsored-deposit.ts
|
|
1087
|
+
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1088
|
+
function makeSponsoredDepositCallback(deps) {
|
|
1089
|
+
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
1090
|
+
return async (smartWallet, chainId, amount) => {
|
|
1091
|
+
const cid = chainId;
|
|
1092
|
+
const token = deps.tokenAddressByChain[cid];
|
|
1093
|
+
if (!token) {
|
|
1094
|
+
throw new OwneyError(
|
|
1095
|
+
"CHAIN_UNSUPPORTED",
|
|
1096
|
+
`No sponsored token configured for chain ${chainId}`
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
const pub = deps.getPublicClient(cid);
|
|
1100
|
+
const wallet = deps.getWalletClient(cid);
|
|
1101
|
+
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1102
|
+
const validAfter = 0n;
|
|
1103
|
+
const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
|
|
1104
|
+
const nonce = randomAuthNonce();
|
|
1105
|
+
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1106
|
+
token,
|
|
1107
|
+
chainId: cid,
|
|
1108
|
+
tokenName,
|
|
1109
|
+
tokenVersion,
|
|
1110
|
+
message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
|
|
1111
|
+
});
|
|
1112
|
+
const authSignature = await wallet.signTypedData(
|
|
1113
|
+
{ account: deps.ownerAddress, ...typedData }
|
|
1114
|
+
);
|
|
1115
|
+
const result = await post({
|
|
1116
|
+
baseUrl: deps.baseUrl,
|
|
1117
|
+
apiKey: deps.apiKey,
|
|
1118
|
+
body: {
|
|
1119
|
+
chainId: cid,
|
|
1120
|
+
token,
|
|
1121
|
+
from: deps.ownerAddress,
|
|
1122
|
+
to: smartWallet,
|
|
1123
|
+
value: amount,
|
|
1124
|
+
validAfter: validAfter.toString(),
|
|
1125
|
+
validBefore: validBefore.toString(),
|
|
1126
|
+
nonce,
|
|
1127
|
+
authSignature,
|
|
1128
|
+
tokenName,
|
|
1129
|
+
tokenVersion
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
return result.txHash;
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
|
|
937
1136
|
// src/client.ts
|
|
938
1137
|
function encodeMultiAgentCursor(map) {
|
|
939
1138
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -955,6 +1154,14 @@ function decodeMultiAgentCursor(token) {
|
|
|
955
1154
|
}
|
|
956
1155
|
return parsed;
|
|
957
1156
|
}
|
|
1157
|
+
var SPONSORED_USDC_BY_CHAIN = {
|
|
1158
|
+
8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
1159
|
+
42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
|
|
1160
|
+
};
|
|
1161
|
+
var VIEM_CHAIN = {
|
|
1162
|
+
8453: import_chains.base,
|
|
1163
|
+
42161: import_chains.arbitrum
|
|
1164
|
+
};
|
|
958
1165
|
var OwneySDK = class {
|
|
959
1166
|
agents = /* @__PURE__ */ new Map();
|
|
960
1167
|
activeAgents = /* @__PURE__ */ new Set();
|
|
@@ -967,6 +1174,7 @@ var OwneySDK = class {
|
|
|
967
1174
|
state = null;
|
|
968
1175
|
apiKey;
|
|
969
1176
|
zyfaiRpcUrls;
|
|
1177
|
+
cachedSponsoredCallback = null;
|
|
970
1178
|
initializingAgentsPromise = null;
|
|
971
1179
|
constructor(config) {
|
|
972
1180
|
this.apiKey = config.apiKey;
|
|
@@ -990,6 +1198,7 @@ var OwneySDK = class {
|
|
|
990
1198
|
);
|
|
991
1199
|
}
|
|
992
1200
|
this.state = { provider, walletAddress, chainId: null };
|
|
1201
|
+
this.cachedSponsoredCallback = null;
|
|
993
1202
|
}
|
|
994
1203
|
/**
|
|
995
1204
|
* Disconnect from all agents and clear connection state.
|
|
@@ -1002,6 +1211,7 @@ var OwneySDK = class {
|
|
|
1002
1211
|
this.activeAgents.clear();
|
|
1003
1212
|
this.disabledAgents.clear();
|
|
1004
1213
|
this.state = null;
|
|
1214
|
+
this.cachedSponsoredCallback = null;
|
|
1005
1215
|
}
|
|
1006
1216
|
isAgentDisabled(agentId) {
|
|
1007
1217
|
return this.disabledAgents.has(agentId);
|
|
@@ -1035,6 +1245,46 @@ var OwneySDK = class {
|
|
|
1035
1245
|
}
|
|
1036
1246
|
return chainId;
|
|
1037
1247
|
}
|
|
1248
|
+
requireConnectedProvider() {
|
|
1249
|
+
if (!this.state?.provider) {
|
|
1250
|
+
throw new OwneyError(
|
|
1251
|
+
"NOT_CONNECTED",
|
|
1252
|
+
"connect(provider) must be called before deposit",
|
|
1253
|
+
{}
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1256
|
+
return this.state.provider;
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Lazily builds (and caches) the default EIP-3009 sponsored deposit callback
|
|
1260
|
+
* used when the caller omits `depositCallback`. Wraps the connected EIP-1193
|
|
1261
|
+
* provider with viem `custom(provider)` to read token meta and sign the
|
|
1262
|
+
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
1263
|
+
*/
|
|
1264
|
+
getDefaultSponsoredCallback() {
|
|
1265
|
+
if (this.cachedSponsoredCallback)
|
|
1266
|
+
return this.cachedSponsoredCallback;
|
|
1267
|
+
const provider = this.requireConnectedProvider();
|
|
1268
|
+
const owner = this.state.walletAddress;
|
|
1269
|
+
this.cachedSponsoredCallback = makeSponsoredDepositCallback({
|
|
1270
|
+
apiKey: this.apiKey,
|
|
1271
|
+
ownerAddress: owner,
|
|
1272
|
+
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
1273
|
+
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1274
|
+
// PublicClient/WalletClient param types — structurally identical at
|
|
1275
|
+
// runtime, but the two share a name TS treats as unrelated.
|
|
1276
|
+
getPublicClient: (cid) => (0, import_viem3.createPublicClient)({
|
|
1277
|
+
chain: VIEM_CHAIN[cid],
|
|
1278
|
+
transport: (0, import_viem3.custom)(provider)
|
|
1279
|
+
}),
|
|
1280
|
+
getWalletClient: (cid) => (0, import_viem3.createWalletClient)({
|
|
1281
|
+
account: owner,
|
|
1282
|
+
chain: VIEM_CHAIN[cid],
|
|
1283
|
+
transport: (0, import_viem3.custom)(provider)
|
|
1284
|
+
})
|
|
1285
|
+
});
|
|
1286
|
+
return this.cachedSponsoredCallback;
|
|
1287
|
+
}
|
|
1038
1288
|
getAgent(agentId) {
|
|
1039
1289
|
const agent = this.agents.get(agentId);
|
|
1040
1290
|
if (!agent) {
|
|
@@ -1188,6 +1438,7 @@ var OwneySDK = class {
|
|
|
1188
1438
|
}
|
|
1189
1439
|
const state = this.requireState();
|
|
1190
1440
|
const chainId = this.requireChainId();
|
|
1441
|
+
const effectiveCallback = depositCallback ?? (asset === "WETH" ? void 0 : this.getDefaultSponsoredCallback());
|
|
1191
1442
|
if (agentId) {
|
|
1192
1443
|
if (this.isAgentDisabled(agentId)) {
|
|
1193
1444
|
throw new OwneyError(
|
|
@@ -1202,7 +1453,13 @@ var OwneySDK = class {
|
|
|
1202
1453
|
return withFailureReporting(
|
|
1203
1454
|
this.apiKey,
|
|
1204
1455
|
agent.id,
|
|
1205
|
-
() => agent.deposit(
|
|
1456
|
+
() => agent.deposit(
|
|
1457
|
+
state,
|
|
1458
|
+
chainId,
|
|
1459
|
+
amount,
|
|
1460
|
+
asset,
|
|
1461
|
+
effectiveCallback
|
|
1462
|
+
)
|
|
1206
1463
|
);
|
|
1207
1464
|
}
|
|
1208
1465
|
const totalAmount = BigInt(amount);
|
|
@@ -1236,7 +1493,13 @@ var OwneySDK = class {
|
|
|
1236
1493
|
agentResults[agent.id] = await withFailureReporting(
|
|
1237
1494
|
this.apiKey,
|
|
1238
1495
|
agent.id,
|
|
1239
|
-
() => agent.deposit(
|
|
1496
|
+
() => agent.deposit(
|
|
1497
|
+
state,
|
|
1498
|
+
chainId,
|
|
1499
|
+
agentAmount,
|
|
1500
|
+
asset,
|
|
1501
|
+
effectiveCallback
|
|
1502
|
+
)
|
|
1240
1503
|
);
|
|
1241
1504
|
}
|
|
1242
1505
|
return { agentResults };
|
|
@@ -1430,10 +1693,7 @@ var OwneySDK = class {
|
|
|
1430
1693
|
disabledBalances,
|
|
1431
1694
|
requested
|
|
1432
1695
|
);
|
|
1433
|
-
const enabledTotal = enabledBalances.reduce(
|
|
1434
|
-
(s, b) => s + b.balance,
|
|
1435
|
-
0n
|
|
1436
|
-
);
|
|
1696
|
+
const enabledTotal = enabledBalances.reduce((s, b) => s + b.balance, 0n);
|
|
1437
1697
|
const enabledPlans = afterDrain > 0n ? planProportionalShares(enabledBalances, afterDrain, enabledTotal) : enabledBalances.map(({ agent, balance }) => ({
|
|
1438
1698
|
agent,
|
|
1439
1699
|
balance,
|
|
@@ -1704,27 +1964,6 @@ var OwneySDK = class {
|
|
|
1704
1964
|
nextCursor: hasMore ? encodeMultiAgentCursor(nextCursorMap) : void 0
|
|
1705
1965
|
};
|
|
1706
1966
|
}
|
|
1707
|
-
// --- Agent control ---
|
|
1708
|
-
/**
|
|
1709
|
-
* Pause an agent's automated operations. The agent will stop rebalancing until resumed.
|
|
1710
|
-
* @param agentId - The agent to pause (e.g. "zyfai")
|
|
1711
|
-
* @returns OwneyAgentStatus with success flag
|
|
1712
|
-
*/
|
|
1713
|
-
async pauseAgent(agentId) {
|
|
1714
|
-
const state = this.requireState();
|
|
1715
|
-
const chainId = this.requireChainId();
|
|
1716
|
-
return this.getAgent(agentId).pause(state, chainId);
|
|
1717
|
-
}
|
|
1718
|
-
/**
|
|
1719
|
-
* Resume an agent's automated operations.
|
|
1720
|
-
* @param agentId - The agent to resume (e.g. "zyfai")
|
|
1721
|
-
* @returns OwneyAgentStatus with success flag
|
|
1722
|
-
*/
|
|
1723
|
-
async resumeAgent(agentId) {
|
|
1724
|
-
const state = this.requireState();
|
|
1725
|
-
const chainId = this.requireChainId();
|
|
1726
|
-
return this.getAgent(agentId).resume(state, chainId);
|
|
1727
|
-
}
|
|
1728
1967
|
/**
|
|
1729
1968
|
* Get the user's profile for a specific agent, or all agents.
|
|
1730
1969
|
* @param agentId - Optional. Agent to query. Omit for all agents.
|
|
@@ -1799,12 +2038,13 @@ var OwneySDK = class {
|
|
|
1799
2038
|
const chainId = this.requireChainId();
|
|
1800
2039
|
const activeAgents = this.getActiveAgents();
|
|
1801
2040
|
const balances = {};
|
|
2041
|
+
const positionsByAgent = {};
|
|
1802
2042
|
let totalBalance = 0;
|
|
1803
2043
|
const entries = [...activeAgents.entries()];
|
|
1804
2044
|
const balanceResults = await Promise.allSettled(
|
|
1805
2045
|
entries.map(async ([id, agent]) => {
|
|
1806
2046
|
const b = await agent.getBalances(state, chainId);
|
|
1807
|
-
return [id, Number(b.totalBalance)];
|
|
2047
|
+
return [id, Number(b.totalBalance), b.positions ?? []];
|
|
1808
2048
|
})
|
|
1809
2049
|
);
|
|
1810
2050
|
let successCount = 0;
|
|
@@ -1813,8 +2053,9 @@ var OwneySDK = class {
|
|
|
1813
2053
|
const settledResult = balanceResults[i];
|
|
1814
2054
|
const [agentId] = entries[i];
|
|
1815
2055
|
if (settledResult.status === "fulfilled") {
|
|
1816
|
-
const [id, bal] = settledResult.value;
|
|
2056
|
+
const [id, bal, agentPositions] = settledResult.value;
|
|
1817
2057
|
balances[id] = bal;
|
|
2058
|
+
positionsByAgent[id] = agentPositions;
|
|
1818
2059
|
totalBalance += bal;
|
|
1819
2060
|
successCount += 1;
|
|
1820
2061
|
} else {
|
|
@@ -1848,13 +2089,70 @@ var OwneySDK = class {
|
|
|
1848
2089
|
}
|
|
1849
2090
|
}
|
|
1850
2091
|
return {
|
|
1851
|
-
agentAllocation: allocation
|
|
2092
|
+
agentAllocation: allocation,
|
|
2093
|
+
agentPositions: positionsByAgent
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
/**
|
|
2097
|
+
* Allocation-weighted APY from the current portfolio: each pool's APY
|
|
2098
|
+
* weighted by the user's position value in it. More accurate per-user than
|
|
2099
|
+
* the historical 30D APY. (ROUT-228)
|
|
2100
|
+
* @param options.agentId - Optional. Scope to one agent. Omit to aggregate
|
|
2101
|
+
* positions across all active agents.
|
|
2102
|
+
*/
|
|
2103
|
+
async getAllocationApy({
|
|
2104
|
+
agentId
|
|
2105
|
+
} = {}) {
|
|
2106
|
+
const state = this.requireState();
|
|
2107
|
+
const chainId = this.requireChainId();
|
|
2108
|
+
const activeAgents = agentId ? /* @__PURE__ */ new Map([[agentId, this.getAgent(agentId)]]) : this.getActiveAgents();
|
|
2109
|
+
const entries = [...activeAgents.entries()];
|
|
2110
|
+
const balanceResults = await Promise.allSettled(
|
|
2111
|
+
entries.map(async ([id, agent]) => {
|
|
2112
|
+
const b = await agent.getBalances(state, chainId);
|
|
2113
|
+
return [id, b.positions ?? []];
|
|
2114
|
+
})
|
|
2115
|
+
);
|
|
2116
|
+
const agentApy = {};
|
|
2117
|
+
const allPositions = [];
|
|
2118
|
+
let successCount = 0;
|
|
2119
|
+
const agentErrors = {};
|
|
2120
|
+
for (let i = 0; i < balanceResults.length; i++) {
|
|
2121
|
+
const settled = balanceResults[i];
|
|
2122
|
+
const [aid] = entries[i];
|
|
2123
|
+
if (settled.status === "fulfilled") {
|
|
2124
|
+
const [id, positions] = settled.value;
|
|
2125
|
+
const per = computeAllocationApy(positions);
|
|
2126
|
+
agentApy[id] = {
|
|
2127
|
+
totalApy: per.totalApy,
|
|
2128
|
+
apyByChainAndAsset: per.apyByChainAndAsset
|
|
2129
|
+
};
|
|
2130
|
+
allPositions.push(...positions);
|
|
2131
|
+
successCount += 1;
|
|
2132
|
+
} else {
|
|
2133
|
+
const reason = settled.reason;
|
|
2134
|
+
agentErrors[aid] = reason instanceof Error ? reason.message : String(reason);
|
|
2135
|
+
console.error(`getAllocationApy agent "${aid}" failed:`, reason);
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
if (successCount === 0) {
|
|
2139
|
+
throw new OwneyError(
|
|
2140
|
+
"ALLOCATION_ALL_FAILED",
|
|
2141
|
+
"Failed to fetch allocation APY: all agents failed.",
|
|
2142
|
+
{ agentErrors }
|
|
2143
|
+
);
|
|
2144
|
+
}
|
|
2145
|
+
const overall = computeAllocationApy(allPositions);
|
|
2146
|
+
return {
|
|
2147
|
+
totalApy: overall.totalApy,
|
|
2148
|
+
apyByChainAndAsset: overall.apyByChainAndAsset,
|
|
2149
|
+
agentApy
|
|
1852
2150
|
};
|
|
1853
2151
|
}
|
|
1854
2152
|
};
|
|
1855
2153
|
|
|
1856
2154
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
1857
|
-
var
|
|
2155
|
+
var import_viem4 = require("viem");
|
|
1858
2156
|
var import_siwe = require("siwe");
|
|
1859
2157
|
var import_sdk2 = require("@zyfai/sdk");
|
|
1860
2158
|
|
|
@@ -1936,7 +2234,7 @@ function buildSIWXConfig(deps) {
|
|
|
1936
2234
|
issuedAt,
|
|
1937
2235
|
toString() {
|
|
1938
2236
|
return new import_siwe.SiweMessage({
|
|
1939
|
-
address: (0,
|
|
2237
|
+
address: (0, import_viem4.getAddress)(accountAddress),
|
|
1940
2238
|
chainId: numericChainId(chainId),
|
|
1941
2239
|
domain,
|
|
1942
2240
|
uri,
|