Token ATH API code examples
Submit an all-time-high job and poll for the result, in curl, JavaScript (fetch) and Python (requests). Shows pool mode (the reliable path), token mode with a fallback, and branching on the
pending/estimated/exactstates.
All examples read the key from TRIPORT_API_KEY and call https://triport.io/rpc/{chain}. See the Token ATH API overview for how the computation works and the method reference for every field.
Submit a job (curl)
Pool mode — pass the specific pool you want measured:
curl -X POST "https://triport.io/rpc/eth" \
-H "x-token: $TRIPORT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"triport_getTokenATH",
"params":[{"chain":"eth","pool":{"address":"0xYOUR_POOL_ADDRESS"},"budget":400}]}'
# -> {"jsonrpc":"2.0","id":1,"result":{"job_id":"ath_01J…","status":"pending","poll_after_s":5}}Token mode is the same call with "token":"0x…" instead of pool. It may answer pool_selection_incomplete; if it does, retry in pool mode.
Poll for the result (curl)
Wait poll_after_s seconds, then poll with the job_id:
curl -X POST "https://triport.io/rpc/eth" \
-H "x-token: $TRIPORT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"triport_getTokenATHResult",
"params":["ath_01J…"]}'
# status "pending" -> poll again later; "estimated" or "exact" -> the result is in `result`Submit then poll (JavaScript)
The loop respects poll_after_s, stops at a terminal status, gives up after a deadline, and falls back from token mode to pool mode on pool_selection_incomplete.
const URL = "https://triport.io/rpc/eth";
async function rpc(method, params) {
const res = await fetch(URL, {
method: "POST",
headers: { "x-token": process.env.TRIPORT_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params }),
});
const body = await res.json();
if (body.error) throw Object.assign(new Error(body.error.message || "rpc_error"), { code: body.error.code });
return body.result;
}
async function tokenAth(target, { budget = 400, deadlineMs = 16 * 60 * 1000 } = {}) {
// target: { token } or { pool: { address } }
const submit = await rpc("triport_getTokenATH", [{ chain: "eth", budget, ...target }]);
let wait = (submit.poll_after_s ?? 5) * 1000;
const until = Date.now() + deadlineMs;
while (Date.now() < until) {
await new Promise((r) => setTimeout(r, wait));
const r = await rpc("triport_getTokenATHResult", [submit.job_id]);
if (r.status === "estimated" || r.status === "exact") return r;
wait = Math.min(wait * 1.5, 30_000); // seconds, not a tight loop
}
throw new Error("ath_timeout");
}
async function athForToken(token) {
try {
return await tokenAth({ token });
} catch (e) {
if (e.code === "pool_selection_incomplete") {
// look up the token's primary pool yourself, then:
// return await tokenAth({ pool: { address: poolAddress } });
}
throw e;
}
}
const ath = await tokenAth({ pool: { address: "0xYOUR_POOL_ADDRESS" } });
console.log(ath.status, ath.ath_trade.block, ath.ath_trade.tx);Submit then poll (Python)
import os, time, requests
URL = "https://triport.io/rpc/eth"
HEADERS = {"x-token": os.environ["TRIPORT_API_KEY"], "Content-Type": "application/json"}
def rpc(method, params):
r = requests.post(URL, headers=HEADERS,
json={"jsonrpc": "2.0", "id": 1, "method": method, "params": params},
timeout=60)
body = r.json()
if "error" in body and body["error"]:
raise RuntimeError(body["error"].get("code") or body["error"].get("message"))
return body["result"]
def token_ath(target, budget=400, deadline_s=16 * 60):
submit = rpc("triport_getTokenATH", [{"chain": "eth", "budget": budget, **target}])
wait = submit.get("poll_after_s", 5)
end = time.time() + deadline_s
while time.time() < end:
time.sleep(wait)
res = rpc("triport_getTokenATHResult", [submit["job_id"]])
if res["status"] in ("estimated", "exact"):
return res
wait = min(wait * 1.5, 30)
raise TimeoutError("ath_timeout")
ath = token_ath({"pool": {"address": "0xYOUR_POOL_ADDRESS"}})
num = int(ath["ath_trade"]["price"]["numerator"])
den = int(ath["ath_trade"]["price"]["denominator"])
print(ath["status"], num / den, ath["ath_trade"]["block"])Reading the result
- Branch on
status:pendingmeans keep polling;estimatedandexactare terminal.estimatedis a sampled heuristic — checkwarnings. - The price is a rational,
ath_trade.price.numerator/.denominator, as strings. Divide with arbitrary precision; do not round before you need to. - The peak is in the resolved
pool.quoteasset and withinscope— per pool, not token-global (not_token_global_ATH). - On
pool_selection_incomplete, resubmit in pool mode with an explicitpool.address. - On
ath_busyorath_chain_unavailable, back off and retry later; neither means the token has no ATH.