Skip to content

Commit 38c2d77

Browse files
committed
feat(discovery): add protocol API fallback for BSC pool auto-discovery
1 parent 1ae96ff commit 38c2d77

File tree

2 files changed

+88
-6
lines changed

2 files changed

+88
-6
lines changed

apps/dashboard/server.mjs

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,20 @@ const BSC_LISTA_POOL_CANDIDATES = String(
947947
const BSC_WOMBAT_POOL_CANDIDATES = String(
948948
envOrCfg("BSC_WOMBAT_POOL_CANDIDATES", "bsc.wombat.poolCandidates", ""),
949949
).trim();
950+
const BSC_LISTA_POOL_DISCOVERY_API_URLS = String(
951+
envOrCfg(
952+
"BSC_LISTA_POOL_DISCOVERY_API_URLS",
953+
"bsc.lista.poolDiscoveryApiUrls",
954+
"",
955+
),
956+
).trim();
957+
const BSC_WOMBAT_POOL_DISCOVERY_API_URLS = String(
958+
envOrCfg(
959+
"BSC_WOMBAT_POOL_DISCOVERY_API_URLS",
960+
"bsc.wombat.poolDiscoveryApiUrls",
961+
"",
962+
),
963+
).trim();
950964
const BSC_WOMBAT_EXECUTE_PRIVATE_KEY = String(
951965
envOrCfg(
952966
"BSC_WOMBAT_EXECUTE_PRIVATE_KEY",
@@ -9310,6 +9324,63 @@ function parseAddressCandidates(raw) {
93109324
.filter((x) => /^0x[a-fA-F0-9]{40}$/.test(x));
93119325
}
93129326

9327+
function parseUrlCandidates(raw) {
9328+
return String(raw || "")
9329+
.split(/[\n,;]+/)
9330+
.map((x) => x.trim())
9331+
.filter((x) => /^https?:\/\//i.test(x));
9332+
}
9333+
9334+
function extractEvmAddressesFromJson(payload) {
9335+
const text = JSON.stringify(payload || {});
9336+
const found = text.match(/0x[a-fA-F0-9]{40}/g) || [];
9337+
return [...new Set(found.map((x) => x.toLowerCase()))];
9338+
}
9339+
9340+
async function fetchJsonWithTimeout(url, timeoutMs = 8000) {
9341+
const controller = new AbortController();
9342+
const timer = setTimeout(() => controller.abort(), timeoutMs);
9343+
try {
9344+
const res = await fetch(url, {
9345+
headers: { accept: "application/json" },
9346+
signal: controller.signal,
9347+
});
9348+
if (!res.ok) return null;
9349+
return await res.json();
9350+
} catch {
9351+
return null;
9352+
} finally {
9353+
clearTimeout(timer);
9354+
}
9355+
}
9356+
9357+
async function discoverPoolCandidatesFromProtocolApis(protocol) {
9358+
const key = String(protocol || "").toLowerCase();
9359+
const urlRaw =
9360+
key === "lista"
9361+
? BSC_LISTA_POOL_DISCOVERY_API_URLS
9362+
: BSC_WOMBAT_POOL_DISCOVERY_API_URLS;
9363+
const urls = parseUrlCandidates(urlRaw);
9364+
if (urls.length === 0) return [];
9365+
const excluded = new Set([
9366+
BSC_USDC.toLowerCase(),
9367+
BSC_USDT.toLowerCase(),
9368+
BSC_WBNB.toLowerCase(),
9369+
BSC_ROUTER_V2.toLowerCase(),
9370+
"0x0000000000000000000000000000000000000000",
9371+
]);
9372+
const out = [];
9373+
for (const url of urls) {
9374+
const payload = await fetchJsonWithTimeout(url);
9375+
if (!payload) continue;
9376+
const addrs = extractEvmAddressesFromJson(payload)
9377+
.filter((x) => !excluded.has(x))
9378+
.slice(0, 120);
9379+
for (const addr of addrs) out.push(addr);
9380+
}
9381+
return [...new Set(out)];
9382+
}
9383+
93139384
async function discoverPoolCandidatesFromDefiLlama(protocol) {
93149385
const key = String(protocol || "").toLowerCase();
93159386
const projectName = key === "lista" ? "lista" : "wombat-exchange";
@@ -9376,13 +9447,17 @@ async function discoverBscPoolsByProtocol(protocol) {
93769447
let candidates = parseAddressCandidates(candidateRaw);
93779448
let source = "env";
93789449
let warning = null;
9450+
if (candidates.length === 0) {
9451+
candidates = await discoverPoolCandidatesFromProtocolApis(key);
9452+
source = "protocol-api";
9453+
}
93799454
if (candidates.length === 0) {
93809455
candidates = await discoverPoolCandidatesFromDefiLlama(key);
93819456
source = "defillama";
9382-
if (candidates.length === 0) {
9383-
warning =
9384-
"auto-discovery found no BSC pool addresses from DeFiLlama; you can still set BSC_*_POOL_CANDIDATES manually";
9385-
}
9457+
}
9458+
if (candidates.length === 0) {
9459+
warning =
9460+
"auto-discovery found no BSC pool addresses from configured protocol API URLs or DeFiLlama; set BSC_*_POOL_DISCOVERY_API_URLS or BSC_*_POOL_CANDIDATES";
93869461
}
93879462
const rows = await scorePoolCandidates(candidates);
93889463
return {

docs/openclaw-strategy-tools-quickstart.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,19 @@ npm run stable-yield:auto-migrate:v2:cron-install
144144
# last json: logs/stable-yield-auto-migrate-v2-last.json
145145
```
146146

147-
BSC 配置向导支持自动发现候选池(需提前配置候选地址列表):
147+
BSC 配置向导支持自动发现候选池,优先级如下:
148+
1) `BSC_*_POOL_CANDIDATES`(手工候选)
149+
2) `BSC_*_POOL_DISCOVERY_API_URLS`(协议 API 自动抓取)
150+
3) DeFiLlama fallback
148151

149152
```bash
150-
# 逗号分隔多个候选池
153+
# 1) 逗号分隔多个候选池
151154
BSC_LISTA_POOL_CANDIDATES=0x...,0x...
152155
BSC_WOMBAT_POOL_CANDIDATES=0x...,0x...
156+
157+
# 2) 可选:协议查询 API(逗号/分号分隔多个 URL)
158+
BSC_LISTA_POOL_DISCOVERY_API_URLS=https://.../lista/pools,https://.../bsc/lista
159+
BSC_WOMBAT_POOL_DISCOVERY_API_URLS=https://.../wombat/pools;https://.../bsc/wombat
153160
```
154161

155162

0 commit comments

Comments
 (0)