주소에 대한 단일 위험 판정은 어떻게 얻고, 언제 unknown이 됩니까?

주소 · 하나의 등급, 그 뒤의 플래그, 증거 행, 그리고 평가할 수 없었던 항목 목록

  • API 가이드
  • 9분
  • 중급
  • 개발자
  • GET /v1/addresses/{address}/risk

ACHIVX Academy 원문 (영어) ↗

GET /v1/addresses/{address}/risk?chain=은 tier 하나 — severe, high, medium, low, none, unknown — 를 flags(sanctioned, frozen, exposed, labeled, service), 신호마다 하나씩인 evidence[] 행, incomplete_reasons[]와 함께 답합니다. 등급은 사실이 정합니다(OFAC 목록 등재는 severe, 발행사 동결은 high, 오염된 출발점까지의 도달은 high 또는 medium). 라벨만으로는 medium이 상한입니다. unknown은 평가를 완료할 수 없었다는 뜻이며 그 이유를 밝힙니다. 활발한 주소에서는 노출 탐색이 자주 시간을 다 쓰며, 그 경우 none이 아니라 time_budget과 함께 unknown으로 읽힙니다. 두 주소가 전에 거래한 적이 있는지 알고 싶으면 from=을 추가하십시오.

요청

curl -s 'https://stablescan.achivx.com/v1/addresses/0x098B716B8Aaf21512996dC57EB0615e2383E2f96/risk?chain=1'

2026-10-24의 제재 대상 예시입니다.

{
  "address": "0x098b716b8aaf21512996dc57eb0615e2383e2f96",
  "chain_id": 1,
  "tier": "severe",
  "flags": {"sanctioned": true, "frozen": true, "exposed": true},
  "evidence": [
    {"signal": "sanctioned", "class": "F", "detail": "on the OFAC SDN list",                "tier": "severe"},
    {"signal": "frozen",     "class": "F", "detail": "frozen/seized by the PYUSD issuer",   "tier": "high"},
    {"signal": "frozen",     "class": "F", "detail": "frozen/seized by the USDC issuer",    "tier": "high"},
    {"signal": "frozen",     "class": "F", "detail": "frozen/seized by the USDT issuer",    "tier": "high"},
    {"signal": "exposure",   "class": "F", "detail": "sanctioned root reached at 0 hops",  "tier": "severe"}
  ],
  "incomplete_reasons": [],
  "data_vintage": "2026-09-10T00:00:11Z",
  "sanctions_list_as_of": "2026-10-24T04:00:04Z",
  "note": "Aggregate of decoded facts (issuer freeze/seize, OFAC listing, exposure to a sanctioned/hack root) and attributed labels (with provenance, capped at medium alone). tier 'unknown' = the assessment could not be completed …",
  "computed_at": "2026-10-24T10:46:19Z",
  "snapshot_served": false,
  "chain_source": "explicit",
  "chains_with_data": [{"chain_id": 1, "kinds": ["issuer_acts"]}, "…"],
  "freshness_seconds": 200,
  "requested_address": "0x098B716B8Aaf21512996dC57EB0615e2383E2f96",
  "address_respelled": false
}

그리고 1분 전의 바이낸스(Binance) 핫월렛입니다. 스스로 불완전하다고 말하는 완전한 응답입니다.

{
  "tier": "unknown",
  "flags": {"service": true},
  "evidence": [
    {"signal": "coverage", "class": "F", "tier": "unknown",
     "detail": "exposure not assessed: the walk stopped on its time budget with 0 of 3 hops completed (time_budget; a quieter moment may complete it) — see get-address-exposure"},
    {"signal": "service",  "class": "F", "detail": "labeled service node (exchange_hot) — not an end-user counterparty"}
  ],
  "incomplete_reasons": ["time_budget"],
  "computed_at": "2026-10-24T10:46:17Z"
}

이 응답은 5.1초가 걸렸고 평소의 60 대신 Cache-Control: max-age=10과 함께 왔습니다. 노출 탐색이 잘렸고, 덜 붐비는 시점에 완료될 수 있도록 판정은 10초 동안만 유지됩니다.

첫 요청의 세 가지 헬퍼로 같은 호출을 하면 다음과 같습니다.

Python

import time
risk = scan(f"/v1/addresses/{addr}/risk", chain=1, **({"from": payer} if payer else {}))   # payer: your own address, or None
print(risk["tier"], risk["flags"], risk["incomplete_reasons"])
if risk["tier"] == "unknown" and "time_budget" in risk["incomplete_reasons"]:
    time.sleep(15)                      # not a hot loop: the cut verdict is reused for ~10 s
    risk = scan(f"/v1/addresses/{addr}/risk", chain=1)

Go

type risk struct {
	Tier              string          `json:"tier"`
	Flags             map[string]bool `json:"flags"`
	IncompleteReasons []string        `json:"incomplete_reasons"`
	NewCounterparty   string          `json:"new_counterparty"` // only with from=
	ComputedAt        time.Time       `json:"computed_at"`
}
var r risk
q := url.Values{"chain": {"1"}}
if payer != "" {
	q.Set("from", payer)
}
if err := get("/v1/addresses/"+addr+"/risk", q, &r); err != nil {
	return err
}
fmt.Println(r.Tier, r.Flags, r.IncompleteReasons)

TypeScript

type Risk = {
  tier: "severe" | "high" | "medium" | "low" | "none" | "unknown";
  flags: Partial<Record<"sanctioned" | "frozen" | "exposed" | "labeled" | "service", boolean>>;
  incomplete_reasons: string[];
  new_counterparty?: "new" | "known" | "unknown";
  computed_at: string;
};
const risk = await scan<Risk>(`/v1/addresses/${addr}/risk`, { chain: 1, from: payer });
console.log(risk.tier, risk.flags, risk.incomplete_reasons);

