use crate::error::{Error, Result};
const FALLBACK_WALLETS: &[&str] = &[
"0x1a1A27de044faFFCCf68E28F03dCfCf5eB3d3cE6",
"0xBB39C16C3fc54d3C9B1f9f9E8dF4a09Ee25AB7df",
"0x7a25dA10f8cA3b67D5fF55e87E2B0C076D3Dd0bD",
"0xe6Fa0E88Fc2cA3dEFecf0Ed3bE2e66e8E29f5d5E",
"0x3cF9Db5B9e6bCb9cd1c38bA97B7DC1Daa7eb51F9",
];
pub async fn get_active_test_wallet(fresh: bool) -> String {
if fresh {
if let Ok(wallets) = scrape_leaderboard(1).await {
if let Some(w) = wallets.first() {
return w.clone();
}
}
}
FALLBACK_WALLETS[0].to_string()
}
pub async fn get_active_test_wallets(count: usize, fresh: bool) -> Vec<String> {
if fresh {
if let Ok(wallets) = scrape_leaderboard(count).await {
if wallets.len() >= count {
return wallets;
}
}
}
FALLBACK_WALLETS.iter()
.take(count)
.map(|s| s.to_string())
.collect()
}
async fn scrape_leaderboard(count: usize) -> Result<Vec<String>> {
let url = "https://polymarket.com/leaderboard";
let client = reqwest::Client::builder()
.user_agent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36")
.build()?;
let resp = client.get(url).send().await?;
let body = resp.text().await?;
let mut wallets = Vec::new();
if let Some(start) = body.find("__NEXT_DATA__") {
if let Some(json_start) = body[start..].find('{') {
let json_str = &body[start + json_start..];
if let Some(end) = find_closing_brace(json_str) {
if let Ok(data) = serde_json::from_str::<serde_json::Value>(&json_str[..=end]) {
extract_wallets(&data, &mut wallets, count * 2);
}
}
}
}
if wallets.len() < count {
let mut i = 0;
while i < body.len().saturating_sub(42) && wallets.len() < count * 2 {
if &body[i..i+2] == "0x" {
let candidate = &body[i..i+42];
if candidate.chars().skip(2).all(|c| c.is_ascii_hexdigit()) {
let addr = candidate.to_string();
if !wallets.contains(&addr) {
wallets.push(addr);
}
}
}
i += 1;
}
}
wallets.truncate(count);
if wallets.is_empty() {
return Err(Error::Api { status: 0, message: "No wallets found in leaderboard".into() });
}
Ok(wallets)
}
fn extract_wallets(value: &serde_json::Value, wallets: &mut Vec<String>, max: usize) {
if wallets.len() >= max { return; }
match value {
serde_json::Value::String(s) => {
if s.starts_with("0x") && s.len() == 42 && s[2..].chars().all(|c| c.is_ascii_hexdigit()) {
if !wallets.contains(s) {
wallets.push(s.clone());
}
}
}
serde_json::Value::Array(arr) => {
for v in arr { extract_wallets(v, wallets, max); }
}
serde_json::Value::Object(map) => {
for v in map.values() { extract_wallets(v, wallets, max); }
}
_ => {}
}
}
fn find_closing_brace(s: &str) -> Option<usize> {
let mut depth = 0;
for (i, c) in s.char_indices() {
match c {
'{' => depth += 1,
'}' => {
depth -= 1;
if depth == 0 { return Some(i); }
}
_ => {}
}
}
None
}