Skip to main content
Each shield contract validates params.asset against a hardcoded literal. Sending the wrong asset reverts with InvalidAsset(bytes32) even though the payment token (USDC) is the same for every product. The asset is a what-it-covers tag, not the payment token.

The 6 V5.4 products

The bytes32 hashes below come from the live /products endpoint and match the PRODUCT_ID constants in each BaseFlashShield deployment on Base mainnet. /products returns 6 active shields. Agents should still filter by active === true to be forward-compatible with future product retirements.
Product nameExpected assetShield typeDuration
FLASHBTC1H-001BTCFlash crash on BTC1 h
FLASHBTC24-001BTCFlash crash on BTC24 h
FLASHBTC48-001BTCFlash crash on BTC48 h
FLASHETH1H-001ETHFlash crash on ETH1 h
FLASHETH24-001ETHFlash crash on ETH24 h
FLASHETH48-001ETHFlash crash on ETH48 h
Each shield is fronted by a FlashShieldAdapter (UUPS proxy) — discover the adapter address with productShield(productId) on PolicyManagerV2, or just read it off /products. SDK 0.6.x auto-resolves both the bytes32 productId hash AND the per-shield asset literal from the canonical name. You don’t need to compute keccak yourself, and you can’t accidentally pair FLASHBTC1H-001 with ETH.
const policy = await lumina.policies.purchase({
  productName:    'FLASHBTC1H-001',  // SDK resolves productId hash + asset='BTC'
  buyer:          '0xYourWalletAddress',
  coverageAmount: '100000000',       // $100 minimum, paid in USDC
})

REST: pass productName to POST /api/v1/policies

The same shortcut works at the API level. asset is optional; if you omit it, the API auto-resolves from the registry.
curl -X POST https://lumina-api-production-ac85.up.railway.app/api/v1/policies \
  -H "x-api-key: $LUMINA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "productName":    "FLASHBTC1H-001",
    "coverageAmount": "100000000",
    "buyer":          "0xYourWalletAddress"
  }'

Sandbox: switch shields with productName

POST /sandbox/try resolves the asset from productId (default FLASHBTC1H-001BTC) or accepts productName for friendlier switching. See Sandbox-first for the full no-wallet path.
curl -X POST https://lumina-api-production-ac85.up.railway.app/sandbox/try \
  -H "Content-Type: application/json" \
  -d '{"productName":"FLASHETH24-001"}'   # → asset auto-resolves to ETH

Advanced: explicit asset override

If you want to bypass the auto-resolver (e.g. to reproduce a revert in testing), pass the bytes32 explicitly:
import { keccak256, toUtf8Bytes } from 'ethers'

await lumina.policies.purchase({
  productId:      keccak256(toUtf8Bytes('FLASHBTC24-001')),
  buyer:          '0xYourWalletAddress',
  coverageAmount: '100000000',
  asset:          'BTC',                       // MUST match the shield's literal
})
The SDK accepts symbols ('BTC' | 'ETH') for the 6 active products and encodes them to bytes32. You can also pass a 32-byte hex string directly.

Common errors

ErrorCauseFix
InvalidAsset(bytes32)Sent the wrong asset for that shieldUse productName and let the SDK auto-resolve
unknown_product (400)productName not in the registryCheck the table above; only the 6 listed products are active
ProductNotConfiguredproductId hash doesn’t exist on-chainVerify the keccak256 preimage matches a canonical name
InvalidCoverageBelow $100 minimum (MIN_PRICE_FOR_NEW_POLICIES)Increase coverageAmount to ≥ 100000000
shield_paused (422)Hitting the paused legacy entry from /productsFilter the product list by active === true