필드별 설명

tier — 한 단어로 된 결론입니다. 사실 기준으로 보면, OFAC 목록 등재는 severe, 이 체인에서의 발행사 동결이나 소각은 high, 거래 상대를 거쳐 제재 대상 출발점에 도달하면 0홉에서는 severe, 그보다 멀면 high 또는 medium(direct → high, indirect → medium)입니다. 라벨은 단독으로는 medium이 상한입니다. none은 모든 입력을 충분한 집계 범위에서 읽었을 때만 주장됩니다. 나머지는 unknown이며, 이것은 절대 none이 아닙니다.

flags — 프로그램용 불리언 값입니다. sanctioned, frozen, exposed, labeled, service가 있으며, true인 것만 들어 있습니다. service: true는 라벨이 붙은 서비스 노드(거래소 핫월렛, 발행사 트레저리)를 표시합니다. 최종 사용자 거래 상대가 아니며, 맥락일 뿐 등급에 기여하지 않습니다.

evidence[] — 신호마다 행이 하나 있습니다. signal(sanctioned, frozen, exposure, label, service, coverage), class(디코딩된 사실은 F, 휴리스틱은 H, 귀속은 A), 사람을 위한 detail, 그리고 그 신호 하나만으로 설정될 tier입니다. tier: "unknown"인 coverage 행은 평가할 수 없었던 것을 말로 설명합니다. 같은 내용을 필드로 담은 것이 incomplete_reasons입니다. 분기는 필드로 하십시오.

incomplete_reasons[] — 판정이 무엇 없이 만들어졌는지를 빠짐없이, 고정된 순서로 나열합니다. 빠진 것이 없으면 []입니다. 모든 값은 응답 읽기에 나열되어 있습니다. 응답을 no-store로 만드는 두 가지는 labels_unread와 new_counterparty_unread입니다. 이들은 끝나지 않은 조회이며, 다시 요청하면 완전한 판정을 얻습니다.

computed_at, snapshot_served, snapshot_age_seconds — 판정이 계산된 시각과, 그 노출 탐색이 저장된 것이었는지 여부입니다(솔라나(Solana)를 제외한 모든 네트워크는 탐색을 15분 동안 보관합니다. 실행할 수 없었던 실시간 탐색을 대신하는 저장 탐색은 degraded_reason으로 표시되며 절대 캐시되지 않습니다). 캐시 기간 안에 반복 요청하면 computed_at까지 포함해 같은 판정이 돌아옵니다. 2026-10-24 제재 대상 예시는 두 번째 조회에서 Age: 2를 답했습니다. 더 자주 폴링해도 더 새로운 판정을 얻지는 못합니다.

sanctions_list_as_of — 판정 뒤에 있는 OFAC 목록이 갱신된 시각입니다. 7일보다 오래되면 ofac_list_stale이 나열되고, 양성 신호가 없는 판정은 unknown으로 읽힙니다.

new_counterparty — from=<송금하려는 주소>가 있을 때만 나타납니다. new(두 주소가 인덱싱된 이력에서 거래한 적 없음), known, 또는 unknown(조회가 끝나지 않음, no-store)입니다. 2026-10-24 바이낸스 지갑이 제재 대상 예시에 지급하는 경우는 "new_counterparty": "unknown"을 답했습니다. 완료되지 않은 조회이지, 발견 사항이 아닙니다.

등급이 읽지 않는 것

이 체인의 freeze[] 상태만 읽으며, own_token_contract가 있는 행은 읽지 않습니다. 같은 주소가 다른 체인에서 동결된 것(frozen_elsewhere), 대기 중인 제안, 동결된 잔액의 크기는 등급에 들어가지 않습니다. 이들은 개요에서 읽으십시오. 솔라나에서는 동결 쌍이 항상 unknown이므로 솔라나 등급은 절대 none이 아닙니다. 그곳의 unknown은 동결 측면을 평가할 수 없다는 뜻이지, 주소가 의심스럽다는 뜻이 아닙니다.

이런 것이 보이면 …

  • time_budget과 함께 tier: "unknown" — 탐색이 잘렸습니다. 판정은 약 10초 동안 재사용됩니다. 잠시 물러났다가 한 번 더 요청하십시오. 붐비는 이웃은 다시 잘릴 수 있으니 반복 루프를 돌리지 마십시오. 탐색 자체(truncation_reason, hops_completed)는 /exposure에 있습니다.
  • frontier_cap과 함께 tier: "unknown" — 주소의 속성입니다(거래 상대 500개보다 넓은 홉). 매 호출마다 반복됩니다. 정책에 따라 결정하십시오.
  • short_history와 함께 tier: "unknown" — 관측된 유입액이 1달러 미만입니다. 평가할 것이 없고, 불리한 것도 없습니다.
  • error.code: "busy"와 함께 503 — 무거운 조회들은 정해진 수의 슬롯을 공유합니다. Retry-After(5초) 후에 백오프를 적용해 재시도하십시오.
  • 200에 Cache-Control: no-store — 일부가 유실되었습니다(labels_unread, new_counterparty_unread, null 최신성). 다시 요청하십시오.

Stablecoin scanner ACHIVX에서

출처

더 알아보기

주소 · GET /v1/addresses/{address}/risk · 2026-10-24 작성, openapi.json, agents.md 및 당일 실제 호출 기준. 응답 형태는 인용이며, 수치는 날짜 기준이고 인덱스에 따라 달라집니다.

이 페이지는 ACHIVX Academy 영어 원문을 한국어로 옮긴 것입니다. 번역과 원문이 다르면 영어 원문이 기준입니다.