Pricing
/v1/pricing/* is a proxy through to the BlockFinaX pricing engine — a
stateful off-chain service that computes Merton jump-diffusion premiums with
GARCH(1,1)-integrated variance, calibrated per-pair against 20+ years of
historical closes. See Concepts → Premium pricing
for the model itself.
The pricing engine is a reference fair-value quote, not a constraint.
The on-chain contract accepts whatever premiumRate the underwriter passes
to createEvent. There is no on-chain check that the rate matches the
engine's quote.
The engine is most useful for:
- New underwriters learning the protocol who want a starting number
- Hedgers and LPs sanity-checking whether a posted
premiumRateis in the ballpark of fair value - Self-service venues that want pricing-as-a-service for their callers
Sophisticated underwriters — investment banks, FX desks, NDF traders —
typically have their own vol view, their own data, and their own NDF /
options-market inputs that produce a tighter or different number. They're
expected to set their own premiumRate and pass signature = "0x" to
mark the event as self-priced. See
Concepts → Setting your own price
for the rationale and the override flow.
The optional signed attestation path (passing chainId + diamondAddress
creatorto/v1/pricing/quote) only matters if the contract has been configured with the engine's signer address and you want the on-chain function to verify recency. Even then, it's the underwriter's choice to use it. Self-priced events skip this entirely.
POST /v1/pricing/quote
Returns a fair-value premium for an event, optionally signed for on-chain attestation.
Request
{
"pair": "USD/GHS",
"strike": 11.4,
"payoutCap": 12.0,
"expiryUnixSeconds": 1782182400,
"notional": 100,
"strikeAbove": true,
// Optional v8 attestation context — if any are provided, ALL must be
"chainId": 8453,
"diamondAddress": "0xbCC51E62C4948FD35ab505bd71804C849601e4Ef",
"creator": "0xCAB3..."
}
| field | type | notes |
|---|---|---|
pair | string | E.g. USD/GHS. Must be a pair the engine has historical data for |
strike, payoutCap | float | Rates in normal decimal (NOT 1e6 fixed-point) |
expiryUnixSeconds | int | Future timestamp |
notional | float | Hedger's notional in USDC (whole units) |
strikeAbove | bool | true = upward hedge / call spread |
chainId, diamondAddress, creator | optional | Provide all 3 to request a signed quote |
Response
{
"data": {
"premiumRate": 0.023,
"premiumUsd": 2.3,
"maxPayoutUsd": 5.26,
"premiumRateFixed6": "23000",
"attestation": null,
"breakdown": {
"pair": "USD/GHS",
"spot": 11.07,
"strike": 11.4, "payoutCap": 12.0,
"rangeWidth": 0.6,
"T_years": 0.0822, "T_days": 30,
"notional": 100,
"direction": "upward",
"coveragePercent": 1.99,
"inputs": {
"r": 0.045, // USD risk-free rate
"q": null, // local rate (null when using empirical drift)
"mu": 0.12, // empirical drift
"qEffective": -0.075, // what the kernel actually used
"sigma": 0.21, // vol with markup applied
"sigmaRealizedRaw": 0.18,
"volMarkup": 0.17
},
"method": "garman-kohlhagen-with-empirical-drift",
"pairClassification": { "tier": "frontierEM", "useEmpiricalDrift": true, "notes": null }
}
}
}
premiumRateFixed6 is the value you pass to createEvent as premiumRate.
With attestation
If you pass chainId + diamondAddress + creator, the engine signs the
quote (assuming PRICING_ENGINE_PRIVATE_KEY is configured upstream). The
response includes:
{
"data": {
"premiumRate": 0.023,
"premiumRateFixed6": "23000",
"attestation": {
"signature": "0xab..130-char hex..",
"quoteTimestamp": "1782182000",
"quoteNonce": "0xcdcd..64-char hex..",
"signerAddress": "0xAaAa...",
"expiresAt": "1782182120"
},
"breakdown": { ... }
}
}
Plug signature, quoteTimestamp, and quoteNonce directly into
createEvent. The quote expires in 120 seconds — expiresAt is the
wall-clock deadline.
Errors
| Status | code | When |
|---|---|---|
| 400 | validation_error | Malformed input (bad address, negative strike, etc.) |
| 400 | validation_error | All-three-or-none rule on attestation fields |
| 400 | validation_error | Engine rejected the quote (e.g. leverage > 100×, unsupported pair) |
| 502 | upstream_error | Engine errored internally |
| 503 | service_unavailable | Engine unreachable (network failure) |
GET /v1/pricing/health
Engine diagnostic snapshot.
{
"data": {
"usdRate": {
"rate": 0.0445,
"recordDate": "2026-05-13",
"fetchedAt": 1782181000000
},
"pricingEngineSigner": "0xAaAa...",
"pairs": [
{ "pair": "USD/GHS", "tier": "frontierEM", "useEmpiricalDrift": true, "historicalCloses": 1300 },
{ "pair": "USD/NGN", "tier": "frontierEM", "useEmpiricalDrift": true, "historicalCloses": 1300 }
]
}
}
Useful for:
- Confirming the engine has fresh USD-rate data (the timestamp).
- Verifying
pricingEngineSignermatches what's set on-chain viasetPricingEngineSigner— if they differ, the engine's signatures will be rejected. - Checking which pairs the engine can price (
historicalClosesshould be= 30 to produce a meaningful EWMA vol).
GET /v1/pricing/signer
Just the signer slice of /health. Returns null if the engine has no
signing key configured (i.e. it's in advisory-only mode).
{ "data": { "signerAddress": "0xAaAa..." } }
Compare against the on-chain signer:
curl https://api.blockfinax.com/v1/hedge/pricing-engine-signer/8453
If they don't match, signed quotes from this engine will not be accepted
by the contract — the on-chain owner needs to call
setPricingEngineSigner to rotate.