trust layer.
One call returns a wallet's 0–1000 trust score, its tier, the provenance behind it, and the fee discounts it unlocks on GIWA. Cached, keyed, and ready for your launchpad, airdrop, or payment flow.
$
01Overview
The DojangScore API is a thin, authenticated read-layer over the DojangScoreV2 contract on GIWA. It converts on-chain attestations (Upbit KYC via Dojang, verified balance, account age, verified code) plus on-chain behaviour into a single 0–1000 trust score with a tier and a provenance ceiling.
Use it to gate, weight, or price anything off-chain: launchpad allocations, airdrop multipliers, trading fees, remittance limits, quest rewards. For settlement-critical logic, read the contract on-chain instead (see On-chain vs API).
02Quickstart
Three steps to a live score.
1 · Get a key (instant)
Issue a free trial key instantly — no email, no wait:
curl -X POST https://giwa-defi-suite.vercel.app/api/keys/trial \
-H "content-type: application/json" \
-d '{"project":"my-launchpad"}'
Returns a key — 1,000 free testnet calls · 60 req/min · upgrade nudge at 900. Keep the key server-side. Subscribe for more at proven.defi@gmail.com.
2 · Make your first request
curl -H "x-proven-key: YOUR_KEY" \ https://giwa-defi-suite.vercel.app/api/score/0xE5EFB15259292F5B60A1DB074B708712998dB147
const res = await fetch(
"https://giwa-defi-suite.vercel.app/api/score/0xE5EF…B147",
{ headers: { "x-proven-key": process.env.PROVEN_KEY } }
);
const score = await res.json();
console.log(score.tierName, score.score);
import requests
r = requests.get(
"https://giwa-defi-suite.vercel.app/api/score/0xE5EF…B147",
headers={"x-proven-key": PROVEN_KEY})
print(r.json()["tierName"], r.json()["score"])
3 · Read the response
score is the clamped 0–1000 value, tierName the band, ceilingProvenance the strongest proof class, and fees the on-chain discounts the tier unlocks. Full schema under GET /score.
The Trust Layer
Identity, not just activity.
Volume is cheap — bots can fake a million swaps. Proven scores who you are, not just what you do: we read Dojang attestations (Upbit KYC, verified balance, account age, verified code) via EAS and compress them into one 0–1000 trust score. Activity can raise your score; it can never substitute for proof.
—Activity-only scorers (e.g. Hanok) reward wash-trading. Proven rewards being a provable human.The Provenance Ceiling.
Our unique cryptographic guarantee: a score can never exceed the strength of its strongest underlying proof. Behavioral points grind you to Silver; consented proofs open Gold; only a regulated attester root unlocks Platinum. A farm with infinite volume still caps at Silver — the ceiling is enforced on-chain, not by policy.
—No other scoring system on GIWA — including Hanok — has a ceiling. Ours is math.Regulatory ready.
Because Proven integrates with Dojang and Upbit KYC, the Platinum tier is compliant-ready for B2B and institutional flows. Remittance limits, tiered fees, gated allocations — every gate inherits a KYC-backed attestation, not a heuristic.
—Institutions don't buy heuristics. They buy attestations.03Authentication
Every request requires the x-proven-key header. Missing or invalid keys return 401.
| Header | Type | Description |
|---|---|---|
x-proven-key | string | Your issued API key. Keep it server-side; never ship it in client bundles. |
Responses include rate-limit headers (X-RateLimit-Limit, -Remaining, -Reset) so you can throttle client-side. See Rate limits.
04Core concepts
The score is a sum of capped provenance contributions, clamped by a ceiling. Understanding both is the whole model.
| Term | Range | Meaning |
|---|---|---|
score | 0–1000 | Final clamped trust score. The value to gate on. |
tier / tierName | 0–3 | Band derived from score (see tiers). |
rawSum | int | Sum of capped contributions before the ceiling clamp. |
ceiling | int | Hard cap set by the strongest provenance class present. |
ceilingProvenance | enum | The class that set the ceiling. |
Tiers & on-chain fees
| Tier | Score | GIWASwap fee | WonVault entry | Typical gate |
|---|---|---|---|---|
| Standard | 0–199 | 0.30% | 2.00% | unverified / bot-risk |
| Silver | 200–499 | 0.20% | 1.50% | behavioural proof |
| Gold | 500–799 | 0.15% | 1.00% | consented identity |
| Platinum | 800–1000 | 0.10% | 0.50% | regulated attester |
The same tier that the API reports is what the on-chain contracts charge — so an off-chain gate and the on-chain fee always agree.
Provenance & the ceiling
| Class | Source | Ceiling | How a wallet gets it |
|---|---|---|---|
ATTESTER | Regulated attester (Upbit / Dojang) | 1000 | KYC attestation on-chain |
CONSENTED | Self-submitted consented proofs | 799 | Wallet submits proofs (ENS, Passport, renewals) |
BEHAVIORAL | Reporter-attested on-chain activity | 499 | Swaps, LP, vault holds, votes |
STATE | Trustless on-chain state | 499 | Currently holds LP / vault shares |
NONE | — | 0 | No signal |
Returns the full trust breakdown for a wallet.
Path parameters
| Param | Type | Description | |
|---|---|---|---|
address | string | required | 0x-prefixed, 40-hex EVM address. Returns 400 if malformed. |
Response · 200
| Field | Type | Description |
|---|---|---|
address | string | Checksummed address. |
score | int | Final clamped score 0–1000. |
tier | int | 0–3. |
tierName | string | Standard / Silver / Gold / Platinum. |
ceiling | int | Provenance ceiling. |
ceilingProvenance | string | NONE / BEHAVIORAL / CONSENTED / ATTESTER. |
provenance.baseAttestation | int | Capped attester-rooted contribution (0–1000). |
provenance.trustlessState | int | Capped trustless state contribution (0–100). |
provenance.reporterActivity | int | Capped behavioural contribution (0–250). |
provenance.consentedProofs | int | Capped consented contribution (0–250). |
rawSum | int | Sum before clamp. |
holdsLP / holdsVault | bool | Current on-chain LP / vault position. |
cached | bool | True if served from the 45s cache. |
cachedAt | ISO-8601 | When the cached value was read. |
curl -H "x-proven-key: $PROVEN_KEY" \ .../api/score/0xADDRESS
const { score, tierName, ceilingProvenance, provenance } =
await (await fetch(URL, { headers: H })).json();
if (ceilingProvenance === "ATTESTER") // regulated — full trust
else if (score >= 200) // behavioural floor
d = requests.get(URL, headers=H).json() if d["ceilingProvenance"] == "ATTESTER": ...
Lightweight tier + fee lookup when you don't need the full breakdown.
| Field | Type | Description |
|---|---|---|
tier / tierName | int / string | Band. |
scoreRange | [int,int] | Inclusive score band. |
fees.swap | string | On-chain GIWASwap fee for this tier. |
fees.vaultEntry | string | On-chain WonVault entry fee. |
Liveness + chain head. No key required.
| Field | Type | Description |
|---|---|---|
ok | bool | Service up. |
chain / chainId | string / int | GIWA Sepolia / 91342. |
block | int | Latest block seen. |
contract | string | DojangScoreV2 address. |
Score up to N addresses in one call for airdrop / allowlist sweeps.
| Field | Type | Description |
|---|---|---|
addresses | array | Array of 0x-prefixed, 40-hex EVM addresses (max 500). |
Returns { results, count, failed }. Malformed entries or lookup failures come back as { address, error } without failing the overall batch. Each valid address counts as one call toward your quota.
curl -X POST -H "x-proven-key: $PROVEN_KEY" \
-H "Content-Type: application/json" \
-d '{"addresses":["0xADDRESS1","0xADDRESS2"]}' \
.../api/score/batch
const res = await fetch(URL, {
method: "POST",
headers: { "x-proven-key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({ addresses: ["0xADD1", "0xADD2"] })
});
const { results, count, failed } = await res.json();
console.log(`Scored ${count - failed} addresses`);
05Errors
| Code | Meaning | Handle by |
|---|---|---|
400 | Malformed address | Validate 0x + 40 hex client-side first. |
401 | Missing / invalid key | Check header + key validity. |
404 | Unknown route | Fix path. |
429 | Rate limited | Back off using Retry-After. |
500 | Internal error | Retry with backoff; report if persistent. |
503 | Upstream RPC unavailable | Retry; fall back to on-chain read if critical. |
Error bodies are { "error": "message", "code": "…" }.
06Rate limits & caching
| Key tier | Burst | Monthly | Notes |
|---|---|---|---|
| Trial (instant) | 60 req/min | 1,000 calls/mo | Free on testnet. Instant via POST /api/keys/trial. Upgrade nudge at 900 calls. Subscribe via proven.defi@gmail.com. |
| Builder | 300 req/min | 50,000 | Paid. |
| Scale | custom | custom | Talk to us. |
Responses are cached for 45 seconds per address; cached:true tells you a value came from cache. For most gating use-cases 45s staleness is irrelevant; for settlement, read on-chain.
07Performance · measured on live deployment
Measured 2026-08-27 · GIWA Sepolia (chainId 91342) · 10–15 sequential requests each
| Endpoint | p50 | p95 | max |
|---|---|---|---|
/api/health | 484 ms | 761 ms | 761 ms |
/api/score/:addr (cached) | 241 ms | 276 ms | 276 ms |
/api/score/:addr (cold) | 511 ms | 1207 ms | 1207 ms |
Cached reads return in under 300 ms. Cold reads include an RPC round-trip to GIWA Sepolia. Times measured from a single origin; your latency may vary by region.
08Playground · reads the chain live, no key needed
This reads DojangScoreV2 directly over public RPC — the same source the API caches — so you can verify any wallet right now.
08Playbooks
Drop-in gating patterns. Each is a few lines because the hard part (provenance) is already on-chain.
Launchpad · sybil-resistant allocation
// Only wallets with a real proof get an allocation; weight by tier. const s = await score(addr); if (s.ceilingProvenance === "NONE") reject(); // no proof, no alloc const mult = [0, 1, 1.5, 2][s.tier]; // Standard..Platinum alloc = base * mult;
Airdrop · tier multipliers
const MULT = { Standard:1, Silver:1.25, Gold:1.5, Platinum:2 };
payout = base * MULT[s.tierName];Payments / remittance · tiered limits
const DAILY = { Standard:500, Silver:2500, Gold:10000, Platinum:50000 };
limit = DAILY[s.tierName];Quests · gate high-value tasks
if (s.tier >= 1) unlock("high-value quest"); // Silver+09On-chain vs API
| API | On-chain | |
|---|---|---|
| Latency | ~tens of ms, cached | RPC round-trip |
| Cost | quota | your RPC |
| Trust | trust Proven's cache | trustless — the contract is truth |
| Use for | off-chain gating, UI, sweeps | fee charging, settlement, anything monetary |
Contract: 0xDe9De6f3d4a50BF414927EF6D523aFa65355492a (DojangScoreV2). Minimal ABI:
["function score(address) view returns (uint16)", "function tierOfWallet(address) view returns (uint8)", "function scoreBreakdown(address) view returns (tuple(uint16,uint16,uint16,uint16,uint16,uint16,uint8,uint16,uint8,bool,bool))"]
10Roadmap
| Item | Status |
|---|---|
| score / tier / health + caching + pilot keys | live (testnet) |
| batch scoring | live (testnet) |
| webhooks on tier change | planned |
| mainnet deployment | planned |
| multi-attester quorum scoring | planned |
11Get a key
Instant trial (recommended)
Issue yourself a key in seconds — no signup, no email. One command:
curl -X POST https://giwa-defi-suite.vercel.app/api/keys/trial \
-H "content-type: application/json" \
-d '{"project":"my-launchpad"}'
You'll receive:
| Field | Value |
|---|---|
| cap | 1,000 calls / 30 days |
| burstPerMin | 60 req/min |
| nudge | Notice appended to responses after call 900 |
| upgrade | proven.defi@gmail.com |
Check your usage at any time:
curl -H "x-proven-key: YOUR_KEY" \ https://giwa-defi-suite.vercel.app/api/keys/usage