@agenticocean/defi-agent 0.2.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/blend-client.d.ts +54 -0
- package/dist/blend-client.d.ts.map +1 -0
- package/dist/blend-client.js +202 -0
- package/dist/blend-client.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts.d.ts +3 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +40 -0
- package/dist/prompts.js.map +1 -0
- package/dist/rebalancer.d.ts +60 -0
- package/dist/rebalancer.d.ts.map +1 -0
- package/dist/rebalancer.js +166 -0
- package/dist/rebalancer.js.map +1 -0
- package/dist/soroswap-client.d.ts +33 -0
- package/dist/soroswap-client.d.ts.map +1 -0
- package/dist/soroswap-client.js +148 -0
- package/dist/soroswap-client.js.map +1 -0
- package/dist/types.d.ts +112 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/yield-optimizer.d.ts +33 -0
- package/dist/yield-optimizer.d.ts.map +1 -0
- package/dist/yield-optimizer.js +169 -0
- package/dist/yield-optimizer.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AgentAIConfig, BlendPoolData, UserBlendPosition } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Blend Protocol client.
|
|
4
|
+
*
|
|
5
|
+
* Reads pool data (rates, reserves, user positions) and builds
|
|
6
|
+
* supply/withdraw operations for the rebalancer.
|
|
7
|
+
*/
|
|
8
|
+
export declare class BlendClient {
|
|
9
|
+
private rpcUrl;
|
|
10
|
+
private passphrase;
|
|
11
|
+
private usdcAddress;
|
|
12
|
+
private defaultPoolId;
|
|
13
|
+
private log;
|
|
14
|
+
constructor(config: AgentAIConfig);
|
|
15
|
+
loadPool(poolId?: string): Promise<BlendPoolData>;
|
|
16
|
+
buildSupplyOp(params: {
|
|
17
|
+
poolId: string;
|
|
18
|
+
from: string;
|
|
19
|
+
asset: string;
|
|
20
|
+
amount: bigint;
|
|
21
|
+
}): string;
|
|
22
|
+
buildWithdrawOp(params: {
|
|
23
|
+
poolId: string;
|
|
24
|
+
from: string;
|
|
25
|
+
asset: string;
|
|
26
|
+
amount: bigint;
|
|
27
|
+
}): string;
|
|
28
|
+
/**
|
|
29
|
+
* Execute a rebalancing supply via the UserVault.
|
|
30
|
+
*
|
|
31
|
+
* Flow:
|
|
32
|
+
* 1. Build a SorobanAuthorizationEntry for vault.agent_pay(agent → blendPool, amount)
|
|
33
|
+
* 2. Sign it with the agent signer key (NOT admin/owner)
|
|
34
|
+
* 3. POST to the x402 facilitator — it wraps + submits on-chain
|
|
35
|
+
* 4. Vault's smart contract enforces daily limit + destination policy
|
|
36
|
+
*
|
|
37
|
+
* No admin key is ever touched.
|
|
38
|
+
*/
|
|
39
|
+
executeViaVault(params: {
|
|
40
|
+
poolId: string;
|
|
41
|
+
agentSignerSecret: string;
|
|
42
|
+
vaultContract: string;
|
|
43
|
+
asset: string;
|
|
44
|
+
amount: bigint;
|
|
45
|
+
facilitatorUrl: string;
|
|
46
|
+
memo: string;
|
|
47
|
+
}): Promise<{
|
|
48
|
+
txHash: string;
|
|
49
|
+
}>;
|
|
50
|
+
loadUserPosition(vaultAddress: string, poolId?: string): Promise<UserBlendPosition>;
|
|
51
|
+
getDefaultPoolId(): string;
|
|
52
|
+
private getMockPoolData;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=blend-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blend-client.d.ts","sourceRoot":"","sources":["../src/blend-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAc,MAAM,YAAY,CAAC;AAE9F;;;;;GAKG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,GAAG,CAAa;gBAEZ,MAAM,EAAE,aAAa;IAQ3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA4BvD,aAAa,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAoB9F,eAAe,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAoBhG;;;;;;;;;;OAUG;IACG,eAAe,CAAC,MAAM,EAAE;QAC5B,MAAM,EAAE,MAAM,CAAC;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,cAAc,EAAE,MAAM,CAAC;QACvB,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAkFzB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwBzF,gBAAgB,IAAI,MAAM;IAI1B,OAAO,CAAC,eAAe;CAWxB"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { Keypair, Contract, TransactionBuilder, nativeToScVal, authorizeEntry } from "@stellar/stellar-sdk";
|
|
2
|
+
import { Server } from "@stellar/stellar-sdk/rpc";
|
|
3
|
+
/**
|
|
4
|
+
* Blend Protocol client.
|
|
5
|
+
*
|
|
6
|
+
* Reads pool data (rates, reserves, user positions) and builds
|
|
7
|
+
* supply/withdraw operations for the rebalancer.
|
|
8
|
+
*/
|
|
9
|
+
export class BlendClient {
|
|
10
|
+
rpcUrl;
|
|
11
|
+
passphrase;
|
|
12
|
+
usdcAddress;
|
|
13
|
+
defaultPoolId;
|
|
14
|
+
log;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.rpcUrl = config.stellarRpcUrl;
|
|
17
|
+
this.passphrase = config.networkPassphrase;
|
|
18
|
+
this.usdcAddress = config.usdcAddress || "CUSDC";
|
|
19
|
+
this.defaultPoolId = config.blendPoolId || "CCEBVDYM32YNYCVNRXQKDFFPISJJCV557CDZEIRBEE4NCV4KHPQ44HGF";
|
|
20
|
+
this.log = config.logger ?? console;
|
|
21
|
+
}
|
|
22
|
+
async loadPool(poolId) {
|
|
23
|
+
const id = poolId || this.defaultPoolId;
|
|
24
|
+
try {
|
|
25
|
+
const { PoolV2, PoolEstimate } = await import("@blend-capital/blend-sdk");
|
|
26
|
+
const network = { rpc: this.rpcUrl, passphrase: this.passphrase, opts: undefined };
|
|
27
|
+
const pool = await PoolV2.load(network, id);
|
|
28
|
+
const oracle = await pool.loadOracle();
|
|
29
|
+
const estimate = PoolEstimate.build(pool.reserves, oracle);
|
|
30
|
+
const reserves = [];
|
|
31
|
+
for (const [index, reserve] of pool.reserves.entries()) {
|
|
32
|
+
const reserveEst = estimate.reserves?.get(index);
|
|
33
|
+
reserves.push({
|
|
34
|
+
assetId: reserve.assetId,
|
|
35
|
+
symbol: reserve.tokenMetadata?.symbol || `reserve_${index}`,
|
|
36
|
+
supplyApy: reserveEst ? reserveEst.supplyApr * 100 : 0,
|
|
37
|
+
borrowApy: reserveEst ? reserveEst.borrowApr * 100 : 0,
|
|
38
|
+
totalSupply: (reserve.totalSupplyUnderlying?.() ?? reserve.totalSupply ?? 0).toString(),
|
|
39
|
+
totalBorrow: (reserve.totalBorrowsUnderlying?.() ?? reserve.totalBorrow ?? 0).toString(),
|
|
40
|
+
utilization: reserveEst?.utilization || 0,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return { poolId: id, poolName: pool.config?.name || "Blend Pool", reserves, emissions: { blndPerDay: 0, estimatedBlndApy: 0 } };
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
this.log.warn("Blend SDK load failed, using mock data", { error: String(err) });
|
|
47
|
+
return this.getMockPoolData(id);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
buildSupplyOp(params) {
|
|
51
|
+
try {
|
|
52
|
+
const { PoolContract, RequestType } = require("@blend-capital/blend-sdk");
|
|
53
|
+
const poolContract = new PoolContract(params.poolId);
|
|
54
|
+
return poolContract.submit({
|
|
55
|
+
from: params.from,
|
|
56
|
+
spender: params.from,
|
|
57
|
+
to: params.from,
|
|
58
|
+
requests: [{
|
|
59
|
+
amount: params.amount,
|
|
60
|
+
request_type: RequestType.SupplyCollateral,
|
|
61
|
+
address: params.asset,
|
|
62
|
+
}],
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
this.log.info("Building Blend supply op (mock)", params);
|
|
67
|
+
return `mock_supply_op_${params.poolId}_${params.amount}`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
buildWithdrawOp(params) {
|
|
71
|
+
try {
|
|
72
|
+
const { PoolContract, RequestType } = require("@blend-capital/blend-sdk");
|
|
73
|
+
const poolContract = new PoolContract(params.poolId);
|
|
74
|
+
return poolContract.submit({
|
|
75
|
+
from: params.from,
|
|
76
|
+
spender: params.from,
|
|
77
|
+
to: params.from,
|
|
78
|
+
requests: [{
|
|
79
|
+
amount: params.amount,
|
|
80
|
+
request_type: RequestType.WithdrawCollateral,
|
|
81
|
+
address: params.asset,
|
|
82
|
+
}],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
this.log.info("Building Blend withdraw op (mock)", params);
|
|
87
|
+
return `mock_withdraw_op_${params.poolId}_${params.amount}`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Execute a rebalancing supply via the UserVault.
|
|
92
|
+
*
|
|
93
|
+
* Flow:
|
|
94
|
+
* 1. Build a SorobanAuthorizationEntry for vault.agent_pay(agent → blendPool, amount)
|
|
95
|
+
* 2. Sign it with the agent signer key (NOT admin/owner)
|
|
96
|
+
* 3. POST to the x402 facilitator — it wraps + submits on-chain
|
|
97
|
+
* 4. Vault's smart contract enforces daily limit + destination policy
|
|
98
|
+
*
|
|
99
|
+
* No admin key is ever touched.
|
|
100
|
+
*/
|
|
101
|
+
async executeViaVault(params) {
|
|
102
|
+
const agentKeypair = Keypair.fromSecret(params.agentSignerSecret);
|
|
103
|
+
const agentAddress = agentKeypair.publicKey();
|
|
104
|
+
try {
|
|
105
|
+
const rpc = new Server(this.rpcUrl);
|
|
106
|
+
// 1. Build a simulated vault.agent_pay() call to get the auth entry
|
|
107
|
+
const vault = new Contract(params.vaultContract);
|
|
108
|
+
const facilitatorAccount = await rpc.getAccount(agentAddress);
|
|
109
|
+
const tx = new TransactionBuilder(facilitatorAccount, {
|
|
110
|
+
fee: "1000000",
|
|
111
|
+
networkPassphrase: this.passphrase,
|
|
112
|
+
})
|
|
113
|
+
.addOperation(vault.call("agent_pay", nativeToScVal(agentAddress, { type: "address" }), nativeToScVal(params.poolId, { type: "address" }), // Blend pool = pay_to
|
|
114
|
+
nativeToScVal(params.amount, { type: "i128" }), nativeToScVal(params.memo, { type: "symbol" })))
|
|
115
|
+
.setTimeout(60)
|
|
116
|
+
.build();
|
|
117
|
+
// 2. Simulate to get the auth entry that needs to be signed
|
|
118
|
+
const sim = await rpc.simulateTransaction(tx);
|
|
119
|
+
if (!("result" in sim) || !sim.result?.auth?.length) {
|
|
120
|
+
this.log.warn("Vault agent_pay simulation returned no auth entries — using mock", { params });
|
|
121
|
+
return { txHash: "mock_vault_tx_" + Date.now() };
|
|
122
|
+
}
|
|
123
|
+
// 3. Sign the agent's SorobanAuthorizationEntry using the SDK helper
|
|
124
|
+
const latestLedger = await rpc.getLatestLedger();
|
|
125
|
+
const expirationLedger = latestLedger.sequence + 100;
|
|
126
|
+
const signedEntry = await authorizeEntry(sim.result.auth[0], agentKeypair, expirationLedger, this.passphrase);
|
|
127
|
+
const signedAuthEntry = signedEntry.toXDR("base64");
|
|
128
|
+
// 4. POST to x402 facilitator — it submits vault.agent_pay() on-chain
|
|
129
|
+
const response = await fetch(`${params.facilitatorUrl}/api/x402/settle`, {
|
|
130
|
+
method: "POST",
|
|
131
|
+
headers: { "Content-Type": "application/json" },
|
|
132
|
+
body: JSON.stringify({
|
|
133
|
+
x402Version: 1,
|
|
134
|
+
scheme: "stellar-vault",
|
|
135
|
+
network: "stellar:testnet",
|
|
136
|
+
payload: {
|
|
137
|
+
vaultContract: params.vaultContract,
|
|
138
|
+
agentSigner: agentAddress,
|
|
139
|
+
payTo: params.poolId,
|
|
140
|
+
amount: params.amount.toString(),
|
|
141
|
+
asset: params.asset,
|
|
142
|
+
memo: params.memo,
|
|
143
|
+
signedAuthEntry,
|
|
144
|
+
expirationLedger,
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
});
|
|
148
|
+
const result = await response.json();
|
|
149
|
+
if (!result.success)
|
|
150
|
+
throw new Error(result.error || "Facilitator rejected payment");
|
|
151
|
+
this.log.info("Vault agent_pay executed via facilitator", {
|
|
152
|
+
txHash: result.txHash,
|
|
153
|
+
amount: params.amount.toString(),
|
|
154
|
+
vault: params.vaultContract,
|
|
155
|
+
});
|
|
156
|
+
return { txHash: result.txHash };
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
this.log.error("executeViaVault failed", { error: String(err) });
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async loadUserPosition(vaultAddress, poolId) {
|
|
164
|
+
const id = poolId || this.defaultPoolId;
|
|
165
|
+
try {
|
|
166
|
+
const { PoolV2, PositionsEstimate } = await import("@blend-capital/blend-sdk");
|
|
167
|
+
const network = { rpc: this.rpcUrl, passphrase: this.passphrase, opts: undefined };
|
|
168
|
+
const pool = await PoolV2.load(network, id);
|
|
169
|
+
const oracle = await pool.loadOracle();
|
|
170
|
+
const user = await pool.loadUser(vaultAddress);
|
|
171
|
+
if (!user?.positions) {
|
|
172
|
+
return { poolId: id, estimatedSupplyValue: 0, estimatedBorrowValue: 0, netApr: 0 };
|
|
173
|
+
}
|
|
174
|
+
const posEst = PositionsEstimate.build(pool, oracle, user.positions);
|
|
175
|
+
return {
|
|
176
|
+
poolId: id,
|
|
177
|
+
estimatedSupplyValue: posEst.totalSupplied || 0,
|
|
178
|
+
estimatedBorrowValue: posEst.totalBorrowed || 0,
|
|
179
|
+
netApr: posEst.netApy || 0,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
this.log.warn("loadUserPosition failed, returning 0", { vaultAddress, error: String(err) });
|
|
184
|
+
return { poolId: id, estimatedSupplyValue: 0, estimatedBorrowValue: 0, netApr: 0 };
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
getDefaultPoolId() {
|
|
188
|
+
return this.defaultPoolId;
|
|
189
|
+
}
|
|
190
|
+
getMockPoolData(poolId) {
|
|
191
|
+
return {
|
|
192
|
+
poolId,
|
|
193
|
+
poolName: "Blend YieldBox v2 (Mock)",
|
|
194
|
+
reserves: [
|
|
195
|
+
{ assetId: this.usdcAddress, symbol: "USDC", supplyApy: 7.2, borrowApy: 9.8, totalSupply: "45000000000000", totalBorrow: "30000000000000", utilization: 0.67 },
|
|
196
|
+
{ assetId: "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC", symbol: "XLM", supplyApy: 4.1, borrowApy: 6.5, totalSupply: "200000000000000", totalBorrow: "80000000000000", utilization: 0.40 },
|
|
197
|
+
],
|
|
198
|
+
emissions: { blndPerDay: 50000, estimatedBlndApy: 2.3 },
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=blend-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blend-client.js","sourceRoot":"","sources":["../src/blend-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type { YieldStrategy, StrategyResponse, BlendPoolData, UserBlendPosition, SwapQuote, PoolData, AllocationTarget, PortfolioSnapshot, AgentAIConfig, LoggerLike, } from "./types.js";
|
|
2
|
+
export { YieldOptimizer } from "./yield-optimizer.js";
|
|
3
|
+
export { SYSTEM_PROMPT, buildUserPrompt } from "./prompts.js";
|
|
4
|
+
export { BlendClient } from "./blend-client.js";
|
|
5
|
+
export { SoroswapClient } from "./soroswap-client.js";
|
|
6
|
+
export { Rebalancer } from "./rebalancer.js";
|
|
7
|
+
export type { RebalancerOptions } from "./rebalancer.js";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,UAAU,GACX,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// ── Yield Optimizer ──
|
|
2
|
+
export { YieldOptimizer } from "./yield-optimizer.js";
|
|
3
|
+
// ── Prompts ──
|
|
4
|
+
export { SYSTEM_PROMPT, buildUserPrompt } from "./prompts.js";
|
|
5
|
+
// ── Blend Client ──
|
|
6
|
+
export { BlendClient } from "./blend-client.js";
|
|
7
|
+
// ── Soroswap Client ──
|
|
8
|
+
export { SoroswapClient } from "./soroswap-client.js";
|
|
9
|
+
// ── Rebalancer ──
|
|
10
|
+
export { Rebalancer } from "./rebalancer.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,wBAAwB;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,gBAAgB;AAChB,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE9D,qBAAqB;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,wBAAwB;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,mBAAmB;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const SYSTEM_PROMPT = "You are a DeFi yield optimization AI for Stellar blockchain.\nYou analyze live pool data from Blend Protocol, Soroswap DEX, DeFindex vaults, and RWA tokens\n(Ondo USDY, Centrifuge deRWAs) to recommend optimal yield strategies.\n\nRESPOND WITH ONLY A JSON OBJECT (no markdown, no explanation outside JSON):\n{\n \"strategies\": [\n {\n \"protocol\": \"Protocol Name\",\n \"action\": \"What to do (e.g. 'Supply USDC to Blend Fixed V2')\",\n \"allocation_pct\": 35.0,\n \"estimated_apy\": 7.2,\n \"risk_level\": \"low|moderate|high\",\n \"details\": \"Brief explanation including risk factors\"\n }\n ],\n \"total_estimated_apy\": 8.1,\n \"summary\": \"2-3 sentence strategy summary\"\n}\n\nRULES:\n- allocation_pct values MUST sum to exactly 100\n- Max 5 strategies\n- low risk: favor USDY, Blend fixed pools, stablecoin LPs\n- moderate: mix lending, auto-compound vaults, small LP allocation\n- high: heavier LP, multi-strategy vaults, leveraged if available\n- Always include at least one low-risk component\n- Consider impermanent loss risk for AMM positions\n- Factor in BLND emission rewards for Blend pools";
|
|
2
|
+
export declare function buildUserPrompt(query: string, poolContext: string, risk: string, amount?: number): string;
|
|
3
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,moCA4BwB,CAAC;AAEnD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CASR"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export const SYSTEM_PROMPT = `You are a DeFi yield optimization AI for Stellar blockchain.
|
|
2
|
+
You analyze live pool data from Blend Protocol, Soroswap DEX, DeFindex vaults, and RWA tokens
|
|
3
|
+
(Ondo USDY, Centrifuge deRWAs) to recommend optimal yield strategies.
|
|
4
|
+
|
|
5
|
+
RESPOND WITH ONLY A JSON OBJECT (no markdown, no explanation outside JSON):
|
|
6
|
+
{
|
|
7
|
+
"strategies": [
|
|
8
|
+
{
|
|
9
|
+
"protocol": "Protocol Name",
|
|
10
|
+
"action": "What to do (e.g. 'Supply USDC to Blend Fixed V2')",
|
|
11
|
+
"allocation_pct": 35.0,
|
|
12
|
+
"estimated_apy": 7.2,
|
|
13
|
+
"risk_level": "low|moderate|high",
|
|
14
|
+
"details": "Brief explanation including risk factors"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"total_estimated_apy": 8.1,
|
|
18
|
+
"summary": "2-3 sentence strategy summary"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
RULES:
|
|
22
|
+
- allocation_pct values MUST sum to exactly 100
|
|
23
|
+
- Max 5 strategies
|
|
24
|
+
- low risk: favor USDY, Blend fixed pools, stablecoin LPs
|
|
25
|
+
- moderate: mix lending, auto-compound vaults, small LP allocation
|
|
26
|
+
- high: heavier LP, multi-strategy vaults, leveraged if available
|
|
27
|
+
- Always include at least one low-risk component
|
|
28
|
+
- Consider impermanent loss risk for AMM positions
|
|
29
|
+
- Factor in BLND emission rewards for Blend pools`;
|
|
30
|
+
export function buildUserPrompt(query, poolContext, risk, amount) {
|
|
31
|
+
return `User query: "${query}"
|
|
32
|
+
Risk tolerance: ${risk}
|
|
33
|
+
${amount ? `Amount to allocate: ${amount} USDC` : ""}
|
|
34
|
+
|
|
35
|
+
LIVE POOL DATA:
|
|
36
|
+
${poolContext}
|
|
37
|
+
|
|
38
|
+
Generate the optimal allocation strategy as JSON.`;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;kDA4BqB,CAAC;AAEnD,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,WAAmB,EACnB,IAAY,EACZ,MAAe;IAEf,OAAO,gBAAgB,KAAK;kBACZ,IAAI;EACpB,MAAM,CAAC,CAAC,CAAC,uBAAuB,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE;;;EAGlD,WAAW;;kDAEqC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { BlendClient } from "./blend-client.js";
|
|
2
|
+
import type { SoroswapClient } from "./soroswap-client.js";
|
|
3
|
+
import type { AllocationTarget, PortfolioSnapshot, LoggerLike } from "./types.js";
|
|
4
|
+
export interface RebalancerOptions {
|
|
5
|
+
driftThresholdPct: number;
|
|
6
|
+
/**
|
|
7
|
+
* Agent signer secret key — authorized on the user's vault.
|
|
8
|
+
* Replaces the old adminSecret. No owner/admin key needed.
|
|
9
|
+
*/
|
|
10
|
+
agentSignerSecret?: string;
|
|
11
|
+
/**
|
|
12
|
+
* The UserVault contract address funds flow from.
|
|
13
|
+
*/
|
|
14
|
+
vaultContract?: string;
|
|
15
|
+
/**
|
|
16
|
+
* x402 facilitator URL for submitting vault.agent_pay() calls.
|
|
17
|
+
*/
|
|
18
|
+
facilitatorUrl?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Rebalancing engine (no cron — apps schedule their own calls).
|
|
22
|
+
*
|
|
23
|
+
* All fund movements go through the UserVault via agent_pay():
|
|
24
|
+
* agent signs → facilitator submits → vault enforces limits on-chain
|
|
25
|
+
*
|
|
26
|
+
* No admin or owner key is ever needed.
|
|
27
|
+
*
|
|
28
|
+
* Usage:
|
|
29
|
+
* ```ts
|
|
30
|
+
* const rebalancer = new Rebalancer(blendClient, soroswapClient, {
|
|
31
|
+
* driftThresholdPct: 5,
|
|
32
|
+
* agentSignerSecret: process.env.AGENT_SIGNER_SECRET_KEY,
|
|
33
|
+
* vaultContract: "C...",
|
|
34
|
+
* facilitatorUrl: "http://localhost:3001",
|
|
35
|
+
* });
|
|
36
|
+
* rebalancer.setTargetAllocation(targets);
|
|
37
|
+
* await rebalancer.checkAndRebalance();
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class Rebalancer {
|
|
41
|
+
private blendClient;
|
|
42
|
+
private soroswapClient;
|
|
43
|
+
private options;
|
|
44
|
+
private log;
|
|
45
|
+
private lastStrategy;
|
|
46
|
+
private rebalanceCount;
|
|
47
|
+
constructor(blendClient: BlendClient, soroswapClient: SoroswapClient, options: RebalancerOptions, logger?: LoggerLike);
|
|
48
|
+
/** Set the target allocation (called after AI generates a strategy). */
|
|
49
|
+
setTargetAllocation(targets: AllocationTarget[]): void;
|
|
50
|
+
getTargetAllocation(): AllocationTarget[];
|
|
51
|
+
getRebalanceCount(): number;
|
|
52
|
+
/**
|
|
53
|
+
* Read current on-chain portfolio positions from Blend and Soroswap.
|
|
54
|
+
* Returns a snapshot with per-protocol USDC values and percentages.
|
|
55
|
+
*/
|
|
56
|
+
readCurrentPortfolio(vaultAddress: string): Promise<PortfolioSnapshot>;
|
|
57
|
+
/** Check if rebalancing is needed and execute if so. */
|
|
58
|
+
checkAndRebalance(): Promise<void>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=rebalancer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebalancer.d.ts","sourceRoot":"","sources":["../src/rebalancer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAElF,MAAM,WAAW,iBAAiB;IAChC,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,cAAc,CAAK;gBAGzB,WAAW,EAAE,WAAW,EACxB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,iBAAiB,EAC1B,MAAM,CAAC,EAAE,UAAU;IAQrB,wEAAwE;IACxE,mBAAmB,CAAC,OAAO,EAAE,gBAAgB,EAAE;IAK/C,mBAAmB,IAAI,gBAAgB,EAAE;IAIzC,iBAAiB,IAAI,MAAM;IAI3B;;;OAGG;IACG,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA6B5E,wDAAwD;IAClD,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAoGzC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rebalancing engine (no cron — apps schedule their own calls).
|
|
3
|
+
*
|
|
4
|
+
* All fund movements go through the UserVault via agent_pay():
|
|
5
|
+
* agent signs → facilitator submits → vault enforces limits on-chain
|
|
6
|
+
*
|
|
7
|
+
* No admin or owner key is ever needed.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```ts
|
|
11
|
+
* const rebalancer = new Rebalancer(blendClient, soroswapClient, {
|
|
12
|
+
* driftThresholdPct: 5,
|
|
13
|
+
* agentSignerSecret: process.env.AGENT_SIGNER_SECRET_KEY,
|
|
14
|
+
* vaultContract: "C...",
|
|
15
|
+
* facilitatorUrl: "http://localhost:3001",
|
|
16
|
+
* });
|
|
17
|
+
* rebalancer.setTargetAllocation(targets);
|
|
18
|
+
* await rebalancer.checkAndRebalance();
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export class Rebalancer {
|
|
22
|
+
blendClient;
|
|
23
|
+
soroswapClient;
|
|
24
|
+
options;
|
|
25
|
+
log;
|
|
26
|
+
lastStrategy = [];
|
|
27
|
+
rebalanceCount = 0;
|
|
28
|
+
constructor(blendClient, soroswapClient, options, logger) {
|
|
29
|
+
this.blendClient = blendClient;
|
|
30
|
+
this.soroswapClient = soroswapClient;
|
|
31
|
+
this.options = options;
|
|
32
|
+
this.log = logger ?? console;
|
|
33
|
+
}
|
|
34
|
+
/** Set the target allocation (called after AI generates a strategy). */
|
|
35
|
+
setTargetAllocation(targets) {
|
|
36
|
+
this.lastStrategy = targets;
|
|
37
|
+
this.log.info("Target allocation updated", { targets });
|
|
38
|
+
}
|
|
39
|
+
getTargetAllocation() {
|
|
40
|
+
return this.lastStrategy;
|
|
41
|
+
}
|
|
42
|
+
getRebalanceCount() {
|
|
43
|
+
return this.rebalanceCount;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Read current on-chain portfolio positions from Blend and Soroswap.
|
|
47
|
+
* Returns a snapshot with per-protocol USDC values and percentages.
|
|
48
|
+
*/
|
|
49
|
+
async readCurrentPortfolio(vaultAddress) {
|
|
50
|
+
const [blendPos, soroPos] = await Promise.all([
|
|
51
|
+
this.blendClient.loadUserPosition(vaultAddress),
|
|
52
|
+
this.soroswapClient.loadLPPosition(vaultAddress),
|
|
53
|
+
]);
|
|
54
|
+
const blendUSDC = blendPos.estimatedSupplyValue - blendPos.estimatedBorrowValue;
|
|
55
|
+
const soroUSDC = soroPos.valueUSDC;
|
|
56
|
+
const totalUSDC = blendUSDC + soroUSDC;
|
|
57
|
+
const positions = [
|
|
58
|
+
{
|
|
59
|
+
protocol: "blend",
|
|
60
|
+
poolId: blendPos.poolId,
|
|
61
|
+
usdcValue: blendUSDC,
|
|
62
|
+
pct: totalUSDC > 0 ? (blendUSDC / totalUSDC) * 100 : 0,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
protocol: "soroswap",
|
|
66
|
+
poolId: soroPos.pairAddress,
|
|
67
|
+
usdcValue: soroUSDC,
|
|
68
|
+
pct: totalUSDC > 0 ? (soroUSDC / totalUSDC) * 100 : 0,
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
this.log.info("Current portfolio snapshot", { vaultAddress, totalUSDC, positions });
|
|
72
|
+
return { totalUSDC, positions };
|
|
73
|
+
}
|
|
74
|
+
/** Check if rebalancing is needed and execute if so. */
|
|
75
|
+
async checkAndRebalance() {
|
|
76
|
+
if (this.lastStrategy.length === 0) {
|
|
77
|
+
this.log.debug("No target strategy set, skipping rebalance check");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const { agentSignerSecret, vaultContract, facilitatorUrl } = this.options;
|
|
81
|
+
if (!agentSignerSecret || !vaultContract) {
|
|
82
|
+
this.log.warn("Rebalancer: agentSignerSecret and vaultContract are required for execution. " +
|
|
83
|
+
"Set them in RebalancerOptions to enable on-chain rebalancing.");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
// 1. Read actual on-chain positions
|
|
88
|
+
const snapshot = await this.readCurrentPortfolio(vaultContract);
|
|
89
|
+
// 2. Update currentPct on each target from real snapshot
|
|
90
|
+
const updatedStrategy = this.lastStrategy.map(target => {
|
|
91
|
+
const pos = snapshot.positions.find(p => p.protocol === target.protocol);
|
|
92
|
+
return { ...target, currentPct: pos?.pct ?? target.currentPct };
|
|
93
|
+
});
|
|
94
|
+
const blendData = await this.blendClient.loadPool();
|
|
95
|
+
const driftThreshold = this.options.driftThresholdPct;
|
|
96
|
+
const url = facilitatorUrl ?? "http://localhost:3001";
|
|
97
|
+
// 3. Separate into withdraws (over-allocated) and supplies (under-allocated)
|
|
98
|
+
const toWithdraw = [];
|
|
99
|
+
const toSupply = [];
|
|
100
|
+
for (const target of updatedStrategy) {
|
|
101
|
+
const drift = Math.abs(target.currentPct - target.targetPct);
|
|
102
|
+
if (drift <= driftThreshold)
|
|
103
|
+
continue;
|
|
104
|
+
const delta = target.targetPct - target.currentPct;
|
|
105
|
+
this.log.info(`Drift detected: ${drift.toFixed(1)}% > ${driftThreshold}%`, { target, delta });
|
|
106
|
+
if (delta < 0) {
|
|
107
|
+
toWithdraw.push({ target, drift, delta });
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
toSupply.push({ target, drift, delta });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (toWithdraw.length === 0 && toSupply.length === 0) {
|
|
114
|
+
this.log.debug("Portfolio within threshold, no rebalance needed");
|
|
115
|
+
this.rebalanceCount++;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// 4. Execute ALL withdraws first
|
|
119
|
+
for (const { target, delta } of toWithdraw) {
|
|
120
|
+
if (target.protocol === "blend") {
|
|
121
|
+
try {
|
|
122
|
+
const result = await this.blendClient.executeViaVault({
|
|
123
|
+
poolId: blendData.poolId,
|
|
124
|
+
agentSignerSecret,
|
|
125
|
+
vaultContract,
|
|
126
|
+
asset: target.asset,
|
|
127
|
+
amount: BigInt(Math.round(Math.abs(delta) * 100_0000000)),
|
|
128
|
+
facilitatorUrl: url,
|
|
129
|
+
memo: "rebalance_withdraw",
|
|
130
|
+
});
|
|
131
|
+
this.log.info("Rebalance withdraw executed via vault", { txHash: result.txHash, target });
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
this.log.error("Rebalance withdraw failed", { target, error: err });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// 5. Then execute ALL supplies
|
|
139
|
+
for (const { target, delta } of toSupply) {
|
|
140
|
+
if (target.protocol === "blend") {
|
|
141
|
+
try {
|
|
142
|
+
const result = await this.blendClient.executeViaVault({
|
|
143
|
+
poolId: blendData.poolId,
|
|
144
|
+
agentSignerSecret,
|
|
145
|
+
vaultContract,
|
|
146
|
+
asset: target.asset,
|
|
147
|
+
amount: BigInt(Math.round(Math.abs(delta) * 100_0000000)),
|
|
148
|
+
facilitatorUrl: url,
|
|
149
|
+
memo: "rebalance_supply",
|
|
150
|
+
});
|
|
151
|
+
this.log.info("Rebalance supply executed via vault", { txHash: result.txHash, target });
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
this.log.error("Rebalance supply failed", { target, error: err });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
this.rebalanceCount++;
|
|
159
|
+
this.log.debug("Rebalance check complete", { count: this.rebalanceCount });
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
this.log.error("Rebalance check failed", { error: err });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=rebalancer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebalancer.js","sourceRoot":"","sources":["../src/rebalancer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AgentAIConfig, SwapQuote, PoolData } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Soroswap DEX client.
|
|
4
|
+
*
|
|
5
|
+
* Provides swap quotes, pool liquidity data, and swap execution for rebalancing.
|
|
6
|
+
*/
|
|
7
|
+
export declare class SoroswapClient {
|
|
8
|
+
private sdk;
|
|
9
|
+
private usdcAddress;
|
|
10
|
+
private rpcUrl;
|
|
11
|
+
private passphrase;
|
|
12
|
+
private log;
|
|
13
|
+
constructor(config: AgentAIConfig);
|
|
14
|
+
private initSdk;
|
|
15
|
+
getQuote(params: {
|
|
16
|
+
assetIn: string;
|
|
17
|
+
assetOut: string;
|
|
18
|
+
amount: bigint;
|
|
19
|
+
}): Promise<SwapQuote>;
|
|
20
|
+
buildSwap(params: {
|
|
21
|
+
assetIn: string;
|
|
22
|
+
assetOut: string;
|
|
23
|
+
amount: bigint;
|
|
24
|
+
from: string;
|
|
25
|
+
}): Promise<string | null>;
|
|
26
|
+
loadLPPosition(vaultAddress: string, pairAddress?: string): Promise<{
|
|
27
|
+
pairAddress: string;
|
|
28
|
+
valueUSDC: number;
|
|
29
|
+
}>;
|
|
30
|
+
getPools(): Promise<PoolData[]>;
|
|
31
|
+
private getMockQuote;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=soroswap-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"soroswap-client.d.ts","sourceRoot":"","sources":["../src/soroswap-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAc,MAAM,YAAY,CAAC;AAEjF;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,GAAG,CAAa;gBAEZ,MAAM,EAAE,aAAa;YAUnB,OAAO;IAaf,QAAQ,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IA2B3F,SAAS,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAqB9G,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IA0C/G,QAAQ,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAarC,OAAO,CAAC,YAAY;CAUrB"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Soroswap DEX client.
|
|
3
|
+
*
|
|
4
|
+
* Provides swap quotes, pool liquidity data, and swap execution for rebalancing.
|
|
5
|
+
*/
|
|
6
|
+
export class SoroswapClient {
|
|
7
|
+
sdk = null;
|
|
8
|
+
usdcAddress;
|
|
9
|
+
rpcUrl;
|
|
10
|
+
passphrase;
|
|
11
|
+
log;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.usdcAddress = config.usdcAddress || "CUSDC";
|
|
14
|
+
this.rpcUrl = config.stellarRpcUrl;
|
|
15
|
+
this.passphrase = config.networkPassphrase;
|
|
16
|
+
this.log = config.logger ?? console;
|
|
17
|
+
if (config.soroswapApiKey) {
|
|
18
|
+
this.initSdk(config.soroswapApiKey);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
async initSdk(apiKey) {
|
|
22
|
+
try {
|
|
23
|
+
const { SoroswapSDK, SupportedNetworks } = await import("@soroswap/sdk");
|
|
24
|
+
this.sdk = new SoroswapSDK({
|
|
25
|
+
apiKey,
|
|
26
|
+
defaultNetwork: SupportedNetworks.TESTNET,
|
|
27
|
+
});
|
|
28
|
+
this.log.info("Soroswap SDK initialized");
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
this.log.warn("Soroswap SDK init failed, using mock", { error: String(err) });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async getQuote(params) {
|
|
35
|
+
if (this.sdk) {
|
|
36
|
+
try {
|
|
37
|
+
const { SupportedNetworks, SupportedProtocols, TradeType } = await import("@soroswap/sdk");
|
|
38
|
+
const quote = await this.sdk.quote({
|
|
39
|
+
assetIn: params.assetIn,
|
|
40
|
+
assetOut: params.assetOut,
|
|
41
|
+
amount: params.amount,
|
|
42
|
+
tradeType: TradeType.EXACT_IN,
|
|
43
|
+
protocols: [SupportedProtocols.SOROSWAP],
|
|
44
|
+
slippageBps: "100",
|
|
45
|
+
network: SupportedNetworks.TESTNET,
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
amountIn: quote.amountIn?.toString() || "0",
|
|
49
|
+
amountOut: quote.amountOut?.toString() || "0",
|
|
50
|
+
priceImpact: quote.priceImpact || 0,
|
|
51
|
+
route: quote.path || [],
|
|
52
|
+
protocol: "soroswap",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
this.log.error("Soroswap quote failed", { error: String(err) });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return this.getMockQuote(params);
|
|
60
|
+
}
|
|
61
|
+
async buildSwap(params) {
|
|
62
|
+
if (!this.sdk)
|
|
63
|
+
return null;
|
|
64
|
+
try {
|
|
65
|
+
const { SupportedNetworks, SupportedProtocols, TradeType } = await import("@soroswap/sdk");
|
|
66
|
+
const quote = await this.sdk.quote({
|
|
67
|
+
assetIn: params.assetIn,
|
|
68
|
+
assetOut: params.assetOut,
|
|
69
|
+
amount: params.amount,
|
|
70
|
+
tradeType: TradeType.EXACT_IN,
|
|
71
|
+
protocols: [SupportedProtocols.SOROSWAP],
|
|
72
|
+
slippageBps: "100",
|
|
73
|
+
network: SupportedNetworks.TESTNET,
|
|
74
|
+
});
|
|
75
|
+
const buildResult = await this.sdk.build({ quote, from: params.from });
|
|
76
|
+
return buildResult?.xdr || null;
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
this.log.error("Soroswap build failed", { error: String(err) });
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async loadLPPosition(vaultAddress, pairAddress) {
|
|
84
|
+
const pair = pairAddress || "SOROSWAP_USDC_XLM_PAIR";
|
|
85
|
+
try {
|
|
86
|
+
const { Contract, TransactionBuilder, nativeToScVal, scValToNative } = await import("@stellar/stellar-sdk");
|
|
87
|
+
const { Server: RpcServer } = await import("@stellar/stellar-sdk/rpc");
|
|
88
|
+
const rpc = new RpcServer(this.rpcUrl);
|
|
89
|
+
const pairContract = new Contract(pair);
|
|
90
|
+
const sourceAccount = await rpc.getAccount(vaultAddress).catch(() => null);
|
|
91
|
+
if (!sourceAccount)
|
|
92
|
+
return { pairAddress: pair, valueUSDC: 0 };
|
|
93
|
+
const balanceTx = new TransactionBuilder(sourceAccount, { fee: "100", networkPassphrase: this.passphrase })
|
|
94
|
+
.addOperation(pairContract.call("balance", nativeToScVal(vaultAddress, { type: "address" })))
|
|
95
|
+
.setTimeout(10).build();
|
|
96
|
+
const balanceSim = await rpc.simulateTransaction(balanceTx);
|
|
97
|
+
if (!("result" in balanceSim) || !balanceSim.result?.retval)
|
|
98
|
+
return { pairAddress: pair, valueUSDC: 0 };
|
|
99
|
+
const lpBalance = scValToNative(balanceSim.result.retval);
|
|
100
|
+
const supplyTx = new TransactionBuilder(sourceAccount, { fee: "100", networkPassphrase: this.passphrase })
|
|
101
|
+
.addOperation(pairContract.call("total_supply"))
|
|
102
|
+
.setTimeout(10).build();
|
|
103
|
+
const supplySim = await rpc.simulateTransaction(supplyTx);
|
|
104
|
+
if (!("result" in supplySim) || !supplySim.result?.retval)
|
|
105
|
+
return { pairAddress: pair, valueUSDC: 0 };
|
|
106
|
+
const totalSupply = scValToNative(supplySim.result.retval);
|
|
107
|
+
if (totalSupply === 0n)
|
|
108
|
+
return { pairAddress: pair, valueUSDC: 0 };
|
|
109
|
+
const reservesTx = new TransactionBuilder(sourceAccount, { fee: "100", networkPassphrase: this.passphrase })
|
|
110
|
+
.addOperation(pairContract.call("get_reserves"))
|
|
111
|
+
.setTimeout(10).build();
|
|
112
|
+
const reservesSim = await rpc.simulateTransaction(reservesTx);
|
|
113
|
+
if (!("result" in reservesSim) || !reservesSim.result?.retval)
|
|
114
|
+
return { pairAddress: pair, valueUSDC: 0 };
|
|
115
|
+
const [reserve0] = scValToNative(reservesSim.result.retval);
|
|
116
|
+
// vault's USDC share = (lpBalance / totalSupply) * reserve0 (if token0 = USDC)
|
|
117
|
+
const usdcValue = Number((lpBalance * reserve0) / totalSupply) / 1e7;
|
|
118
|
+
return { pairAddress: pair, valueUSDC: usdcValue };
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
this.log.warn("loadLPPosition failed, returning 0", { pair, error: String(err) });
|
|
122
|
+
return { pairAddress: pair, valueUSDC: 0 };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async getPools() {
|
|
126
|
+
return [
|
|
127
|
+
{
|
|
128
|
+
pairAddress: "SOROSWAP_USDC_XLM_PAIR",
|
|
129
|
+
token0: this.usdcAddress,
|
|
130
|
+
token1: "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
|
|
131
|
+
reserve0: "4800000000000",
|
|
132
|
+
reserve1: "120000000000000",
|
|
133
|
+
apy: 12.5,
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
}
|
|
137
|
+
getMockQuote(params) {
|
|
138
|
+
const rate = 4n;
|
|
139
|
+
return {
|
|
140
|
+
amountIn: params.amount.toString(),
|
|
141
|
+
amountOut: (params.amount * rate).toString(),
|
|
142
|
+
priceImpact: 0.02,
|
|
143
|
+
route: [params.assetIn, params.assetOut],
|
|
144
|
+
protocol: "soroswap-mock",
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=soroswap-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"soroswap-client.js","sourceRoot":"","sources":["../src/soroswap-client.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export interface YieldStrategy {
|
|
2
|
+
protocol: string;
|
|
3
|
+
action: string;
|
|
4
|
+
allocation_pct: number;
|
|
5
|
+
estimated_apy: number;
|
|
6
|
+
risk_level: "low" | "moderate" | "high";
|
|
7
|
+
details: string;
|
|
8
|
+
}
|
|
9
|
+
export interface StrategyResponse {
|
|
10
|
+
query: string;
|
|
11
|
+
risk_tolerance: string;
|
|
12
|
+
amount_usdc?: number;
|
|
13
|
+
strategies: YieldStrategy[];
|
|
14
|
+
total_estimated_apy: number;
|
|
15
|
+
summary: string;
|
|
16
|
+
data_sources: {
|
|
17
|
+
blend_pools: number;
|
|
18
|
+
soroswap_pools: number;
|
|
19
|
+
rwa_sources: number;
|
|
20
|
+
};
|
|
21
|
+
disclaimer: string;
|
|
22
|
+
x402?: {
|
|
23
|
+
txHash: string;
|
|
24
|
+
payer: string;
|
|
25
|
+
agentId: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface BlendPoolData {
|
|
29
|
+
poolId: string;
|
|
30
|
+
poolName: string;
|
|
31
|
+
reserves: Array<{
|
|
32
|
+
assetId: string;
|
|
33
|
+
symbol: string;
|
|
34
|
+
supplyApy: number;
|
|
35
|
+
borrowApy: number;
|
|
36
|
+
totalSupply: string;
|
|
37
|
+
totalBorrow: string;
|
|
38
|
+
utilization: number;
|
|
39
|
+
}>;
|
|
40
|
+
emissions: {
|
|
41
|
+
blndPerDay: number;
|
|
42
|
+
estimatedBlndApy: number;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export interface UserBlendPosition {
|
|
46
|
+
poolId: string;
|
|
47
|
+
estimatedSupplyValue: number;
|
|
48
|
+
estimatedBorrowValue: number;
|
|
49
|
+
netApr: number;
|
|
50
|
+
}
|
|
51
|
+
export interface SwapQuote {
|
|
52
|
+
amountIn: string;
|
|
53
|
+
amountOut: string;
|
|
54
|
+
priceImpact: number;
|
|
55
|
+
route: string[];
|
|
56
|
+
protocol: string;
|
|
57
|
+
}
|
|
58
|
+
export interface PoolData {
|
|
59
|
+
pairAddress: string;
|
|
60
|
+
token0: string;
|
|
61
|
+
token1: string;
|
|
62
|
+
reserve0: string;
|
|
63
|
+
reserve1: string;
|
|
64
|
+
apy: number;
|
|
65
|
+
}
|
|
66
|
+
export interface AllocationTarget {
|
|
67
|
+
protocol: string;
|
|
68
|
+
asset: string;
|
|
69
|
+
targetPct: number;
|
|
70
|
+
currentPct: number;
|
|
71
|
+
}
|
|
72
|
+
export interface PortfolioSnapshot {
|
|
73
|
+
totalUSDC: number;
|
|
74
|
+
positions: Array<{
|
|
75
|
+
protocol: string;
|
|
76
|
+
poolId: string;
|
|
77
|
+
usdcValue: number;
|
|
78
|
+
pct: number;
|
|
79
|
+
}>;
|
|
80
|
+
}
|
|
81
|
+
export interface AgentAIConfig {
|
|
82
|
+
stellarRpcUrl: string;
|
|
83
|
+
networkPassphrase: string;
|
|
84
|
+
anthropicApiKey?: string;
|
|
85
|
+
soroswapApiKey?: string;
|
|
86
|
+
usdcAddress?: string;
|
|
87
|
+
blendPoolId?: string;
|
|
88
|
+
logger?: LoggerLike;
|
|
89
|
+
/**
|
|
90
|
+
* The agent's Stellar secret key (authorized on the user's vault).
|
|
91
|
+
* Used to sign SorobanAuthorizationEntry for vault.agent_pay() calls.
|
|
92
|
+
* Never needs admin/owner key — vault policy enforces limits on-chain.
|
|
93
|
+
*/
|
|
94
|
+
agentSignerSecret?: string;
|
|
95
|
+
/**
|
|
96
|
+
* The user's UserVault contract address.
|
|
97
|
+
* All rebalancing payments flow through this vault via agent_pay().
|
|
98
|
+
*/
|
|
99
|
+
vaultContract?: string;
|
|
100
|
+
/**
|
|
101
|
+
* URL of the x402 facilitator endpoint.
|
|
102
|
+
* Defaults to local backend.
|
|
103
|
+
*/
|
|
104
|
+
facilitatorUrl?: string;
|
|
105
|
+
}
|
|
106
|
+
export interface LoggerLike {
|
|
107
|
+
info(message: string, ...args: any[]): void;
|
|
108
|
+
warn(message: string, ...args: any[]): void;
|
|
109
|
+
error(message: string, ...args: any[]): void;
|
|
110
|
+
debug(message: string, ...args: any[]): void;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0BAA0B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BlendClient } from "./blend-client.js";
|
|
2
|
+
import { SoroswapClient } from "./soroswap-client.js";
|
|
3
|
+
import { Rebalancer } from "./rebalancer.js";
|
|
4
|
+
import type { AgentAIConfig, StrategyResponse } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* AI-powered yield optimization engine.
|
|
7
|
+
*
|
|
8
|
+
* Pipeline:
|
|
9
|
+
* 1. Fetch live data from Blend (APYs, utilization) + Soroswap (swap rates)
|
|
10
|
+
* 2. Format as structured context for Claude
|
|
11
|
+
* 3. Claude generates allocation strategy based on risk tolerance
|
|
12
|
+
* 4. Parse + validate strategy
|
|
13
|
+
* 5. Optionally trigger rebalancer with new targets
|
|
14
|
+
*/
|
|
15
|
+
export declare class YieldOptimizer {
|
|
16
|
+
private anthropic;
|
|
17
|
+
private blendClient;
|
|
18
|
+
private soroswapClient;
|
|
19
|
+
private rebalancer;
|
|
20
|
+
private usdcAddress;
|
|
21
|
+
private log;
|
|
22
|
+
private config;
|
|
23
|
+
constructor(config: AgentAIConfig, rebalancer?: Rebalancer);
|
|
24
|
+
/** Get the internal BlendClient instance. */
|
|
25
|
+
getBlendClient(): BlendClient;
|
|
26
|
+
/** Get the internal SoroswapClient instance. */
|
|
27
|
+
getSoroswapClient(): SoroswapClient;
|
|
28
|
+
optimize(query: string, riskTolerance?: string, amount?: number): Promise<StrategyResponse>;
|
|
29
|
+
private generateWithClaude;
|
|
30
|
+
private formatPoolContext;
|
|
31
|
+
private fallbackStrategy;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=yield-optimizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yield-optimizer.d.ts","sourceRoot":"","sources":["../src/yield-optimizer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,KAAK,EACV,aAAa,EAEb,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;GASG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAmB;IACpC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,UAAU,CAAoB;IACtC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,GAAG,CAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,UAAU;IAY1D,6CAA6C;IAC7C,cAAc,IAAI,WAAW;IAI7B,gDAAgD;IAChD,iBAAiB,IAAI,cAAc;IAI7B,QAAQ,CACZ,KAAK,EAAE,MAAM,EACb,aAAa,GAAE,MAAmB,EAClC,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,CAAC;YA0Dd,kBAAkB;IAqBhC,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,gBAAgB;CAoCzB"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
2
|
+
import { BlendClient } from "./blend-client.js";
|
|
3
|
+
import { SoroswapClient } from "./soroswap-client.js";
|
|
4
|
+
import { SYSTEM_PROMPT, buildUserPrompt } from "./prompts.js";
|
|
5
|
+
/**
|
|
6
|
+
* AI-powered yield optimization engine.
|
|
7
|
+
*
|
|
8
|
+
* Pipeline:
|
|
9
|
+
* 1. Fetch live data from Blend (APYs, utilization) + Soroswap (swap rates)
|
|
10
|
+
* 2. Format as structured context for Claude
|
|
11
|
+
* 3. Claude generates allocation strategy based on risk tolerance
|
|
12
|
+
* 4. Parse + validate strategy
|
|
13
|
+
* 5. Optionally trigger rebalancer with new targets
|
|
14
|
+
*/
|
|
15
|
+
export class YieldOptimizer {
|
|
16
|
+
anthropic;
|
|
17
|
+
blendClient;
|
|
18
|
+
soroswapClient;
|
|
19
|
+
rebalancer;
|
|
20
|
+
usdcAddress;
|
|
21
|
+
log;
|
|
22
|
+
config;
|
|
23
|
+
constructor(config, rebalancer) {
|
|
24
|
+
this.config = config;
|
|
25
|
+
this.anthropic = config.anthropicApiKey
|
|
26
|
+
? new Anthropic({ apiKey: config.anthropicApiKey })
|
|
27
|
+
: null;
|
|
28
|
+
this.blendClient = new BlendClient(config);
|
|
29
|
+
this.soroswapClient = new SoroswapClient(config);
|
|
30
|
+
this.rebalancer = rebalancer ?? null;
|
|
31
|
+
this.usdcAddress = config.usdcAddress || "";
|
|
32
|
+
this.log = config.logger ?? console;
|
|
33
|
+
}
|
|
34
|
+
/** Get the internal BlendClient instance. */
|
|
35
|
+
getBlendClient() {
|
|
36
|
+
return this.blendClient;
|
|
37
|
+
}
|
|
38
|
+
/** Get the internal SoroswapClient instance. */
|
|
39
|
+
getSoroswapClient() {
|
|
40
|
+
return this.soroswapClient;
|
|
41
|
+
}
|
|
42
|
+
async optimize(query, riskTolerance = "moderate", amount) {
|
|
43
|
+
const [blendData, soroswapPools] = await Promise.all([
|
|
44
|
+
this.blendClient.loadPool(),
|
|
45
|
+
this.soroswapClient.getPools(),
|
|
46
|
+
]);
|
|
47
|
+
const poolContext = this.formatPoolContext(blendData, soroswapPools);
|
|
48
|
+
let strategy;
|
|
49
|
+
if (this.anthropic) {
|
|
50
|
+
try {
|
|
51
|
+
strategy = await this.generateWithClaude(query, poolContext, riskTolerance, amount);
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
this.log.warn("Claude unavailable, using fallback strategy", { error: err });
|
|
55
|
+
strategy = this.fallbackStrategy(riskTolerance, amount);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
strategy = this.fallbackStrategy(riskTolerance, amount);
|
|
60
|
+
}
|
|
61
|
+
if (this.rebalancer && strategy.strategies.length > 0) {
|
|
62
|
+
let snapshot = null;
|
|
63
|
+
if (this.config.vaultContract) {
|
|
64
|
+
try {
|
|
65
|
+
snapshot = await this.rebalancer.readCurrentPortfolio(this.config.vaultContract);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
this.log.warn("Could not read current portfolio, using currentPct: 0", { error: err });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
this.rebalancer.setTargetAllocation(strategy.strategies.map(s => {
|
|
72
|
+
const protocol = s.protocol.toLowerCase().includes("blend") ? "blend" : "soroswap";
|
|
73
|
+
const pos = snapshot?.positions.find(p => p.protocol === protocol);
|
|
74
|
+
return {
|
|
75
|
+
protocol,
|
|
76
|
+
asset: this.usdcAddress,
|
|
77
|
+
targetPct: s.allocation_pct,
|
|
78
|
+
currentPct: pos?.pct ?? 0,
|
|
79
|
+
};
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
query,
|
|
84
|
+
risk_tolerance: riskTolerance,
|
|
85
|
+
amount_usdc: amount,
|
|
86
|
+
strategies: strategy.strategies,
|
|
87
|
+
total_estimated_apy: strategy.total_estimated_apy,
|
|
88
|
+
summary: strategy.summary,
|
|
89
|
+
data_sources: {
|
|
90
|
+
blend_pools: blendData.reserves.length,
|
|
91
|
+
soroswap_pools: soroswapPools.length,
|
|
92
|
+
rwa_sources: 2,
|
|
93
|
+
},
|
|
94
|
+
disclaimer: "APY estimates based on current rates. Not financial advice. DYOR.",
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async generateWithClaude(query, poolContext, risk, amount) {
|
|
98
|
+
const userPrompt = buildUserPrompt(query, poolContext, risk, amount);
|
|
99
|
+
const response = await this.anthropic.messages.create({
|
|
100
|
+
model: "claude-sonnet-4-5-20250929",
|
|
101
|
+
max_tokens: 1500,
|
|
102
|
+
system: SYSTEM_PROMPT,
|
|
103
|
+
messages: [{ role: "user", content: userPrompt }],
|
|
104
|
+
});
|
|
105
|
+
const text = response.content[0].type === "text" ? response.content[0].text : "";
|
|
106
|
+
try {
|
|
107
|
+
const start = text.indexOf("{");
|
|
108
|
+
const end = text.lastIndexOf("}") + 1;
|
|
109
|
+
return JSON.parse(text.slice(start, end));
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
this.log.error("Failed to parse Claude response", { text });
|
|
113
|
+
return this.fallbackStrategy(risk, amount);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
formatPoolContext(blend, soroswap) {
|
|
117
|
+
const lines = [];
|
|
118
|
+
lines.push("=== BLEND PROTOCOL (Lending) ===");
|
|
119
|
+
for (const r of blend.reserves) {
|
|
120
|
+
lines.push(` ${r.symbol}: Supply APY ${r.supplyApy.toFixed(1)}% | Borrow APY ${r.borrowApy.toFixed(1)}% | Utilization ${(r.utilization * 100).toFixed(0)}%`);
|
|
121
|
+
}
|
|
122
|
+
lines.push("\n=== SOROSWAP (AMM DEX) ===");
|
|
123
|
+
for (const p of soroswap) {
|
|
124
|
+
lines.push(` ${p.token0}/${p.token1}: LP APY ~${p.apy}%`);
|
|
125
|
+
}
|
|
126
|
+
lines.push("\n=== RWA YIELDS ===");
|
|
127
|
+
lines.push(" Ondo USDY: 4.8% (US Treasury-backed, lowest risk)");
|
|
128
|
+
lines.push(" Centrifuge deJTRSY: 4.5% (Institutional treasuries)");
|
|
129
|
+
lines.push("\n=== DEFINDEX VAULTS ===");
|
|
130
|
+
lines.push(" Auto-Compound Blend Vault: ~9.1% (compounds Blend + BLND rewards)");
|
|
131
|
+
lines.push(" Multi-Strategy Vault: ~11.3% (Blend + Soroswap + Aquarius)");
|
|
132
|
+
return lines.join("\n");
|
|
133
|
+
}
|
|
134
|
+
fallbackStrategy(risk, _amount) {
|
|
135
|
+
const strategies = {
|
|
136
|
+
low: {
|
|
137
|
+
strategies: [
|
|
138
|
+
{ protocol: "Ondo USDY", action: "Hold USDY", allocation_pct: 40, estimated_apy: 4.8, risk_level: "low", details: "US Treasury-backed" },
|
|
139
|
+
{ protocol: "Blend Fixed V2", action: "Supply USDC", allocation_pct: 40, estimated_apy: 7.2, risk_level: "low", details: "Immutable pool, backstop protected" },
|
|
140
|
+
{ protocol: "Soroswap USDC/EURC", action: "Provide LP", allocation_pct: 20, estimated_apy: 3.8, risk_level: "low", details: "Stablecoin pair, minimal IL" },
|
|
141
|
+
],
|
|
142
|
+
total_estimated_apy: 5.6,
|
|
143
|
+
summary: "Conservative strategy: Treasury yields + lending + stable LP.",
|
|
144
|
+
},
|
|
145
|
+
moderate: {
|
|
146
|
+
strategies: [
|
|
147
|
+
{ protocol: "DeFindex Auto-Compound", action: "Deposit vault", allocation_pct: 35, estimated_apy: 9.1, risk_level: "moderate", details: "Auto-compounds Blend yields" },
|
|
148
|
+
{ protocol: "Blend Fixed V2", action: "Supply USDC", allocation_pct: 30, estimated_apy: 7.2, risk_level: "low", details: "Stable base yield" },
|
|
149
|
+
{ protocol: "Ondo USDY", action: "Hold USDY", allocation_pct: 20, estimated_apy: 4.8, risk_level: "low", details: "Safety allocation" },
|
|
150
|
+
{ protocol: "Soroswap USDC/XLM", action: "Provide LP", allocation_pct: 15, estimated_apy: 12.5, risk_level: "high", details: "Yield kicker, IL monitored" },
|
|
151
|
+
],
|
|
152
|
+
total_estimated_apy: 8.1,
|
|
153
|
+
summary: "Balanced: lending core + vault optimization + small LP kicker.",
|
|
154
|
+
},
|
|
155
|
+
high: {
|
|
156
|
+
strategies: [
|
|
157
|
+
{ protocol: "DeFindex Multi-Strategy", action: "Deposit vault", allocation_pct: 35, estimated_apy: 11.3, risk_level: "high", details: "Blend + Soroswap + Aquarius" },
|
|
158
|
+
{ protocol: "Soroswap USDC/XLM", action: "Provide LP", allocation_pct: 30, estimated_apy: 12.5, risk_level: "high", details: "Strong fee revenue" },
|
|
159
|
+
{ protocol: "Blend YieldBlox V2", action: "Supply USDC", allocation_pct: 25, estimated_apy: 8.5, risk_level: "moderate", details: "BLND rewards boost" },
|
|
160
|
+
{ protocol: "Ondo USDY", action: "Hold USDY", allocation_pct: 10, estimated_apy: 4.8, risk_level: "low", details: "Safety base" },
|
|
161
|
+
],
|
|
162
|
+
total_estimated_apy: 10.4,
|
|
163
|
+
summary: "Aggressive: maximizing yield through LP + multi-strategy vaults.",
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
return strategies[risk] || strategies.moderate;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=yield-optimizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yield-optimizer.js","sourceRoot":"","sources":["../src/yield-optimizer.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agenticocean/defi-agent",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "AI-powered DeFi agent toolkit for Stellar — yield optimization, Blend, Soroswap",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"lint": "tsc --noEmit",
|
|
20
|
+
"clean": "rm -rf dist"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@anthropic-ai/sdk": "^0.40.0",
|
|
24
|
+
"@stellar/stellar-sdk": "^13.1.0"
|
|
25
|
+
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"@blend-capital/blend-sdk": ">=3.0.0"
|
|
28
|
+
},
|
|
29
|
+
"peerDependenciesMeta": {
|
|
30
|
+
"@blend-capital/blend-sdk": {
|
|
31
|
+
"optional": true
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@blend-capital/blend-sdk": "^3.2.2",
|
|
36
|
+
"dotenv": "^16.6.1",
|
|
37
|
+
"typescript": "^5.7.0"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT"
|
|
43
|
+
}
|