Documentation
¶
Overview ¶
Package graphvm implements the Graph VM (G-Chain) — a shared GraphQL database across all Lux chains. Any chain's state is queryable through a unified GraphQL endpoint.
Index ¶
- Constants
- Variables
- type Block
- func (b *Block) Accept(context.Context) error
- func (b *Block) Bytes() []byte
- func (b *Block) Height() uint64
- func (b *Block) ID() ids.ID
- func (b *Block) Parent() ids.ID
- func (b *Block) ParentID() ids.ID
- func (b *Block) Reject(context.Context) error
- func (b *Block) Status() uint8
- func (b *Block) Timestamp() time.Time
- func (b *Block) Verify(context.Context) error
- type Bundle
- type Burn
- type DexFactory
- type Factory
- type GConfig
- type GraphQLError
- type GraphQLRequest
- type GraphQLResponse
- type Mint
- type Pair
- type PairDayData
- type Pool
- type PoolDayData
- type PoolHourData
- type QueryExecutor
- type ResolverFunc
- type Swap
- type Tick
- type Token
- type TokenDayData
- type TokenHourData
- type VM
- func (vm *VM) BuildBlock(ctx context.Context) (chain.Block, error)
- func (vm *VM) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersion *chain.VersionInfo) error
- func (vm *VM) CreateHandlers(context.Context) (map[string]http.Handler, error)
- func (vm *VM) CrossChainRequest(ctx context.Context, chainID ids.ID, requestID uint32, deadline time.Time, ...) error
- func (vm *VM) CrossChainRequestFailed(ctx context.Context, chainID ids.ID, requestID uint32, appErr *warp.Error) error
- func (vm *VM) CrossChainResponse(ctx context.Context, chainID ids.ID, requestID uint32, msg []byte) error
- func (vm *VM) Disconnected(ctx context.Context, nodeID ids.NodeID) error
- func (vm *VM) FeePolicy() fee.Policy
- func (vm *VM) GetBlock(ctx context.Context, blkID ids.ID) (chain.Block, error)
- func (vm *VM) GetBlockIDAtHeight(ctx context.Context, height uint64) (ids.ID, error)
- func (vm *VM) Gossip(ctx context.Context, nodeID ids.NodeID, msg []byte) error
- func (vm *VM) HealthCheck(context.Context) (chain.HealthResult, error)
- func (vm *VM) Initialize(ctx context.Context, vmInit vmcore.Init) error
- func (vm *VM) LastAccepted(context.Context) (ids.ID, error)
- func (vm *VM) NewHTTPHandler(ctx context.Context) (http.Handler, error)
- func (vm *VM) ParseBlock(ctx context.Context, blockBytes []byte) (chain.Block, error)
- func (vm *VM) Request(ctx context.Context, nodeID ids.NodeID, requestID uint32, deadline time.Time, ...) error
- func (vm *VM) RequestFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32, appErr *warp.Error) error
- func (vm *VM) Response(ctx context.Context, nodeID ids.NodeID, requestID uint32, response []byte) error
- func (vm *VM) SetPreference(ctx context.Context, blkID ids.ID) error
- func (vm *VM) SetState(ctx context.Context, state uint32) error
- func (vm *VM) Shutdown(context.Context) error
- func (vm *VM) Version(context.Context) (string, error)
- func (vm *VM) WaitForEvent(ctx context.Context) (vmcore.Message, error)
Constants ¶
const ( PrefixFactory = "dex:factory:" PrefixBundle = "dex:bundle:" PrefixToken = "dex:token:" PrefixPool = "dex:pool:" PrefixPair = "dex:pair:" PrefixTick = "dex:tick:" PrefixSwap = "dex:swap:" PrefixMint = "dex:mint:" PrefixBurn = "dex:burn:" PrefixTokenDay = "dex:tokenday:" PrefixTokenHour = "dex:tokenhour:" PrefixPoolDay = "dex:poolday:" PrefixPoolHour = "dex:poolhour:" PrefixPairDay = "dex:pairday:" PrefixDayData = "dex:daydata:" PrefixPoolByToken = "idx:pool:token:" )
Database key prefixes for DEX data. A record lives at "<prefix><id>"; the pool->token index lives at PrefixPoolByToken+<token>.
Variables ¶
var VMID = ids.ID{'g', 'r', 'a', 'p', 'h', 'v', 'm'}
VMID is the unique identifier for GraphVM (G-Chain)
var (
Version = &nodeversion.Semantic{
Major: 1,
Minor: 0,
Patch: 0,
}
)
Functions ¶
This section is empty.
Types ¶
type Block ¶
type Block struct {
// contains filtered or unexported fields
}
Block is the G-Chain's genesis block, which is the only block it has. Its fields are fixed at construction and it is accepted by definition, so there is no mutable status to keep in step with consensus.
func (*Block) Accept ¶
Accept implements the chain.Block interface. Genesis is already the accepted frontier, so accepting it changes nothing; accepting anything else would move the frontier to a block GetBlock cannot return, which is the shape that leaves a node unable to boot.
func (*Block) Bytes ¶
Bytes implements the block.Block interface. It returns the deterministic canonical encoding set at construction; the block ID is the SHA-256 of exactly these bytes, so ParseBlock(b.Bytes()).ID() == b.ID().
func (*Block) Reject ¶
Reject implements the chain.Block interface. The frontier is the only block there is, and rejecting it would leave the chain without one.
func (*Block) Status ¶
Status implements the block.Block interface. The interface requires a concrete uint8; choices.Status is `type Status uint8`, so a method returning the named type would NOT satisfy block.Block — which is why GetBlock could never have returned a *Block before this fix.
type Bundle ¶
type Bundle struct {
ID string `json:"id"`
EthPriceUSD string `json:"ethPriceUSD"`
EthPrice string `json:"ethPrice"` // v2 compat (same as ethPriceUSD)
LuxPriceUSD string `json:"luxPriceUSD"` // native token price
}
Bundle represents ETH/native price in USD
type Burn ¶
type Burn struct {
ID string `json:"id"`
Transaction string `json:"transaction"`
Timestamp int64 `json:"timestamp"`
Pool string `json:"pool"`
Pair string `json:"pair"` // v2 compat
Token0 string `json:"token0"`
Token1 string `json:"token1"`
Owner string `json:"owner"`
Origin string `json:"origin"`
Amount string `json:"amount"`
Amount0 string `json:"amount0"`
Amount1 string `json:"amount1"`
AmountUSD string `json:"amountUSD"`
TickLower int64 `json:"tickLower"` // v3
TickUpper int64 `json:"tickUpper"` // v3
Liquidity string `json:"liquidity"` // v2
LogIndex int64 `json:"logIndex"`
}
Burn represents a liquidity remove event
type DexFactory ¶
type DexFactory struct {
ID string `json:"id"`
PoolCount int64 `json:"poolCount"`
PairCount int64 `json:"pairCount"` // v2 compat
TxCount int64 `json:"txCount"`
TotalVolumeUSD string `json:"totalVolumeUSD"`
TotalVolumeETH string `json:"totalVolumeETH"`
TotalFeesUSD string `json:"totalFeesUSD"`
TotalValueLockedUSD string `json:"totalValueLockedUSD"`
TotalLiquidityUSD string `json:"totalLiquidityUSD"` // v2 compat
TotalValueLockedETH string `json:"totalValueLockedETH"`
}
DexFactory represents DEX factory stats (Uniswap-compatible)
type GConfig ¶
type GConfig struct {
// Query bounds
MaxQueryDepth int `json:"maxQueryDepth"`
QueryTimeoutMs int `json:"queryTimeoutMs"`
MaxResultSize int `json:"maxResultSize"`
// Authentication
RequireAuth bool `json:"requireAuth"`
APIKeys []string `json:"apiKeys"`
}
GConfig contains VM configuration. Every field here is read; a knob that changes nothing is worse than no knob, because it reads as a control.
type GraphQLError ¶
type GraphQLError struct {
Message string `json:"message"`
}
GraphQLError represents a GraphQL error
type GraphQLRequest ¶
type GraphQLRequest struct {
Query string `json:"query"`
OperationName string `json:"operationName,omitempty"`
Variables map[string]interface{} `json:"variables,omitempty"`
}
GraphQLRequest represents an incoming GraphQL request
type GraphQLResponse ¶
type GraphQLResponse struct {
Data interface{} `json:"data,omitempty"`
Errors []GraphQLError `json:"errors,omitempty"`
}
GraphQLResponse represents a GraphQL response
type Mint ¶
type Mint struct {
ID string `json:"id"`
Transaction string `json:"transaction"`
Timestamp int64 `json:"timestamp"`
Pool string `json:"pool"`
Pair string `json:"pair"` // v2 compat
Token0 string `json:"token0"`
Token1 string `json:"token1"`
Owner string `json:"owner"`
Sender string `json:"sender"`
Origin string `json:"origin"`
Amount string `json:"amount"` // liquidity amount
Amount0 string `json:"amount0"`
Amount1 string `json:"amount1"`
AmountUSD string `json:"amountUSD"`
TickLower int64 `json:"tickLower"` // v3
TickUpper int64 `json:"tickUpper"` // v3
Liquidity string `json:"liquidity"` // v2
LogIndex int64 `json:"logIndex"`
}
Mint represents a liquidity add event
type Pair ¶
type Pair struct {
ID string `json:"id"` // address
Token0 *Token `json:"token0"`
Token1 *Token `json:"token1"`
Reserve0 string `json:"reserve0"`
Reserve1 string `json:"reserve1"`
TotalSupply string `json:"totalSupply"`
ReserveETH string `json:"reserveETH"`
ReserveUSD string `json:"reserveUSD"`
TrackedReserveETH string `json:"trackedReserveETH"`
Token0Price string `json:"token0Price"`
Token1Price string `json:"token1Price"`
VolumeToken0 string `json:"volumeToken0"`
VolumeToken1 string `json:"volumeToken1"`
VolumeUSD string `json:"volumeUSD"`
TxCount int64 `json:"txCount"`
CreatedAtTimestamp int64 `json:"createdAtTimestamp"`
CreatedAtBlockNumber int64 `json:"createdAtBlockNumber"`
}
Pair represents a v2-style constant product AMM pair
type PairDayData ¶
type PairDayData struct {
ID string `json:"id"`
Date int64 `json:"date"`
PairAddress string `json:"pairAddress"`
Token0 string `json:"token0"`
Token1 string `json:"token1"`
Reserve0 string `json:"reserve0"`
Reserve1 string `json:"reserve1"`
TotalSupply string `json:"totalSupply"`
ReserveUSD string `json:"reserveUSD"`
DailyVolumeToken0 string `json:"dailyVolumeToken0"`
DailyVolumeToken1 string `json:"dailyVolumeToken1"`
DailyVolumeUSD string `json:"dailyVolumeUSD"`
DailyTxns int64 `json:"dailyTxns"`
}
PairDayData represents daily v2 pair stats
type Pool ¶
type Pool struct {
ID string `json:"id"` // address
CreatedAtTimestamp int64 `json:"createdAtTimestamp"`
CreatedAtBlockNumber int64 `json:"createdAtBlockNumber"`
Token0 *Token `json:"token0"`
Token1 *Token `json:"token1"`
FeeTier int64 `json:"feeTier"`
Liquidity string `json:"liquidity"`
SqrtPrice string `json:"sqrtPrice"`
Token0Price string `json:"token0Price"`
Token1Price string `json:"token1Price"`
Tick int64 `json:"tick"`
ObservationIndex int64 `json:"observationIndex"`
VolumeToken0 string `json:"volumeToken0"`
VolumeToken1 string `json:"volumeToken1"`
VolumeUSD string `json:"volumeUSD"`
FeesUSD string `json:"feesUSD"`
TxCount int64 `json:"txCount"`
TotalValueLockedToken0 string `json:"totalValueLockedToken0"`
TotalValueLockedToken1 string `json:"totalValueLockedToken1"`
TotalValueLockedETH string `json:"totalValueLockedETH"`
TotalValueLockedUSD string `json:"totalValueLockedUSD"`
}
Pool represents a v3-style concentrated liquidity pool
type PoolDayData ¶
type PoolDayData struct {
ID string `json:"id"`
Date int64 `json:"date"`
Pool string `json:"pool"`
Liquidity string `json:"liquidity"`
SqrtPrice string `json:"sqrtPrice"`
Token0Price string `json:"token0Price"`
Token1Price string `json:"token1Price"`
Tick int64 `json:"tick"`
TvlUSD string `json:"tvlUSD"`
VolumeToken0 string `json:"volumeToken0"`
VolumeToken1 string `json:"volumeToken1"`
VolumeUSD string `json:"volumeUSD"`
FeesUSD string `json:"feesUSD"`
TxCount int64 `json:"txCount"`
Open string `json:"open"`
High string `json:"high"`
Low string `json:"low"`
Close string `json:"close"`
}
PoolDayData represents daily pool stats
type PoolHourData ¶
type PoolHourData struct {
ID string `json:"id"`
PeriodStartUnix int64 `json:"periodStartUnix"`
Pool string `json:"pool"`
Liquidity string `json:"liquidity"`
SqrtPrice string `json:"sqrtPrice"`
Token0Price string `json:"token0Price"`
Token1Price string `json:"token1Price"`
Tick int64 `json:"tick"`
TvlUSD string `json:"tvlUSD"`
VolumeToken0 string `json:"volumeToken0"`
VolumeToken1 string `json:"volumeToken1"`
VolumeUSD string `json:"volumeUSD"`
FeesUSD string `json:"feesUSD"`
TxCount int64 `json:"txCount"`
Open string `json:"open"`
High string `json:"high"`
Low string `json:"low"`
Close string `json:"close"`
}
PoolHourData represents hourly pool stats
type QueryExecutor ¶
type QueryExecutor struct {
// contains filtered or unexported fields
}
QueryExecutor executes GraphQL queries against the shared database. Its resolver table is built once in NewQueryExecutor and read-only thereafter, so concurrent requests need no lock.
func NewQueryExecutor ¶
func NewQueryExecutor(db database.Database, config *GConfig) *QueryExecutor
NewQueryExecutor creates a new GraphQL query executor
func (*QueryExecutor) Execute ¶
func (e *QueryExecutor) Execute(ctx context.Context, req *GraphQLRequest) *GraphQLResponse
Execute executes a GraphQL query
type ResolverFunc ¶
type ResolverFunc func(ctx context.Context, db database.Database, args map[string]interface{}) (interface{}, error)
ResolverFunc resolves a field from the database. What it returns must be JSON-encodable: the response is measured and sent by encoding it.
type Swap ¶
type Swap struct {
ID string `json:"id"` // txHash#logIndex
Transaction string `json:"transaction"`
Timestamp int64 `json:"timestamp"`
Pool string `json:"pool"`
Pair string `json:"pair"` // v2 compat
Token0 string `json:"token0"`
Token1 string `json:"token1"`
Sender string `json:"sender"`
Recipient string `json:"recipient"`
Origin string `json:"origin"`
Amount0 string `json:"amount0"`
Amount1 string `json:"amount1"`
Amount0In string `json:"amount0In"` // v2
Amount0Out string `json:"amount0Out"` // v2
Amount1In string `json:"amount1In"` // v2
Amount1Out string `json:"amount1Out"` // v2
AmountUSD string `json:"amountUSD"`
SqrtPriceX96 string `json:"sqrtPriceX96"` // v3
Tick int64 `json:"tick"` // v3
LogIndex int64 `json:"logIndex"`
}
Swap represents a swap event
type Tick ¶
type Tick struct {
ID string `json:"id"` // pool#tickIdx
PoolAddress string `json:"poolAddress"`
TickIdx int64 `json:"tickIdx"`
LiquidityGross string `json:"liquidityGross"`
LiquidityNet string `json:"liquidityNet"`
Price0 string `json:"price0"`
Price1 string `json:"price1"`
CreatedAtTimestamp int64 `json:"createdAtTimestamp"`
CreatedAtBlockNumber int64 `json:"createdAtBlockNumber"`
}
Tick represents liquidity at a specific price tick (v3)
type Token ¶
type Token struct {
ID string `json:"id"` // address
Symbol string `json:"symbol"`
Name string `json:"name"`
Decimals int64 `json:"decimals"`
TotalSupply string `json:"totalSupply"`
Volume string `json:"volume"`
VolumeUSD string `json:"volumeUSD"`
UntrackedVolumeUSD string `json:"untrackedVolumeUSD"`
FeesUSD string `json:"feesUSD"`
TxCount int64 `json:"txCount"`
PoolCount int64 `json:"poolCount"`
TotalValueLocked string `json:"totalValueLocked"`
TotalValueLockedUSD string `json:"totalValueLockedUSD"`
TotalLiquidity string `json:"totalLiquidity"` // v2 compat
DerivedETH string `json:"derivedETH"`
DerivedLUX string `json:"derivedLUX"` // native token derived price
TradeVolume string `json:"tradeVolume"` // v2 compat
TradeVolumeUSD string `json:"tradeVolumeUSD"` // v2 compat
}
Token represents ERC20 token metadata and stats
type TokenDayData ¶
type TokenDayData struct {
ID string `json:"id"` // tokenAddr-timestamp
Date int64 `json:"date"`
Token string `json:"token"`
Volume string `json:"volume"`
VolumeUSD string `json:"volumeUSD"`
TotalValueLocked string `json:"totalValueLocked"`
TotalValueLockedUSD string `json:"totalValueLockedUSD"`
PriceUSD string `json:"priceUSD"`
FeesUSD string `json:"feesUSD"`
Open string `json:"open"`
High string `json:"high"`
Low string `json:"low"`
Close string `json:"close"`
}
TokenDayData represents daily token stats
type TokenHourData ¶
type TokenHourData struct {
ID string `json:"id"`
PeriodStartUnix int64 `json:"periodStartUnix"`
Token string `json:"token"`
Volume string `json:"volume"`
VolumeUSD string `json:"volumeUSD"`
TotalValueLocked string `json:"totalValueLocked"`
TotalValueLockedUSD string `json:"totalValueLockedUSD"`
PriceUSD string `json:"priceUSD"`
FeesUSD string `json:"feesUSD"`
Open string `json:"open"`
High string `json:"high"`
Low string `json:"low"`
Close string `json:"close"`
}
TokenHourData represents hourly token stats
type VM ¶
type VM struct {
// contains filtered or unexported fields
}
VM implements the chain.ChainVM interface for the Graph Chain (G-Chain)
func (*VM) BuildBlock ¶
BuildBlock implements the chain.ChainVM interface, by declining. See errReadOnlyChain.
func (*VM) Connected ¶
func (vm *VM) Connected(ctx context.Context, nodeID ids.NodeID, nodeVersion *chain.VersionInfo) error
Connected implements the validators.Connector interface
func (*VM) CreateHandlers ¶
CreateHandlers implements the common.VM interface.
The node mounts each key under /v1/bc/<chainID> and matches that full path EXACTLY, then hands the handler the request with the path it arrived on. A handler that dispatches on r.URL.Path therefore never recognizes anything. The key IS the route; one handler per key.
func (*VM) CrossChainRequest ¶
func (vm *VM) CrossChainRequest(ctx context.Context, chainID ids.ID, requestID uint32, deadline time.Time, msg []byte) error
CrossChainRequest implements the common.VM interface
func (*VM) CrossChainRequestFailed ¶
func (vm *VM) CrossChainRequestFailed(ctx context.Context, chainID ids.ID, requestID uint32, appErr *warp.Error) error
CrossChainRequestFailed implements the common.VM interface
func (*VM) CrossChainResponse ¶
func (vm *VM) CrossChainResponse(ctx context.Context, chainID ids.ID, requestID uint32, msg []byte) error
CrossChainResponse implements the common.VM interface
func (*VM) Disconnected ¶
Disconnected implements the validators.Connector interface
func (*VM) FeePolicy ¶ added in v1.2.6
FeePolicy exposes the chain's declared fee policy for diagnostics and the boot-time Validate gate.
func (*VM) GetBlock ¶
GetBlock implements the chain.ChainVM interface. The G-Chain has exactly one block — genesis — which is permanently the accepted frontier; any other ID is unknown. Returning database.ErrNotFound (not a "not implemented") lets the ZAP VM server map a genuine miss to the wire NotFound code.
func (*VM) GetBlockIDAtHeight ¶
GetBlockIDAtHeight implements the chain.ChainVM interface. Genesis (height 0) is the only block; every other height is absent.
func (*VM) HealthCheck ¶
HealthCheck implements the health.Checker interface
func (*VM) Initialize ¶
Initialize implements the common.VM interface
func (*VM) LastAccepted ¶
LastAccepted implements the chain.ChainVM interface.
func (*VM) NewHTTPHandler ¶
NewHTTPHandler returns the same one route, mounted by path.
func (*VM) ParseBlock ¶
ParseBlock implements the chain.ChainVM interface. The only block this chain has is genesis, so those are the only bytes that name a block of it: anything else is refused here rather than admitted, verified, accepted, and then found unresolvable by the next node that boots.
func (*VM) Request ¶
func (vm *VM) Request(ctx context.Context, nodeID ids.NodeID, requestID uint32, deadline time.Time, request []byte) error
Request implements the common.AppHandler interface
func (*VM) RequestFailed ¶
func (vm *VM) RequestFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32, appErr *warp.Error) error
RequestFailed implements the common.AppHandler interface
func (*VM) Response ¶
func (vm *VM) Response(ctx context.Context, nodeID ids.NodeID, requestID uint32, response []byte) error
Response implements the common.AppHandler interface
func (*VM) SetPreference ¶
SetPreference implements the chain.ChainVM interface. Preferring a block this chain does not have is a caller error, not a value to store.
func (*VM) WaitForEvent ¶
WaitForEvent waits out the context and reports nothing, because this chain has nothing to report: it never builds a block, so there is never news of one to send. A latch here would wake a builder that declines, which is why this is not the frozen WaitForEvent the other chains had — those had work and no way to say so. See errReadOnlyChain.