Earn Overview
Sparky Earn offers fixed-term USDT products backed by an on-chain ERC-1155 contract. Users subscribe during a subscription window, principal is locked until settlement, then principal + interest are claimed on-chain.
All paths below are relative to https://api-avax.<sparky-domain>/api/v1 (one deployment per chain — see Base URLs).
- Token: USDT (6 decimals)
- Receipt: soulbound ERC-1155 NFT (non-transferable), burned on claim
- Interest:
principal × (annual_rate / 365) × lock_days
Product lifecycle
created ──▶ subscribing ──▶ active ──▶ settled ──▶ ended
│ │
└──▶ cancelled ◀───────────┘
| Status | Meaning |
|---|---|
created | Not yet open |
subscribing | Subscription window open |
active | Window closed, principal locked |
settled | Matured — claim available |
ended | Everyone has claimed |
cancelled | Emergency cancel — emergencyClaim returns principal |
Transitions are driven by a scheduler that runs every 60 s, so expect up to a minute of lag around each boundary.
NFT status
| Status | Meaning |
|---|---|
created | Record created, awaiting chain confirmation |
active | Minted, product running |
matured | Settled, claimable |
redeemed | Claimed, NFT burned |
Units
| Field family | Unit | Example |
|---|---|---|
Product quotas / limits (total_quota, min_amount, …) | on-chain units (USDT × 10^6) | "100000000" = 100 USDT |
Subscription records (amount, expected_return, …) | on-chain units | |
annual_rate, period_rate | percent string | "50.00%" |
*_bps | basis points | 5000 = 50 % |
POST /earn/subscribe/prepare → amount in request | human-readable USDT | "100" |
Subscription flow
① GET /earn/products → pick a product in `subscribing`
② POST /earn/subscribe/prepare → backend EIP-712 signature (30 min)
③ USDT.approve(contract, amount) (on-chain)
④ Earn.subscribe(productId, amount, deadline, signature) (on-chain)
⑤ backend indexes `Subscribed` → record + NFT + points
Claiming after settlement is a direct contract call (claim(productId)); no backend endpoint is involved.
Endpoints
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /earn/domain | — | EIP-712 domain + Subscribe type |
| GET | /earn/products | — | Product list |
| GET | /earn/products/:id | — | Product detail |
| GET | /earn/performance | — | Historical performance |
| GET | /earn/subscriptions | JWT | My subscriptions |
| POST | /earn/subscribe/prepare | JWT | Subscription signature |
Contract interface: Earn contract. Daily subscription quotas per user derive from the Earn Level — see Points › Earn Quota.
Errors
{ "error": "Product is not open for subscription", "code": "SUBSCRIPTION_CLOSED" }
| code | HTTP | Meaning |
|---|---|---|
SUBSCRIPTION_CLOSED | 400 | Product not subscribing or outside the window |
AMOUNT_TOO_LOW | 400 | Below min_amount |
AMOUNT_TOO_HIGH | 400 | Above max_amount_per_user |
QUOTA_EXCEEDED | 400 | Product quota exhausted |
INVALID_AMOUNT | 400 | Malformed / ≤ 0 |
PRODUCT_NOT_FOUND | 404 | |
UNAUTHORIZED | 401 |