Files
graph/e2e/resolvers_test.go

1355 lines
46 KiB
Go

//go:build e2e
package e2e
import (
"context"
"fmt"
"testing"
"github.com/luxfi/graph/engine"
"github.com/luxfi/graph/storage"
)
// ---------------------------------------------------------------------------
// Helper: create engine with all schemas loaded and a seeded store.
// ---------------------------------------------------------------------------
func newTestEngine(t *testing.T) (*engine.Engine, *storage.Store) {
t.Helper()
store, err := storage.New(t.TempDir())
if err != nil {
t.Fatal(err)
}
if err := store.Init(context.Background()); err != nil {
t.Fatal(err)
}
eng := engine.New(store, nil)
if err := eng.LoadBuiltin("all"); err != nil {
t.Fatal(err)
}
return eng, store
}
func execOK(t *testing.T, eng *engine.Engine, query string) map[string]interface{} {
t.Helper()
resp := eng.Execute(context.Background(), &engine.Request{Query: query})
if len(resp.Errors) > 0 {
t.Fatalf("query error: %s\nquery: %s", resp.Errors[0].Message, query)
}
data, ok := resp.Data.(map[string]interface{})
if !ok {
t.Fatalf("expected map data, got %T", resp.Data)
}
return data
}
func execErr(t *testing.T, eng *engine.Engine, query string) string {
t.Helper()
resp := eng.Execute(context.Background(), &engine.Request{Query: query})
if len(resp.Errors) == 0 {
t.Fatal("expected error, got none")
}
return resp.Errors[0].Message
}
func requireList(t *testing.T, data map[string]interface{}, key string, minLen int) []interface{} {
t.Helper()
raw, ok := data[key]
if !ok {
t.Fatalf("missing key %q in response", key)
}
list, ok := raw.([]interface{})
if !ok {
t.Fatalf("key %q: expected []interface{}, got %T", key, raw)
}
if len(list) < minLen {
t.Fatalf("key %q: expected >= %d items, got %d", key, minLen, len(list))
}
return list
}
func requireMap(t *testing.T, data map[string]interface{}, key string) map[string]interface{} {
t.Helper()
raw, ok := data[key]
if !ok || raw == nil {
t.Fatalf("missing or nil key %q in response", key)
}
m, ok := raw.(map[string]interface{})
if !ok {
t.Fatalf("key %q: expected map, got %T", key, raw)
}
return m
}
func requireField(t *testing.T, m map[string]interface{}, field string) interface{} {
t.Helper()
v, ok := m[field]
if !ok || v == nil {
t.Fatalf("missing field %q", field)
}
return v
}
// ---------------------------------------------------------------------------
// 1. AMM resolvers (C-Chain) — factory, bundle, pool, swap, token
// ---------------------------------------------------------------------------
func TestResolver_AMM_Factory(t *testing.T) {
eng, store := newTestEngine(t)
store.SeedFactory("1", &storage.SeedFactoryData{
PoolCount: 10, TxCount: 100,
TotalVolumeUSD: "500000.00", TotalValueLockedUSD: "200000.00",
})
data := execOK(t, eng, `{ factory(id: "1") { id poolCount txCount totalVolumeUSD totalValueLockedUSD } }`)
f := requireMap(t, data, "factory")
if fmt.Sprint(f["poolCount"]) != "10" {
t.Errorf("poolCount: got %v", f["poolCount"])
}
}
func TestResolver_AMM_Factories(t *testing.T) {
eng, store := newTestEngine(t)
store.SeedFactory("1", &storage.SeedFactoryData{PoolCount: 5, TxCount: 50, TotalVolumeUSD: "1000.00", TotalValueLockedUSD: "500.00"})
data := execOK(t, eng, `{ factories(first: 10) { id poolCount } }`)
requireList(t, data, "factories", 1)
}
func TestResolver_AMM_Bundle(t *testing.T) {
eng, store := newTestEngine(t)
store.SeedBundle("1", &storage.SeedBundleData{EthPriceUSD: "2.50"})
data := execOK(t, eng, `{ bundle(id: "1") { ethPriceUSD } }`)
b := requireMap(t, data, "bundle")
requireField(t, b, "ethPriceUSD")
}
func TestResolver_AMM_Pools(t *testing.T) {
eng, store := newTestEngine(t)
store.SeedToken("0xt0", &storage.SeedTokenData{Symbol: "A", Name: "TokenA", Decimals: 18})
store.SeedToken("0xt1", &storage.SeedTokenData{Symbol: "B", Name: "TokenB", Decimals: 18})
store.SeedPool("0xpool1", &storage.SeedPoolData{
Token0: "0xt0", Token1: "0xt1", FeeTier: 3000,
TotalValueLockedUSD: "100000.00", VolumeUSD: "50000.00",
Token0Price: "1.00", Token1Price: "1.00", TxCount: 42,
})
data := execOK(t, eng, `{ pools(first: 10) { id feeTier totalValueLockedUSD token0 { id symbol } token1 { id symbol } } }`)
pools := requireList(t, data, "pools", 1)
p := pools[0].(map[string]interface{})
requireField(t, p, "feeTier")
requireField(t, p, "token0")
requireField(t, p, "token1")
}
func TestResolver_AMM_Swaps(t *testing.T) {
eng, store := newTestEngine(t)
store.SeedSwap("0xswap1", &storage.SeedSwapData{
Timestamp: 1711929600, Pool: "0xpool1",
Amount0: "100.0", Amount1: "-250.0", AmountUSD: "250.00", Sender: "0xuser1",
})
store.SeedSwap("0xswap2", &storage.SeedSwapData{
Timestamp: 1711929601, Pool: "0xpool1",
Amount0: "200.0", Amount1: "-500.0", AmountUSD: "500.00", Sender: "0xuser2",
})
data := execOK(t, eng, `{ swaps(first: 10, orderBy: timestamp, orderDirection: desc) { id timestamp amount0 amount1 amountUSD sender } }`)
swaps := requireList(t, data, "swaps", 2)
s := swaps[0].(map[string]interface{})
requireField(t, s, "timestamp")
requireField(t, s, "sender")
}
func TestResolver_AMM_SwapSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SeedSwap("0xswap-single", &storage.SeedSwapData{
Timestamp: 100, Pool: "0xp", Amount0: "1", Amount1: "2", AmountUSD: "3", Sender: "0xs",
})
data := execOK(t, eng, `{ swap(id: "0xswap-single") { id amountUSD } }`)
s := requireMap(t, data, "swap")
if s["amountUSD"] != "3" {
t.Errorf("amountUSD: got %v", s["amountUSD"])
}
}
// ---------------------------------------------------------------------------
// 2. DEX resolvers (D-Chain) — orders, fills, markets, positions, funding, liquidations
// ---------------------------------------------------------------------------
func TestResolver_DEX_Orders(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Order", "order-1", map[string]interface{}{
"id": "order-1", "market": "LUX/USD", "side": "buy", "price": "2.50", "amount": "100", "status": "open",
})
store.SetEntity("Order", "order-2", map[string]interface{}{
"id": "order-2", "market": "LUX/USD", "side": "sell", "price": "2.60", "amount": "50", "status": "filled",
})
data := execOK(t, eng, `{ orders(first: 10) { id market side price amount status } }`)
requireList(t, data, "orders", 2)
}
func TestResolver_DEX_OrderSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Order", "order-1", map[string]interface{}{
"id": "order-1", "market": "LUX/USD", "side": "buy", "price": "2.50", "amount": "100",
})
data := execOK(t, eng, `{ order(id: "order-1") { id market side price } }`)
o := requireMap(t, data, "order")
if o["market"] != "LUX/USD" {
t.Errorf("market: got %v", o["market"])
}
}
func TestResolver_DEX_Fills(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Fill", "fill-1", map[string]interface{}{
"id": "fill-1", "order": "order-1", "price": "2.50", "amount": "50", "timestamp": 1711929600,
})
data := execOK(t, eng, `{ fills(first: 10) { id } }`)
requireList(t, data, "fills", 1)
}
func TestResolver_DEX_FillSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Fill", "fill-1", map[string]interface{}{
"id": "fill-1", "price": "2.50",
})
data := execOK(t, eng, `{ fill(id: "fill-1") { id price } }`)
f := requireMap(t, data, "fill")
if f["price"] != "2.50" {
t.Errorf("price: got %v", f["price"])
}
}
func TestResolver_DEX_Markets(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Market", "LUX-USD", map[string]interface{}{
"id": "LUX-USD", "base": "LUX", "quote": "USD", "lastPrice": "2.50", "volume24h": "1000000",
})
data := execOK(t, eng, `{ markets(first: 10) { id } }`)
requireList(t, data, "markets", 1)
}
func TestResolver_DEX_MarketSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Market", "LUX-USD", map[string]interface{}{
"id": "LUX-USD", "base": "LUX", "quote": "USD",
})
data := execOK(t, eng, `{ market(id: "LUX-USD") { id base quote } }`)
m := requireMap(t, data, "market")
if m["base"] != "LUX" {
t.Errorf("base: got %v", m["base"])
}
}
func TestResolver_DEX_PerpPositions(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("PerpPosition", "pos-1", map[string]interface{}{
"id": "pos-1", "market": "LUX/USD", "side": "long", "size": "1000", "entryPrice": "2.50",
})
data := execOK(t, eng, `{ perpPositions(first: 10) { id } }`)
requireList(t, data, "perpPositions", 1)
}
func TestResolver_DEX_FundingRates(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("FundingRate", "fr-1", map[string]interface{}{
"id": "fr-1", "market": "LUX/USD", "rate": "0.001", "timestamp": 1711929600,
})
data := execOK(t, eng, `{ fundingRates(first: 10) { id } }`)
requireList(t, data, "fundingRates", 1)
}
func TestResolver_DEX_Liquidations(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Liquidation", "liq-1", map[string]interface{}{
"id": "liq-1", "position": "pos-1", "amount": "500", "price": "2.00",
})
data := execOK(t, eng, `{ liquidations(first: 10) { id } }`)
requireList(t, data, "liquidations", 1)
}
func TestResolver_DEX_Orderbook(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Orderbook", "LUX-USD", map[string]interface{}{
"id": "LUX-USD", "bids": 50, "asks": 45,
})
data := execOK(t, eng, `{ orderbook(id: "LUX-USD") { id bids asks } }`)
ob := requireMap(t, data, "orderbook")
requireField(t, ob, "bids")
}
// ---------------------------------------------------------------------------
// 3. Platform resolvers (P-Chain) — validators, delegators, subnets, blockchains
// ---------------------------------------------------------------------------
func TestResolver_Platform_Validators(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Validator", "NodeID-abc", map[string]interface{}{
"id": "NodeID-abc", "stake": "2000000", "uptime": "99.95", "startTime": 1700000000, "endTime": 1800000000,
})
store.SetEntity("Validator", "NodeID-def", map[string]interface{}{
"id": "NodeID-def", "stake": "1000000", "uptime": "99.80",
})
data := execOK(t, eng, `{ validators(first: 10) { id stake uptime } }`)
requireList(t, data, "validators", 2)
}
func TestResolver_Platform_ValidatorSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Validator", "NodeID-abc", map[string]interface{}{
"id": "NodeID-abc", "stake": "2000000", "uptime": "99.95",
})
data := execOK(t, eng, `{ validator(id: "NodeID-abc") { id stake uptime } }`)
v := requireMap(t, data, "validator")
if v["stake"] != "2000000" {
t.Errorf("stake: got %v", v["stake"])
}
}
func TestResolver_Platform_Delegators(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Delegator", "del-1", map[string]interface{}{
"id": "del-1", "nodeID": "NodeID-abc", "stake": "100000", "rewardAddress": "P-lux1abc",
})
data := execOK(t, eng, `{ delegators(first: 10) { id } }`)
requireList(t, data, "delegators", 1)
}
func TestResolver_Platform_Subnets(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Subnet", "sub-1", map[string]interface{}{
"id": "sub-1", "controlKeys": 3, "threshold": 2,
})
data := execOK(t, eng, `{ subnets(first: 10) { id } }`)
requireList(t, data, "subnets", 1)
}
func TestResolver_Platform_Blockchains(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Blockchain", "bc-1", map[string]interface{}{
"id": "bc-1", "name": "Zoo", "vmID": "srEXiWaHuhNyGwPUi444Tw", "subnetID": "sub-1",
})
data := execOK(t, eng, `{ blockchains(first: 10) { id } }`)
requireList(t, data, "blockchains", 1)
}
func TestResolver_Platform_StakingRewards(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("StakingReward", "sr-1", map[string]interface{}{
"id": "sr-1", "nodeID": "NodeID-abc", "amount": "5000", "timestamp": 1711929600,
})
data := execOK(t, eng, `{ stakingRewards(first: 10) { id } }`)
requireList(t, data, "stakingRewards", 1)
}
func TestResolver_Platform_NetworkStats(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("NetworkStats", "1", map[string]interface{}{
"id": "1", "totalStake": "50000000", "validatorCount": 5, "delegatorCount": 100,
})
data := execOK(t, eng, `{ networkStats { id totalStake validatorCount } }`)
ns := requireMap(t, data, "networkStats")
if ns["totalStake"] != "50000000" {
t.Errorf("totalStake: got %v", ns["totalStake"])
}
}
// ---------------------------------------------------------------------------
// 4. Exchange resolvers (X-Chain) — assets, UTXOs, transfers, imports, exports
// ---------------------------------------------------------------------------
func TestResolver_Exchange_Assets(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Asset", "LUX", map[string]interface{}{
"id": "LUX", "symbol": "LUX", "name": "Lux", "denomination": 9,
})
store.SetEntity("Asset", "ZOO", map[string]interface{}{
"id": "ZOO", "symbol": "ZOO", "name": "Zoo Token", "denomination": 6,
})
data := execOK(t, eng, `{ assets(first: 10) { id symbol name denomination } }`)
requireList(t, data, "assets", 2)
}
func TestResolver_Exchange_AssetSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Asset", "LUX", map[string]interface{}{
"id": "LUX", "symbol": "LUX", "name": "Lux", "denomination": 9,
})
data := execOK(t, eng, `{ asset(id: "LUX") { id symbol denomination } }`)
a := requireMap(t, data, "asset")
if a["symbol"] != "LUX" {
t.Errorf("symbol: got %v", a["symbol"])
}
}
func TestResolver_Exchange_UTXOs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("UTXO", "utxo-1", map[string]interface{}{
"id": "utxo-1", "txID": "0xabc", "outputIndex": 0, "amount": "1000000000",
})
data := execOK(t, eng, `{ utxos(first: 10) { id } }`)
requireList(t, data, "utxos", 1)
}
func TestResolver_Exchange_XTransfers(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("XTransfer", "xt-1", map[string]interface{}{
"id": "xt-1", "from": "X-lux1abc", "to": "X-lux1def", "amount": "500000",
})
data := execOK(t, eng, `{ xTransfers(first: 10) { id } }`)
requireList(t, data, "xTransfers", 1)
}
func TestResolver_Exchange_ImportExportTxs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ImportTx", "imp-1", map[string]interface{}{
"id": "imp-1", "sourceChain": "C", "amount": "1000",
})
store.SetEntity("ExportTx", "exp-1", map[string]interface{}{
"id": "exp-1", "destChain": "P", "amount": "2000",
})
data := execOK(t, eng, `{ importTxs(first: 10) { id } }`)
requireList(t, data, "importTxs", 1)
data = execOK(t, eng, `{ exportTxs(first: 10) { id } }`)
requireList(t, data, "exportTxs", 1)
}
// ---------------------------------------------------------------------------
// 5. Bridge resolvers (B-Chain) — transfers, MPC sigs, wrapped assets, requests
// ---------------------------------------------------------------------------
func TestResolver_Bridge_Transfers(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("BridgeTransfer", "bt-1", map[string]interface{}{
"id": "bt-1", "sourceChain": "C", "destChain": "ethereum", "amount": "1000", "status": "completed",
})
data := execOK(t, eng, `{ bridgeTransfers(first: 10) { id sourceChain destChain amount } }`)
list := requireList(t, data, "bridgeTransfers", 1)
bt := list[0].(map[string]interface{})
if bt["sourceChain"] != "C" {
t.Errorf("sourceChain: got %v", bt["sourceChain"])
}
}
func TestResolver_Bridge_TransferSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("BridgeTransfer", "bt-1", map[string]interface{}{
"id": "bt-1", "sourceChain": "C", "destChain": "ethereum", "amount": "1000",
})
data := execOK(t, eng, `{ bridgeTransfer(id: "bt-1") { id amount } }`)
bt := requireMap(t, data, "bridgeTransfer")
if bt["amount"] != "1000" {
t.Errorf("amount: got %v", bt["amount"])
}
}
func TestResolver_Bridge_MPCSignatures(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("MPCSignature", "mpc-1", map[string]interface{}{
"id": "mpc-1", "txHash": "0xabc", "signers": 3, "threshold": 2,
})
data := execOK(t, eng, `{ mpcSignatures(first: 10) { id } }`)
requireList(t, data, "mpcSignatures", 1)
}
func TestResolver_Bridge_WrappedAssets(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("WrappedAsset", "wa-1", map[string]interface{}{
"id": "wa-1", "original": "ETH", "wrapped": "WETH.lux", "totalLocked": "500",
})
data := execOK(t, eng, `{ wrappedAssets(first: 10) { id } }`)
requireList(t, data, "wrappedAssets", 1)
}
func TestResolver_Bridge_BridgeRequests(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("BridgeRequest", "br-1", map[string]interface{}{
"id": "br-1", "user": "0xabc", "amount": "100", "status": "pending",
})
data := execOK(t, eng, `{ bridgeRequests(first: 10) { id } }`)
requireList(t, data, "bridgeRequests", 1)
}
// ---------------------------------------------------------------------------
// 6. FHE/Threshold resolvers (T-Chain) — DKG, decryption, compute, ciphertexts
// ---------------------------------------------------------------------------
func TestResolver_FHE_DKGCeremonies(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("DKGCeremony", "dkg-1", map[string]interface{}{
"id": "dkg-1", "participants": 5, "threshold": 3, "status": "complete", "round": 1,
})
data := execOK(t, eng, `{ dkgCeremonies(first: 10) { id participants threshold status } }`)
list := requireList(t, data, "dkgCeremonies", 1)
dkg := list[0].(map[string]interface{})
if dkg["status"] != "complete" {
t.Errorf("status: got %v", dkg["status"])
}
}
func TestResolver_FHE_DKGCeremonySingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("DKGCeremony", "dkg-1", map[string]interface{}{
"id": "dkg-1", "participants": 5, "threshold": 3, "status": "complete",
})
data := execOK(t, eng, `{ dkgCeremony(id: "dkg-1") { id threshold } }`)
dkg := requireMap(t, data, "dkgCeremony")
if fmt.Sprint(dkg["threshold"]) != "3" {
t.Errorf("threshold: got %v", dkg["threshold"])
}
}
func TestResolver_FHE_DecryptionRequests(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("DecryptionRequest", "dr-1", map[string]interface{}{
"id": "dr-1", "requester": "0xabc", "ciphertextID": "ct-1", "status": "pending",
})
data := execOK(t, eng, `{ decryptionRequests(first: 10) { id } }`)
requireList(t, data, "decryptionRequests", 1)
}
func TestResolver_FHE_ComputeJobs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ComputeJob", "cj-1", map[string]interface{}{
"id": "cj-1", "operation": "add", "inputA": "ct-1", "inputB": "ct-2", "result": "ct-3",
})
data := execOK(t, eng, `{ computeJobs(first: 10) { id } }`)
requireList(t, data, "computeJobs", 1)
}
func TestResolver_FHE_Ciphertexts(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Ciphertext", "ct-1", map[string]interface{}{
"id": "ct-1", "owner": "0xabc", "scheme": "BGV", "size": 4096,
})
data := execOK(t, eng, `{ ciphertexts(first: 10) { id } }`)
requireList(t, data, "ciphertexts", 1)
}
// ---------------------------------------------------------------------------
// 7. Privacy resolvers (Z-Chain) — shielded transfers, ZK proofs, nullifiers
// ---------------------------------------------------------------------------
func TestResolver_Privacy_ShieldedTransfers(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ShieldedTransfer", "st-1", map[string]interface{}{
"id": "st-1", "nullifier": "0xnull1", "commitment": "0xcomm1", "amount": "encrypted",
})
data := execOK(t, eng, `{ shieldedTransfers(first: 10) { id nullifier commitment } }`)
list := requireList(t, data, "shieldedTransfers", 1)
st := list[0].(map[string]interface{})
if st["nullifier"] != "0xnull1" {
t.Errorf("nullifier: got %v", st["nullifier"])
}
}
func TestResolver_Privacy_ShieldedTransferSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ShieldedTransfer", "st-1", map[string]interface{}{
"id": "st-1", "nullifier": "0xnull1", "commitment": "0xcomm1",
})
data := execOK(t, eng, `{ shieldedTransfer(id: "st-1") { id nullifier } }`)
st := requireMap(t, data, "shieldedTransfer")
if st["nullifier"] != "0xnull1" {
t.Errorf("nullifier: got %v", st["nullifier"])
}
}
func TestResolver_Privacy_ZKProofs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ZKProof", "zk-1", map[string]interface{}{
"id": "zk-1", "proofType": "groth16", "verifier": "0xverify", "verified": true,
})
data := execOK(t, eng, `{ zkProofs(first: 10) { id } }`)
requireList(t, data, "zkProofs", 1)
}
func TestResolver_Privacy_Nullifiers(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Nullifier", "null-1", map[string]interface{}{
"id": "null-1", "hash": "0xnullhash", "spent": true,
})
data := execOK(t, eng, `{ nullifiers(first: 10) { id } }`)
requireList(t, data, "nullifiers", 1)
}
func TestResolver_Privacy_Commitments(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Commitment", "comm-1", map[string]interface{}{
"id": "comm-1", "leafIndex": 42, "value": "0xcommhash",
})
data := execOK(t, eng, `{ commitments(first: 10) { id } }`)
requireList(t, data, "commitments", 1)
}
// ---------------------------------------------------------------------------
// 8. Quantum resolvers (Q-Chain) — corona sigs, quantum proofs, PQ keys
// ---------------------------------------------------------------------------
func TestResolver_Quantum_CoronaSignatures(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("CoronaSignature", "rs-1", map[string]interface{}{
"id": "rs-1", "algorithm": "ML-DSA-65", "keyID": "key-1", "verified": true,
})
data := execOK(t, eng, `{ coronaSignatures(first: 10) { id algorithm verified } }`)
list := requireList(t, data, "coronaSignatures", 1)
rs := list[0].(map[string]interface{})
if rs["algorithm"] != "ML-DSA-65" {
t.Errorf("algorithm: got %v", rs["algorithm"])
}
}
func TestResolver_Quantum_CoronaSignatureSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("CoronaSignature", "rs-1", map[string]interface{}{
"id": "rs-1", "algorithm": "ML-DSA-65",
})
data := execOK(t, eng, `{ coronaSignature(id: "rs-1") { id algorithm } }`)
rs := requireMap(t, data, "coronaSignature")
if rs["algorithm"] != "ML-DSA-65" {
t.Errorf("algorithm: got %v", rs["algorithm"])
}
}
func TestResolver_Quantum_QuantumProofs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("QuantumProof", "qp-1", map[string]interface{}{
"id": "qp-1", "proofType": "lattice", "securityLevel": 128,
})
data := execOK(t, eng, `{ quantumProofs(first: 10) { id } }`)
requireList(t, data, "quantumProofs", 1)
}
func TestResolver_Quantum_PQKeyPairs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("PQKeyPair", "kp-1", map[string]interface{}{
"id": "kp-1", "algorithm": "ML-KEM-768", "publicKeyHash": "0xpkhash",
})
data := execOK(t, eng, `{ pqKeyPairs(first: 10) { id } }`)
requireList(t, data, "pqKeyPairs", 1)
}
func TestResolver_Quantum_Stats(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("QuantumStats", "1", map[string]interface{}{
"id": "1", "totalSignatures": 1000, "totalProofs": 500,
})
data := execOK(t, eng, `{ quantumStats { id totalSignatures totalProofs } }`)
qs := requireMap(t, data, "quantumStats")
if fmt.Sprint(qs["totalSignatures"]) != "1000" {
t.Errorf("totalSignatures: got %v", qs["totalSignatures"])
}
}
// ---------------------------------------------------------------------------
// 9. Key resolvers (K-Chain) — managed keys, rotations, ceremonies, attestations
// ---------------------------------------------------------------------------
func TestResolver_Key_ManagedKeys(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ManagedKey", "mk-1", map[string]interface{}{
"id": "mk-1", "algorithm": "ECDSA-secp256k1", "owner": "0xabc", "status": "active",
})
data := execOK(t, eng, `{ managedKeys(first: 10) { id algorithm owner status } }`)
list := requireList(t, data, "managedKeys", 1)
mk := list[0].(map[string]interface{})
if mk["algorithm"] != "ECDSA-secp256k1" {
t.Errorf("algorithm: got %v", mk["algorithm"])
}
}
func TestResolver_Key_ManagedKeySingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ManagedKey", "mk-1", map[string]interface{}{
"id": "mk-1", "algorithm": "ECDSA-secp256k1",
})
data := execOK(t, eng, `{ managedKey(id: "mk-1") { id algorithm } }`)
mk := requireMap(t, data, "managedKey")
if mk["algorithm"] != "ECDSA-secp256k1" {
t.Errorf("algorithm: got %v", mk["algorithm"])
}
}
func TestResolver_Key_Rotations(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("KeyRotation", "kr-1", map[string]interface{}{
"id": "kr-1", "keyID": "mk-1", "oldPublicKey": "0xold", "newPublicKey": "0xnew",
})
data := execOK(t, eng, `{ keyRotations(first: 10) { id } }`)
requireList(t, data, "keyRotations", 1)
}
func TestResolver_Key_Ceremonies(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("KeyCeremony", "kc-1", map[string]interface{}{
"id": "kc-1", "participants": 5, "threshold": 3, "protocol": "FROST",
})
data := execOK(t, eng, `{ keyCeremonies(first: 10) { id } }`)
requireList(t, data, "keyCeremonies", 1)
}
func TestResolver_Key_Attestations(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("KeyAttestation", "ka-1", map[string]interface{}{
"id": "ka-1", "keyID": "mk-1", "attester": "0xatt", "valid": true,
})
data := execOK(t, eng, `{ keyAttestations(first: 10) { id } }`)
requireList(t, data, "keyAttestations", 1)
}
// ---------------------------------------------------------------------------
// 10. AI resolvers (A-Chain) — inference proofs, models, attestations, jobs
// ---------------------------------------------------------------------------
func TestResolver_AI_InferenceProofs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("InferenceProof", "ip-1", map[string]interface{}{
"id": "ip-1", "modelHash": "0xmodel1", "inputHash": "0xinput1", "outputHash": "0xout1", "prover": "0xprover1",
})
data := execOK(t, eng, `{ inferenceProofs(first: 10) { id modelHash prover } }`)
list := requireList(t, data, "inferenceProofs", 1)
ip := list[0].(map[string]interface{})
if ip["modelHash"] != "0xmodel1" {
t.Errorf("modelHash: got %v", ip["modelHash"])
}
}
func TestResolver_AI_InferenceProofSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("InferenceProof", "ip-1", map[string]interface{}{
"id": "ip-1", "modelHash": "0xmodel1",
})
data := execOK(t, eng, `{ inferenceProof(id: "ip-1") { id modelHash } }`)
ip := requireMap(t, data, "inferenceProof")
if ip["modelHash"] != "0xmodel1" {
t.Errorf("modelHash: got %v", ip["modelHash"])
}
}
func TestResolver_AI_ModelHashes(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ModelHash", "mh-1", map[string]interface{}{
"id": "mh-1", "hash": "0xhash", "name": "qwen3-70b", "version": "1.0",
})
data := execOK(t, eng, `{ modelHashes(first: 10) { id } }`)
requireList(t, data, "modelHashes", 1)
}
func TestResolver_AI_ComputeAttestations(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ComputeAttestation", "ca-1", map[string]interface{}{
"id": "ca-1", "attester": "NodeID-abc", "gpuModel": "H100", "tflops": 989,
})
data := execOK(t, eng, `{ computeAttestations(first: 10) { id } }`)
requireList(t, data, "computeAttestations", 1)
}
func TestResolver_AI_Jobs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("AIJob", "job-1", map[string]interface{}{
"id": "job-1", "model": "qwen3-70b", "status": "running", "cost": "50",
})
data := execOK(t, eng, `{ aiJobs(first: 10) { id } }`)
requireList(t, data, "aiJobs", 1)
}
func TestResolver_AI_TrainingRuns(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("TrainingRun", "tr-1", map[string]interface{}{
"id": "tr-1", "dataset": "ds-1", "epochs": 10, "loss": "0.05",
})
data := execOK(t, eng, `{ trainingRuns(first: 10) { id } }`)
requireList(t, data, "trainingRuns", 1)
}
// ---------------------------------------------------------------------------
// 11. Identity resolvers (I-Chain) — DIDs, credentials, attestations
// ---------------------------------------------------------------------------
func TestResolver_Identity_DIDs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("DID", "did:lux:abc123", map[string]interface{}{
"id": "did:lux:abc123", "controller": "0xabc", "created": 1711929600, "method": "lux",
})
data := execOK(t, eng, `{ dids(first: 10) { id controller method } }`)
list := requireList(t, data, "dids", 1)
did := list[0].(map[string]interface{})
if did["method"] != "lux" {
t.Errorf("method: got %v", did["method"])
}
}
func TestResolver_Identity_DIDSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("DID", "did:lux:abc123", map[string]interface{}{
"id": "did:lux:abc123", "controller": "0xabc",
})
data := execOK(t, eng, `{ did(id: "did:lux:abc123") { id controller } }`)
did := requireMap(t, data, "did")
if did["controller"] != "0xabc" {
t.Errorf("controller: got %v", did["controller"])
}
}
func TestResolver_Identity_VerifiableCredentials(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("VerifiableCredential", "vc-1", map[string]interface{}{
"id": "vc-1", "issuer": "did:lux:issuer1", "subject": "did:lux:abc123", "type": "KYC",
})
data := execOK(t, eng, `{ verifiableCredentials(first: 10) { id } }`)
requireList(t, data, "verifiableCredentials", 1)
}
func TestResolver_Identity_Attestations(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("Attestation", "att-1", map[string]interface{}{
"id": "att-1", "attester": "did:lux:att1", "subject": "did:lux:abc123", "claim": "verified",
})
data := execOK(t, eng, `{ attestations(first: 10) { id } }`)
requireList(t, data, "attestations", 1)
}
func TestResolver_Identity_CredentialSchemas(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("CredentialSchema", "cs-1", map[string]interface{}{
"id": "cs-1", "name": "KYCSchema", "version": "1.0", "fields": 5,
})
data := execOK(t, eng, `{ credentialSchemas(first: 10) { id } }`)
requireList(t, data, "credentialSchemas", 1)
}
// ---------------------------------------------------------------------------
// 12. Oracle resolvers (O-Chain) — price feeds, data requests, reports, nodes
// ---------------------------------------------------------------------------
func TestResolver_Oracle_PriceFeeds(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("PriceFeed", "LUX-USD", map[string]interface{}{
"id": "LUX-USD", "pair": "LUX/USD", "price": "2.50", "timestamp": 1711929600, "decimals": 8,
})
data := execOK(t, eng, `{ priceFeeds(first: 10) { id pair price } }`)
list := requireList(t, data, "priceFeeds", 1)
pf := list[0].(map[string]interface{})
if pf["price"] != "2.50" {
t.Errorf("price: got %v", pf["price"])
}
}
func TestResolver_Oracle_PriceFeedSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("PriceFeed", "LUX-USD", map[string]interface{}{
"id": "LUX-USD", "price": "2.50",
})
data := execOK(t, eng, `{ priceFeed(id: "LUX-USD") { id price } }`)
pf := requireMap(t, data, "priceFeed")
if pf["price"] != "2.50" {
t.Errorf("price: got %v", pf["price"])
}
}
func TestResolver_Oracle_DataRequests(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("DataRequest", "dreq-1", map[string]interface{}{
"id": "dreq-1", "requester": "0xabc", "dataType": "price", "status": "fulfilled",
})
data := execOK(t, eng, `{ dataRequests(first: 10) { id } }`)
requireList(t, data, "dataRequests", 1)
}
func TestResolver_Oracle_OracleReports(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("OracleReport", "or-1", map[string]interface{}{
"id": "or-1", "feedID": "LUX-USD", "value": "2.50", "reporter": "NodeID-abc",
})
data := execOK(t, eng, `{ oracleReports(first: 10) { id } }`)
requireList(t, data, "oracleReports", 1)
}
func TestResolver_Oracle_OracleNodes(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("OracleNode", "on-1", map[string]interface{}{
"id": "on-1", "nodeID": "NodeID-abc", "stake": "100000", "reputation": 95,
})
data := execOK(t, eng, `{ oracleNodes(first: 10) { id } }`)
requireList(t, data, "oracleNodes", 1)
}
// ---------------------------------------------------------------------------
// 13. Relay resolvers (R-Chain) — warp messages, relay requests/proofs/routes
// ---------------------------------------------------------------------------
func TestResolver_Relay_WarpMessages(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("WarpMessage", "wm-1", map[string]interface{}{
"id": "wm-1", "sourceChain": "C", "destChain": "Zoo", "payload": "0xdata", "timestamp": 1711929600,
})
data := execOK(t, eng, `{ warpMessages(first: 10) { id sourceChain destChain } }`)
list := requireList(t, data, "warpMessages", 1)
wm := list[0].(map[string]interface{})
if wm["sourceChain"] != "C" {
t.Errorf("sourceChain: got %v", wm["sourceChain"])
}
}
func TestResolver_Relay_WarpMessageSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("WarpMessage", "wm-1", map[string]interface{}{
"id": "wm-1", "sourceChain": "C", "destChain": "Zoo",
})
data := execOK(t, eng, `{ warpMessage(id: "wm-1") { id sourceChain } }`)
wm := requireMap(t, data, "warpMessage")
if wm["sourceChain"] != "C" {
t.Errorf("sourceChain: got %v", wm["sourceChain"])
}
}
func TestResolver_Relay_RelayRequests(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("RelayRequest", "rr-1", map[string]interface{}{
"id": "rr-1", "messageID": "wm-1", "relayer": "0xrelayer", "fee": "10",
})
data := execOK(t, eng, `{ relayRequests(first: 10) { id } }`)
requireList(t, data, "relayRequests", 1)
}
func TestResolver_Relay_RelayProofs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("RelayProof", "rp-1", map[string]interface{}{
"id": "rp-1", "messageID": "wm-1", "proof": "0xproof", "verified": true,
})
data := execOK(t, eng, `{ relayProofs(first: 10) { id } }`)
requireList(t, data, "relayProofs", 1)
}
func TestResolver_Relay_MessageReceipts(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("MessageReceipt", "mr-1", map[string]interface{}{
"id": "mr-1", "messageID": "wm-1", "status": "delivered", "timestamp": 1711929700,
})
data := execOK(t, eng, `{ messageReceipts(first: 10) { id } }`)
requireList(t, data, "messageReceipts", 1)
}
// ---------------------------------------------------------------------------
// 14. ServiceNode resolvers (S-Chain) — nodes, registrations, SLA, uptime
// ---------------------------------------------------------------------------
func TestResolver_ServiceNode_Nodes(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ServiceNode", "sn-1", map[string]interface{}{
"id": "sn-1", "nodeID": "NodeID-abc", "stake": "500000", "serviceType": "rpc", "status": "active",
})
data := execOK(t, eng, `{ serviceNodes(first: 10) { id nodeID stake serviceType status } }`)
list := requireList(t, data, "serviceNodes", 1)
sn := list[0].(map[string]interface{})
if sn["serviceType"] != "rpc" {
t.Errorf("serviceType: got %v", sn["serviceType"])
}
}
func TestResolver_ServiceNode_NodeSingle(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ServiceNode", "sn-1", map[string]interface{}{
"id": "sn-1", "serviceType": "rpc",
})
data := execOK(t, eng, `{ serviceNode(id: "sn-1") { id serviceType } }`)
sn := requireMap(t, data, "serviceNode")
if sn["serviceType"] != "rpc" {
t.Errorf("serviceType: got %v", sn["serviceType"])
}
}
func TestResolver_ServiceNode_Registrations(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ServiceRegistration", "sr-1", map[string]interface{}{
"id": "sr-1", "nodeID": "sn-1", "service": "graphql", "endpoint": "https://graph.lux.network",
})
data := execOK(t, eng, `{ serviceRegistrations(first: 10) { id } }`)
requireList(t, data, "serviceRegistrations", 1)
}
func TestResolver_ServiceNode_SLARecords(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("SLARecord", "sla-1", map[string]interface{}{
"id": "sla-1", "nodeID": "sn-1", "uptime": "99.99", "latencyMs": 12,
})
data := execOK(t, eng, `{ slaRecords(first: 10) { id } }`)
requireList(t, data, "slaRecords", 1)
}
func TestResolver_ServiceNode_UptimeProofs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("UptimeProof", "up-1", map[string]interface{}{
"id": "up-1", "nodeID": "sn-1", "timestamp": 1711929600, "proof": "0xuptimeproof",
})
data := execOK(t, eng, `{ uptimeProofs(first: 10) { id } }`)
requireList(t, data, "uptimeProofs", 1)
}
func TestResolver_ServiceNode_Endpoints(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ServiceEndpoint", "ep-1", map[string]interface{}{
"id": "ep-1", "nodeID": "sn-1", "url": "https://rpc.lux.network", "protocol": "jsonrpc",
})
data := execOK(t, eng, `{ serviceEndpoints(first: 10) { id } }`)
requireList(t, data, "serviceEndpoints", 1)
}
// ---------------------------------------------------------------------------
// 15. Precompile resolvers — all precompile types
// ---------------------------------------------------------------------------
func TestResolver_Precompile_Calls(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("PrecompileCall", "pc-1", map[string]interface{}{
"id": "pc-1", "address": "0x0200000000000000000000000000000000000007", "caller": "0xabc", "gasUsed": 21000,
})
data := execOK(t, eng, `{ precompileCalls(first: 10) { id address caller gasUsed } }`)
list := requireList(t, data, "precompileCalls", 1)
pc := list[0].(map[string]interface{})
if fmt.Sprint(pc["gasUsed"]) != "21000" {
t.Errorf("gasUsed: got %v", pc["gasUsed"])
}
}
func TestResolver_Precompile_AIWorkProofs(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("AIWorkProof", "awp-1", map[string]interface{}{
"id": "awp-1", "miner": "0xminer", "nonce": 42, "difficulty": "1000000",
})
data := execOK(t, eng, `{ aiWorkProofs(first: 10) { id } }`)
requireList(t, data, "aiWorkProofs", 1)
}
func TestResolver_Precompile_FHEOperations(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("FHEOperation", "fheop-1", map[string]interface{}{
"id": "fheop-1", "operation": "add", "gasUsed": 500000,
})
data := execOK(t, eng, `{ fheOperations(first: 10) { id } }`)
requireList(t, data, "fheOperations", 1)
}
func TestResolver_Precompile_ZKVerifications(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ZKVerification", "zkv-1", map[string]interface{}{
"id": "zkv-1", "proofSystem": "groth16", "verified": true,
})
data := execOK(t, eng, `{ zkVerifications(first: 10) { id } }`)
requireList(t, data, "zkVerifications", 1)
}
func TestResolver_Precompile_RingSignatures(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("RingSignature", "ring-1", map[string]interface{}{
"id": "ring-1", "ringSize": 8, "keyImage": "0xkeyimage",
})
data := execOK(t, eng, `{ ringSignatures(first: 10) { id } }`)
requireList(t, data, "ringSignatures", 1)
}
func TestResolver_Precompile_PQCryptoOps(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("PQCryptoOp", "pq-1", map[string]interface{}{
"id": "pq-1", "algorithm": "ML-DSA-65", "operation": "verify",
})
data := execOK(t, eng, `{ pqCryptoOps(first: 10) { id } }`)
requireList(t, data, "pqCryptoOps", 1)
}
func TestResolver_Precompile_ThresholdOps(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("ThresholdOp", "top-1", map[string]interface{}{
"id": "top-1", "protocol": "FROST", "participants": 5, "threshold": 3,
})
data := execOK(t, eng, `{ thresholdOps(first: 10) { id } }`)
requireList(t, data, "thresholdOps", 1)
}
func TestResolver_Precompile_WarpCalls(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("WarpCall", "wc-1", map[string]interface{}{
"id": "wc-1", "sourceChain": "C", "destChain": "Zoo", "messageID": "0xmsg",
})
data := execOK(t, eng, `{ warpCalls(first: 10) { id } }`)
requireList(t, data, "warpCalls", 1)
}
func TestResolver_Precompile_FHEACLGrants(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("FHEACLGrant", "acl-1", map[string]interface{}{
"id": "acl-1", "ciphertextID": "ct-1", "grantee": "0xabc",
})
data := execOK(t, eng, `{ fheACLGrants(first: 10) { id } }`)
requireList(t, data, "fheACLGrants", 1)
}
// ---------------------------------------------------------------------------
// 16. Stats resolvers — singleton stats for each chain
// ---------------------------------------------------------------------------
func TestResolver_Stats_All(t *testing.T) {
eng, store := newTestEngine(t)
store.SetEntity("BridgeStats", "1", map[string]interface{}{
"id": "1", "totalTransfers": 5000, "totalVolume": "10000000",
})
store.SetEntity("FHEStats", "1", map[string]interface{}{
"id": "1", "totalCeremonies": 100, "totalComputeJobs": 500,
})
store.SetEntity("OracleStats", "1", map[string]interface{}{
"id": "1", "totalFeeds": 50, "totalReports": 10000,
})
store.SetEntity("RelayStats", "1", map[string]interface{}{
"id": "1", "totalMessages": 2000, "totalRelayed": 1999,
})
store.SetEntity("ServiceStats", "1", map[string]interface{}{
"id": "1", "totalNodes": 100, "averageUptime": "99.95",
})
store.SetEntity("KeyStats", "1", map[string]interface{}{
"id": "1", "totalKeys": 500, "totalRotations": 50,
})
store.SetEntity("AIStats", "1", map[string]interface{}{
"id": "1", "totalInferences": 100000, "totalModels": 25,
})
store.SetEntity("IdentityStats", "1", map[string]interface{}{
"id": "1", "totalDIDs": 10000, "totalCredentials": 50000,
})
tests := []struct {
query string
key string
}{
{`{ bridgeStats { id totalTransfers } }`, "bridgeStats"},
{`{ fheStats { id totalCeremonies } }`, "fheStats"},
{`{ oracleStats { id totalFeeds } }`, "oracleStats"},
{`{ relayStats { id totalMessages } }`, "relayStats"},
{`{ serviceStats { id totalNodes } }`, "serviceStats"},
{`{ keyStats { id totalKeys } }`, "keyStats"},
{`{ aiStats { id totalInferences } }`, "aiStats"},
{`{ identityStats { id totalDIDs } }`, "identityStats"},
}
for _, tt := range tests {
t.Run(tt.key, func(t *testing.T) {
data := execOK(t, eng, tt.query)
m := requireMap(t, data, tt.key)
requireField(t, m, "id")
})
}
}
// ---------------------------------------------------------------------------
// 17. Error cases — missing ID, unknown field
// ---------------------------------------------------------------------------
func TestResolver_ErrorMissingID(t *testing.T) {
eng, _ := newTestEngine(t)
tests := []struct {
name string
query string
}{
{"order", `{ order { id } }`},
{"bridgeTransfer", `{ bridgeTransfer { id } }`},
{"validator", `{ validator { id } }`},
{"asset", `{ asset { id } }`},
{"shieldedTransfer", `{ shieldedTransfer { id } }`},
{"coronaSignature", `{ coronaSignature { id } }`},
{"managedKey", `{ managedKey { id } }`},
{"inferenceProof", `{ inferenceProof { id } }`},
{"did", `{ did { id } }`},
{"priceFeed", `{ priceFeed { id } }`},
{"warpMessage", `{ warpMessage { id } }`},
{"serviceNode", `{ serviceNode { id } }`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
msg := execErr(t, eng, tt.query)
if msg == "" {
t.Fatal("expected non-empty error message")
}
})
}
}
func TestResolver_UnknownField(t *testing.T) {
eng, _ := newTestEngine(t)
msg := execErr(t, eng, `{ nonexistentResolver(first: 10) { id } }`)
if msg == "" {
t.Fatal("expected error for unknown field")
}
}
// ---------------------------------------------------------------------------
// 18. Empty store returns empty lists, not errors
// ---------------------------------------------------------------------------
func TestResolver_EmptyStore_AllChains(t *testing.T) {
eng, _ := newTestEngine(t)
queries := []struct {
name string
query string
key string
}{
{"orders", `{ orders(first: 10) { id } }`, "orders"},
{"validators", `{ validators(first: 10) { id } }`, "validators"},
{"assets", `{ assets(first: 10) { id } }`, "assets"},
{"bridgeTransfers", `{ bridgeTransfers(first: 10) { id } }`, "bridgeTransfers"},
{"dkgCeremonies", `{ dkgCeremonies(first: 10) { id } }`, "dkgCeremonies"},
{"shieldedTransfers", `{ shieldedTransfers(first: 10) { id } }`, "shieldedTransfers"},
{"coronaSignatures", `{ coronaSignatures(first: 10) { id } }`, "coronaSignatures"},
{"managedKeys", `{ managedKeys(first: 10) { id } }`, "managedKeys"},
{"inferenceProofs", `{ inferenceProofs(first: 10) { id } }`, "inferenceProofs"},
{"dids", `{ dids(first: 10) { id } }`, "dids"},
{"priceFeeds", `{ priceFeeds(first: 10) { id } }`, "priceFeeds"},
{"warpMessages", `{ warpMessages(first: 10) { id } }`, "warpMessages"},
{"serviceNodes", `{ serviceNodes(first: 10) { id } }`, "serviceNodes"},
{"precompileCalls", `{ precompileCalls(first: 10) { id } }`, "precompileCalls"},
}
for _, tt := range queries {
t.Run(tt.name, func(t *testing.T) {
data := execOK(t, eng, tt.query)
// Either nil or empty slice is acceptable for empty store
if data[tt.key] == nil {
return
}
if list, ok := data[tt.key].([]interface{}); ok && len(list) > 0 {
t.Fatalf("expected empty list for %s, got %d items", tt.key, len(list))
}
})
}
}
// ---------------------------------------------------------------------------
// 19. First limit parameter works across all chain resolvers
// ---------------------------------------------------------------------------
func TestResolver_FirstLimitRespected(t *testing.T) {
eng, store := newTestEngine(t)
// Seed 5 orders
for i := 0; i < 5; i++ {
id := fmt.Sprintf("order-%d", i)
store.SetEntity("Order", id, map[string]interface{}{
"id": id, "market": "LUX/USD", "side": "buy", "price": "2.50",
})
}
data := execOK(t, eng, `{ orders(first: 2) { id } }`)
list := requireList(t, data, "orders", 1)
if len(list) > 2 {
t.Fatalf("first:2 should return <= 2 items, got %d", len(list))
}
}
// ---------------------------------------------------------------------------
// 20. Single entity lookup returns nil for nonexistent ID (no error)
// ---------------------------------------------------------------------------
func TestResolver_NonexistentEntity_ReturnsNil(t *testing.T) {
eng, _ := newTestEngine(t)
// These should return nil data for the field, not an error
data := execOK(t, eng, `{ validator(id: "NodeID-doesnotexist") { id } }`)
if data["validator"] != nil {
t.Errorf("expected nil for nonexistent validator, got %v", data["validator"])
}
data = execOK(t, eng, `{ bridgeTransfer(id: "nonexistent") { id } }`)
if data["bridgeTransfer"] != nil {
t.Errorf("expected nil for nonexistent bridgeTransfer, got %v", data["bridgeTransfer"])
}
}