forked from cerc-io/laconicd-deprecated
add gql
This commit is contained in:
+353
@@ -0,0 +1,353 @@
|
||||
# Cerc-io laconic gql
|
||||
|
||||
> Browser : http://localhost:9473 for gql
|
||||
|
||||
## Start server
|
||||
|
||||
```shell
|
||||
./build/laconicd start --gql-playground --gql-server
|
||||
```
|
||||
|
||||
Basic node status:
|
||||
|
||||
```graphql
|
||||
{
|
||||
getStatus {
|
||||
version
|
||||
node {
|
||||
id
|
||||
network
|
||||
moniker
|
||||
}
|
||||
sync {
|
||||
latest_block_height
|
||||
catching_up
|
||||
}
|
||||
num_peers
|
||||
peers {
|
||||
is_outbound
|
||||
remote_ip
|
||||
}
|
||||
disk_usage
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Full node status:
|
||||
|
||||
```graphql
|
||||
{
|
||||
getStatus {
|
||||
version
|
||||
node {
|
||||
id
|
||||
network
|
||||
moniker
|
||||
}
|
||||
sync {
|
||||
latest_block_hash
|
||||
latest_block_time
|
||||
latest_block_height
|
||||
catching_up
|
||||
}
|
||||
validator {
|
||||
address
|
||||
voting_power
|
||||
proposer_priority
|
||||
}
|
||||
validators {
|
||||
address
|
||||
voting_power
|
||||
proposer_priority
|
||||
}
|
||||
num_peers
|
||||
peers {
|
||||
node {
|
||||
id
|
||||
network
|
||||
moniker
|
||||
}
|
||||
is_outbound
|
||||
remote_ip
|
||||
}
|
||||
disk_usage
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Get records by IDs.
|
||||
|
||||
```graphql
|
||||
{
|
||||
getRecordsByIds(ids: ["QmYDtNCKtTu6u6jaHaFAC5PWZXcj7fAmry6NoWwMaixFHz"]) {
|
||||
id
|
||||
names
|
||||
bondId
|
||||
createTime
|
||||
expiryTime
|
||||
owners
|
||||
attributes {
|
||||
key
|
||||
value {
|
||||
string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Query records.
|
||||
|
||||
```graphql
|
||||
{
|
||||
queryRecords(attributes: [{ key: "type", value: { string: "crn:bot" } }]) {
|
||||
id
|
||||
names
|
||||
bondId
|
||||
createTime
|
||||
expiryTime
|
||||
owners
|
||||
attributes {
|
||||
key
|
||||
value {
|
||||
string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Get account details:
|
||||
|
||||
```graphql
|
||||
{
|
||||
getAccounts(addresses: ["cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094"]) {
|
||||
address
|
||||
pubKey
|
||||
number
|
||||
sequence
|
||||
balance {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Query bonds:
|
||||
|
||||
```graphql
|
||||
{
|
||||
queryBonds(
|
||||
attributes: [
|
||||
{
|
||||
key: "owner"
|
||||
value: { string: "cosmos1wh8vvd0ymc5nt37h29z8kk2g2ays45ct2qu094" }
|
||||
}
|
||||
]
|
||||
) {
|
||||
id
|
||||
owner
|
||||
balance {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Get bonds by IDs.
|
||||
|
||||
```graphql
|
||||
{
|
||||
getBondsByIds(
|
||||
ids: [
|
||||
"1c2b677cb2a27c88cc6bf8acf675c94b69051125b40c4fd073153b10f046dd87"
|
||||
"c3f7a78c5042d2003880962ba31ff3b01fcf5942960e0bc3ca331f816346a440"
|
||||
]
|
||||
) {
|
||||
id
|
||||
owner
|
||||
balance {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Query Bonds by Owner
|
||||
|
||||
```graphql
|
||||
{
|
||||
queryBondsByOwner(
|
||||
ownerAddresses: ["ethm1mfdjngh5jvjs9lqtt9a7y2hlgw8v3syh3hsqzk"]
|
||||
) {
|
||||
owner
|
||||
bonds {
|
||||
id
|
||||
owner
|
||||
balance {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Query auctions by ids
|
||||
|
||||
```graphql
|
||||
{
|
||||
getAuctionsByIds(
|
||||
ids: ["be98f2073c246194276554eefdb4c95b682a35a0f06fbe619a6da57c10c93e90"]
|
||||
) {
|
||||
id
|
||||
ownerAddress
|
||||
createTime
|
||||
minimumBid {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
commitFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
commitsEndTime
|
||||
revealFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
revealsEndTime
|
||||
winnerBid {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
winnerPrice {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
winnerAddress
|
||||
bids {
|
||||
bidderAddress
|
||||
commitHash
|
||||
commitTime
|
||||
commitFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
revealFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
revealTime
|
||||
bidAmount {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
status
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
LookUp Authorities
|
||||
|
||||
```graphql
|
||||
{
|
||||
lookupAuthorities(names: []) {
|
||||
ownerAddress
|
||||
ownerAddress
|
||||
height
|
||||
bondId
|
||||
status
|
||||
expiryTime
|
||||
auction {
|
||||
id
|
||||
ownerAddress
|
||||
createTime
|
||||
minimumBid {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
commitFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
commitsEndTime
|
||||
revealFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
revealsEndTime
|
||||
winnerBid {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
winnerPrice {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
winnerAddress
|
||||
bids {
|
||||
bidderAddress
|
||||
commitHash
|
||||
commitTime
|
||||
commitFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
revealFee {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
revealTime
|
||||
bidAmount {
|
||||
type
|
||||
quantity
|
||||
}
|
||||
status
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
LookUp Names
|
||||
|
||||
```graphql
|
||||
{
|
||||
lookupNames(names: ["crn://hello/test"]) {
|
||||
latest {
|
||||
id
|
||||
height
|
||||
}
|
||||
history {
|
||||
id
|
||||
height
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Resolve Names
|
||||
|
||||
```graphql
|
||||
{
|
||||
resolveNames(names: ["asd"]) {
|
||||
id
|
||||
names
|
||||
bondId
|
||||
createTime
|
||||
expiryTime
|
||||
owners
|
||||
attributes {
|
||||
key
|
||||
value {
|
||||
string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
+8781
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
# .gqlgen.yml example
|
||||
#
|
||||
# Refer to https://gqlgen.com/config/
|
||||
# for detailed .gqlgen.yml documentation.
|
||||
|
||||
schema:
|
||||
- cerc-io/laconicd/*.graphql
|
||||
exec:
|
||||
filename: generated.go
|
||||
model:
|
||||
filename: models_gen.go
|
||||
resolver:
|
||||
filename: resolver.go
|
||||
type: Resolver
|
||||
@@ -0,0 +1,160 @@
|
||||
// Code generated by github.com/99designs/gqlgen, DO NOT EDIT.
|
||||
|
||||
package gql
|
||||
|
||||
type Account struct {
|
||||
Address string `json:"address"`
|
||||
PubKey *string `json:"pubKey"`
|
||||
Number string `json:"number"`
|
||||
Sequence string `json:"sequence"`
|
||||
Balance []*Coin `json:"balance"`
|
||||
}
|
||||
|
||||
type Auction struct {
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
OwnerAddress string `json:"ownerAddress"`
|
||||
CreateTime string `json:"createTime"`
|
||||
CommitsEndTime string `json:"commitsEndTime"`
|
||||
RevealsEndTime string `json:"revealsEndTime"`
|
||||
CommitFee *Coin `json:"commitFee"`
|
||||
RevealFee *Coin `json:"revealFee"`
|
||||
MinimumBid *Coin `json:"minimumBid"`
|
||||
WinnerAddress string `json:"winnerAddress"`
|
||||
WinnerBid *Coin `json:"winnerBid"`
|
||||
WinnerPrice *Coin `json:"winnerPrice"`
|
||||
Bids []*AuctionBid `json:"bids"`
|
||||
}
|
||||
|
||||
type AuctionBid struct {
|
||||
BidderAddress string `json:"bidderAddress"`
|
||||
Status string `json:"status"`
|
||||
CommitHash string `json:"commitHash"`
|
||||
CommitTime string `json:"commitTime"`
|
||||
CommitFee *Coin `json:"commitFee"`
|
||||
RevealTime string `json:"revealTime"`
|
||||
RevealFee *Coin `json:"revealFee"`
|
||||
BidAmount *Coin `json:"bidAmount"`
|
||||
}
|
||||
|
||||
type AuthorityRecord struct {
|
||||
OwnerAddress string `json:"ownerAddress"`
|
||||
OwnerPublicKey string `json:"ownerPublicKey"`
|
||||
Height string `json:"height"`
|
||||
Status string `json:"status"`
|
||||
BondID string `json:"bondId"`
|
||||
ExpiryTime string `json:"expiryTime"`
|
||||
Auction *Auction `json:"auction"`
|
||||
}
|
||||
|
||||
type Bond struct {
|
||||
ID string `json:"id"`
|
||||
Owner string `json:"owner"`
|
||||
Balance []*Coin `json:"balance"`
|
||||
}
|
||||
|
||||
type Coin struct {
|
||||
Type string `json:"type"`
|
||||
Quantity string `json:"quantity"`
|
||||
}
|
||||
|
||||
type KeyValue struct {
|
||||
Key string `json:"key"`
|
||||
Value *Value `json:"value"`
|
||||
}
|
||||
|
||||
type KeyValueInput struct {
|
||||
Key string `json:"key"`
|
||||
Value *ValueInput `json:"value"`
|
||||
}
|
||||
|
||||
type NameRecord struct {
|
||||
Latest *NameRecordEntry `json:"latest"`
|
||||
History []*NameRecordEntry `json:"history"`
|
||||
}
|
||||
|
||||
type NameRecordEntry struct {
|
||||
ID string `json:"id"`
|
||||
Height string `json:"height"`
|
||||
}
|
||||
|
||||
type NodeInfo struct {
|
||||
ID string `json:"id"`
|
||||
Network string `json:"network"`
|
||||
Moniker string `json:"moniker"`
|
||||
}
|
||||
|
||||
type OwnerBonds struct {
|
||||
Owner string `json:"owner"`
|
||||
Bonds []*Bond `json:"bonds"`
|
||||
}
|
||||
|
||||
type PeerInfo struct {
|
||||
Node *NodeInfo `json:"node"`
|
||||
IsOutbound bool `json:"is_outbound"`
|
||||
RemoteIP string `json:"remote_ip"`
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
ID string `json:"id"`
|
||||
Names []string `json:"names"`
|
||||
BondID string `json:"bondId"`
|
||||
CreateTime string `json:"createTime"`
|
||||
ExpiryTime string `json:"expiryTime"`
|
||||
Owners []string `json:"owners"`
|
||||
Attributes []*KeyValue `json:"attributes"`
|
||||
References []*Record `json:"references"`
|
||||
}
|
||||
|
||||
type Reference struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type ReferenceInput struct {
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
type Status struct {
|
||||
Version string `json:"version"`
|
||||
Node *NodeInfo `json:"node"`
|
||||
Sync *SyncInfo `json:"sync"`
|
||||
Validator *ValidatorInfo `json:"validator"`
|
||||
Validators []*ValidatorInfo `json:"validators"`
|
||||
NumPeers string `json:"num_peers"`
|
||||
Peers []*PeerInfo `json:"peers"`
|
||||
DiskUsage string `json:"disk_usage"`
|
||||
}
|
||||
|
||||
type SyncInfo struct {
|
||||
LatestBlockHash string `json:"latest_block_hash"`
|
||||
LatestBlockHeight string `json:"latest_block_height"`
|
||||
LatestBlockTime string `json:"latest_block_time"`
|
||||
CatchingUp bool `json:"catching_up"`
|
||||
}
|
||||
|
||||
type ValidatorInfo struct {
|
||||
Address string `json:"address"`
|
||||
VotingPower string `json:"voting_power"`
|
||||
ProposerPriority *string `json:"proposer_priority"`
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
Null *bool `json:"null"`
|
||||
Int *int `json:"int"`
|
||||
Float *float64 `json:"float"`
|
||||
String *string `json:"string"`
|
||||
Boolean *bool `json:"boolean"`
|
||||
JSON *string `json:"json"`
|
||||
Reference *Reference `json:"reference"`
|
||||
Values []*Value `json:"values"`
|
||||
}
|
||||
|
||||
type ValueInput struct {
|
||||
Null *bool `json:"null"`
|
||||
Int *int `json:"int"`
|
||||
Float *float64 `json:"float"`
|
||||
String *string `json:"string"`
|
||||
Boolean *bool `json:"boolean"`
|
||||
Reference *ReferenceInput `json:"reference"`
|
||||
Values []*ValueInput `json:"values"`
|
||||
}
|
||||
+348
@@ -0,0 +1,348 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"strconv"
|
||||
|
||||
auctiontypes "github.com/cerc-io/laconicd/x/auction/types"
|
||||
bondtypes "github.com/cerc-io/laconicd/x/bond/types"
|
||||
nstypes "github.com/cerc-io/laconicd/x/nameservice/types"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
// DefaultLogNumLines is the number of log lines to tail by default.
|
||||
const DefaultLogNumLines = 50
|
||||
|
||||
// MaxLogNumLines is the max number of log lines that can be tailed.
|
||||
const MaxLogNumLines = 1000
|
||||
|
||||
type Resolver struct {
|
||||
ctx client.Context
|
||||
logFile string
|
||||
}
|
||||
|
||||
// Query is the entry point to query execution.
|
||||
func (r *Resolver) Query() QueryResolver {
|
||||
return &queryResolver{r}
|
||||
}
|
||||
|
||||
type queryResolver struct{ *Resolver }
|
||||
|
||||
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*AuthorityRecord, error) {
|
||||
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*AuthorityRecord
|
||||
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.Whois(context.Background(), &nstypes.QueryWhoisRequest{Name: name})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nameAuthority := res.GetNameAuthority()
|
||||
gqlNameAuthorityRecord, err := GetGQLNameAuthorityRecord(&nameAuthority)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if nameAuthority.AuctionId != "" {
|
||||
auctionResp, err := auctionQueryClient.GetAuction(context.Background(), &auctiontypes.AuctionRequest{Id: nameAuthority.GetAuctionId()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bidsResp, err := auctionQueryClient.GetBids(context.Background(), &auctiontypes.BidsRequest{AuctionId: nameAuthority.GetAuctionId()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlAuctionRecord, err := GetGQLAuction(auctionResp.GetAuction(), bidsResp.GetBids())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlNameAuthorityRecord.Auction = gqlAuctionRecord
|
||||
}
|
||||
|
||||
gqlResponse = append(gqlResponse, gqlNameAuthorityRecord)
|
||||
}
|
||||
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*Record, error) {
|
||||
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*Record
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.ResolveCrn(context.Background(), &nstypes.QueryResolveCrn{Crn: name})
|
||||
if err != nil {
|
||||
// Return nil for record not found.
|
||||
gqlResponse = append(gqlResponse, nil)
|
||||
} else {
|
||||
gqlRecord, err := getGQLRecord(context.Background(), q, *res.GetRecord())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlResponse = append(gqlResponse, gqlRecord)
|
||||
}
|
||||
}
|
||||
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) LookupNames(ctx context.Context, names []string) ([]*NameRecord, error) {
|
||||
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||
var gqlResponse []*NameRecord
|
||||
|
||||
for _, name := range names {
|
||||
res, err := nsQueryClient.LookupCrn(context.Background(), &nstypes.QueryLookupCrn{Crn: name})
|
||||
if err != nil {
|
||||
// Return nil for name not found.
|
||||
gqlResponse = append(gqlResponse, nil)
|
||||
} else {
|
||||
gqlRecord, err := getGQLNameRecord(res.GetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlResponse = append(gqlResponse, gqlRecord)
|
||||
}
|
||||
}
|
||||
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) QueryRecords(ctx context.Context, attributes []*KeyValueInput, all *bool) ([]*Record, error) {
|
||||
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||
|
||||
res, err := nsQueryClient.ListRecords(
|
||||
context.Background(),
|
||||
&nstypes.QueryListRecordsRequest{
|
||||
Attributes: parseRequestAttributes(attributes),
|
||||
All: (all != nil && *all),
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
records := res.GetRecords()
|
||||
gqlResponse := make([]*Record, len(records))
|
||||
|
||||
for i, record := range records {
|
||||
gqlRecord, err := getGQLRecord(context.Background(), q, record)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gqlResponse[i] = gqlRecord
|
||||
}
|
||||
|
||||
return gqlResponse, nil
|
||||
|
||||
}
|
||||
|
||||
func (q queryResolver) GetRecordsByIds(ctx context.Context, ids []string) ([]*Record, error) {
|
||||
nsQueryClient := nstypes.NewQueryClient(q.ctx)
|
||||
gqlResponse := make([]*Record, len(ids))
|
||||
|
||||
for i, id := range ids {
|
||||
res, err := nsQueryClient.GetRecord(context.Background(), &nstypes.QueryRecordByIdRequest{Id: id})
|
||||
if err != nil {
|
||||
// Return nil for record not found.
|
||||
gqlResponse[i] = nil
|
||||
} else {
|
||||
record, err := getGQLRecord(context.Background(), q, res.GetRecord())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gqlResponse[i] = record
|
||||
}
|
||||
}
|
||||
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetStatus(ctx context.Context) (*Status, error) {
|
||||
nodeInfo, syncInfo, validatorInfo, err := getStatusInfo(q.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
numPeers, peers, err := getNetInfo(q.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
validatorSet, err := getValidatorSet(q.ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
diskUsage, err := GetDiskUsage(NodeDataPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Status{
|
||||
Version: NameServiceVersion,
|
||||
Node: nodeInfo,
|
||||
Sync: syncInfo,
|
||||
Validator: validatorInfo,
|
||||
Validators: validatorSet,
|
||||
NumPeers: numPeers,
|
||||
Peers: peers,
|
||||
DiskUsage: diskUsage,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAccounts(ctx context.Context, addresses []string) ([]*Account, error) {
|
||||
accounts := make([]*Account, len(addresses))
|
||||
for index, address := range addresses {
|
||||
account, err := q.GetAccount(ctx, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
accounts[index] = account
|
||||
}
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAccount(ctx context.Context, address string) (*Account, error) {
|
||||
authQueryClient := authtypes.NewQueryClient(q.ctx)
|
||||
accountResponse, err := authQueryClient.Account(ctx, &authtypes.QueryAccountRequest{Address: address})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var account authtypes.AccountI
|
||||
err = q.ctx.Codec.UnpackAny(accountResponse.GetAccount(), &account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var pubKey *string
|
||||
if account.GetPubKey() != nil {
|
||||
pubKeyStr := base64.StdEncoding.EncodeToString(account.GetPubKey().Bytes())
|
||||
pubKey = &pubKeyStr
|
||||
}
|
||||
|
||||
// Get the account balance
|
||||
bankQueryClient := banktypes.NewQueryClient(q.ctx)
|
||||
balance, err := bankQueryClient.AllBalances(ctx, &banktypes.QueryAllBalancesRequest{Address: address})
|
||||
|
||||
accNum := strconv.FormatUint(account.GetAccountNumber(), 10)
|
||||
seq := strconv.FormatUint(account.GetSequence(), 10)
|
||||
|
||||
return &Account{
|
||||
Address: address,
|
||||
Number: accNum,
|
||||
Sequence: seq,
|
||||
PubKey: pubKey,
|
||||
Balance: getGQLCoins(balance.GetBalances()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetBondsByIds(ctx context.Context, ids []string) ([]*Bond, error) {
|
||||
bonds := make([]*Bond, len(ids))
|
||||
for index, id := range ids {
|
||||
bondObj, err := q.GetBond(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bonds[index] = bondObj
|
||||
}
|
||||
|
||||
return bonds, nil
|
||||
}
|
||||
|
||||
func (q *queryResolver) GetBond(ctx context.Context, id string) (*Bond, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bondResp, err := bondQueryClient.GetBondById(context.Background(), &bondtypes.QueryGetBondByIdRequest{Id: id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bond := bondResp.GetBond()
|
||||
if bond == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return getGQLBond(bondResp.GetBond())
|
||||
}
|
||||
|
||||
func (q queryResolver) QueryBonds(ctx context.Context, attributes []*KeyValueInput) ([]*Bond, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bonds, err := bondQueryClient.Bonds(context.Background(), &bondtypes.QueryGetBondsRequest{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlResponse := make([]*Bond, len(bonds.GetBonds()))
|
||||
for i, bondObj := range bonds.GetBonds() {
|
||||
gqlBond, err := getGQLBond(bondObj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gqlResponse[i] = gqlBond
|
||||
}
|
||||
|
||||
return gqlResponse, nil
|
||||
}
|
||||
|
||||
// QueryBondsByOwner will return bonds by owner
|
||||
func (q queryResolver) QueryBondsByOwner(ctx context.Context, ownerAddresses []string) ([]*OwnerBonds, error) {
|
||||
ownerBonds := make([]*OwnerBonds, len(ownerAddresses))
|
||||
for index, ownerAddress := range ownerAddresses {
|
||||
bondsObj, err := q.GetBondsByOwner(ctx, ownerAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ownerBonds[index] = bondsObj
|
||||
}
|
||||
|
||||
return ownerBonds, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetBondsByOwner(ctx context.Context, address string) (*OwnerBonds, error) {
|
||||
bondQueryClient := bondtypes.NewQueryClient(q.ctx)
|
||||
bondResp, err := bondQueryClient.GetBondsByOwner(context.Background(), &bondtypes.QueryGetBondsByOwnerRequest{Owner: address})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ownerBonds := make([]*Bond, len(bondResp.GetBonds()))
|
||||
for i, bond := range bondResp.GetBonds() {
|
||||
bondObj, err := getGQLBond(&bond)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ownerBonds[i] = bondObj
|
||||
}
|
||||
|
||||
return &OwnerBonds{Bonds: ownerBonds, Owner: address}, nil
|
||||
}
|
||||
|
||||
func (q queryResolver) GetAuctionsByIds(ctx context.Context, ids []string) ([]*Auction, error) {
|
||||
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
||||
gqlAuctionResponse := make([]*Auction, len(ids))
|
||||
for i, id := range ids {
|
||||
auctionObj, err := auctionQueryClient.GetAuction(context.Background(), &auctiontypes.AuctionRequest{Id: id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bidsObj, err := auctionQueryClient.GetBids(context.Background(), &auctiontypes.BidsRequest{AuctionId: id})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlAuction, err := GetGQLAuction(auctionObj.GetAuction(), bidsObj.GetBids())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gqlAuctionResponse[i] = gqlAuction
|
||||
}
|
||||
|
||||
return gqlAuctionResponse, nil
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/99designs/gqlgen/graphql/handler"
|
||||
"github.com/99designs/gqlgen/graphql/playground"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// Server configures and starts the GQL server.
|
||||
func Server(ctx client.Context) {
|
||||
if !viper.GetBool("gql-server") {
|
||||
return
|
||||
}
|
||||
logFile := viper.GetString("log-file")
|
||||
|
||||
port := viper.GetString("gql-port")
|
||||
|
||||
srv := handler.NewDefaultServer(NewExecutableSchema(Config{Resolvers: &Resolver{
|
||||
ctx: ctx,
|
||||
logFile: logFile,
|
||||
}}))
|
||||
|
||||
http.Handle("/", playground.Handler("GraphQL playground", "/api"))
|
||||
|
||||
if viper.GetBool("gql-playground") {
|
||||
apiBase := viper.GetString("gql-playground-api-base")
|
||||
|
||||
http.Handle("/webui", playground.Handler("GraphQL playground", apiBase+"/api"))
|
||||
http.Handle("/console", playground.Handler("GraphQL playground", apiBase+"/graphql"))
|
||||
}
|
||||
|
||||
http.Handle("/api", srv)
|
||||
http.Handle("/graphql", srv)
|
||||
|
||||
log.Info("Connect to GraphQL playground", "url", fmt.Sprintf("http://localhost:%s", port))
|
||||
err := http.ListenAndServe(":"+port, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
)
|
||||
|
||||
// NodeDataPath is the path to the laconicd data folder.
|
||||
var NodeDataPath = os.ExpandEnv("$HOME/.laconicd/data")
|
||||
|
||||
func getStatusInfo(client client.Context) (*NodeInfo, *SyncInfo, *ValidatorInfo, error) {
|
||||
nodeClient, err := client.GetNode()
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
nodeStatus, err := nodeClient.Status(context.Background())
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return &NodeInfo{
|
||||
ID: string(nodeStatus.NodeInfo.ID()),
|
||||
Network: nodeStatus.NodeInfo.Network,
|
||||
Moniker: nodeStatus.NodeInfo.Moniker,
|
||||
}, &SyncInfo{
|
||||
LatestBlockHash: nodeStatus.SyncInfo.LatestBlockHash.String(),
|
||||
LatestBlockHeight: strconv.FormatInt(nodeStatus.SyncInfo.LatestBlockHeight, 10),
|
||||
LatestBlockTime: nodeStatus.SyncInfo.LatestBlockTime.String(),
|
||||
CatchingUp: nodeStatus.SyncInfo.CatchingUp,
|
||||
}, &ValidatorInfo{
|
||||
Address: nodeStatus.ValidatorInfo.Address.String(),
|
||||
VotingPower: strconv.FormatInt(nodeStatus.ValidatorInfo.VotingPower, 10),
|
||||
ProposerPriority: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getNetInfo(client client.Context) (string, []*PeerInfo, error) {
|
||||
nodeClient, err := client.GetNode()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
netInfo, err := nodeClient.NetInfo(context.Background())
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
peersInfo := make([]*PeerInfo, netInfo.NPeers)
|
||||
// TODO: find a way to get the peer information from nodeClient
|
||||
for index, peer := range netInfo.Peers {
|
||||
peersInfo[index] = &PeerInfo{
|
||||
Node: &NodeInfo{
|
||||
ID: string(peer.NodeInfo.ID()),
|
||||
// Moniker: peer.Node.Moniker,
|
||||
// Network: peer.Node.Network,
|
||||
},
|
||||
// IsOutbound: peer.IsOutbound,
|
||||
// RemoteIP: peer.RemoteIP,
|
||||
}
|
||||
}
|
||||
|
||||
return strconv.FormatInt(int64(netInfo.NPeers), 10), peersInfo, nil
|
||||
}
|
||||
|
||||
func getValidatorSet(client client.Context) ([]*ValidatorInfo, error) {
|
||||
nodeClient, err := client.GetNode()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
res, err := nodeClient.Validators(context.Background(), nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
validatorSet := make([]*ValidatorInfo, len(res.Validators))
|
||||
for index, validator := range res.Validators {
|
||||
proposerPriority := strconv.FormatInt(validator.ProposerPriority, 10)
|
||||
validatorSet[index] = &ValidatorInfo{
|
||||
Address: validator.Address.String(),
|
||||
VotingPower: strconv.FormatInt(validator.VotingPower, 10),
|
||||
ProposerPriority: &proposerPriority,
|
||||
}
|
||||
}
|
||||
|
||||
return validatorSet, nil
|
||||
}
|
||||
|
||||
// GetDiskUsage returns disk usage for the given path.
|
||||
func GetDiskUsage(dirPath string) (string, error) {
|
||||
out, err := exec.Command("du", "-sh", dirPath).Output()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.Fields(string(out))[0], nil
|
||||
}
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
package gql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
auctiontypes "github.com/cerc-io/laconicd/x/auction/types"
|
||||
bondtypes "github.com/cerc-io/laconicd/x/bond/types"
|
||||
nstypes "github.com/cerc-io/laconicd/x/nameservice/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
// OwnerAttributeName denotes the owner attribute name for a bond.
|
||||
const OwnerAttributeName = "owner"
|
||||
|
||||
// BondIDAttributeName denotes the record bond ID.
|
||||
const BondIDAttributeName = "bondId"
|
||||
|
||||
// ExpiryTimeAttributeName denotes the record expiry time.
|
||||
const ExpiryTimeAttributeName = "expiryTime"
|
||||
|
||||
func getGQLCoin(coin sdk.Coin) *Coin {
|
||||
gqlCoin := Coin{
|
||||
Type: coin.Denom,
|
||||
Quantity: coin.Amount.BigInt().String(),
|
||||
}
|
||||
|
||||
return &gqlCoin
|
||||
}
|
||||
|
||||
func getGQLCoins(coins sdk.Coins) []*Coin {
|
||||
gqlCoins := make([]*Coin, len(coins))
|
||||
for index, coin := range coins {
|
||||
gqlCoins[index] = getGQLCoin(coin)
|
||||
}
|
||||
|
||||
return gqlCoins
|
||||
}
|
||||
func GetGQLNameAuthorityRecord(record *nstypes.NameAuthority) (*AuthorityRecord, error) {
|
||||
if record == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &AuthorityRecord{
|
||||
OwnerAddress: record.OwnerAddress,
|
||||
OwnerPublicKey: record.OwnerPublicKey,
|
||||
Height: strconv.FormatUint(record.Height, 10),
|
||||
Status: record.Status,
|
||||
BondID: record.GetBondId(),
|
||||
ExpiryTime: record.GetExpiryTime().String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getGQLRecord(ctx context.Context, resolver QueryResolver, record nstypes.Record) (*Record, error) {
|
||||
// Nil record.
|
||||
if record.Deleted {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
recordType := record.ToRecordType()
|
||||
attributes, err := getAttributes(&recordType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
references, err := getReferences(ctx, resolver, &recordType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Record{
|
||||
ID: record.Id,
|
||||
BondID: record.GetBondId(),
|
||||
CreateTime: record.GetCreateTime(),
|
||||
ExpiryTime: record.GetExpiryTime(),
|
||||
Owners: record.GetOwners(),
|
||||
Names: record.GetNames(),
|
||||
Attributes: attributes,
|
||||
References: references,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getGQLNameRecord(record *nstypes.NameRecord) (*NameRecord, error) {
|
||||
if record == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
records := make([]*NameRecordEntry, len(record.History))
|
||||
for index, entry := range record.History {
|
||||
records[index] = getNameRecordEntry(entry)
|
||||
}
|
||||
|
||||
return &NameRecord{
|
||||
Latest: getNameRecordEntry(record.Latest),
|
||||
History: records,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getNameRecordEntry(record *nstypes.NameRecordEntry) *NameRecordEntry {
|
||||
return &NameRecordEntry{
|
||||
ID: record.Id,
|
||||
Height: strconv.FormatUint(record.Height, 10),
|
||||
}
|
||||
}
|
||||
|
||||
func getGQLBond(bondObj *bondtypes.Bond) (*Bond, error) {
|
||||
// Nil record.
|
||||
if bondObj == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &Bond{
|
||||
ID: bondObj.Id,
|
||||
Owner: bondObj.Owner,
|
||||
Balance: getGQLCoins(bondObj.Balance),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func matchBondOnAttributes(bondObj *bondtypes.Bond, attributes []*KeyValueInput) bool {
|
||||
for _, attr := range attributes {
|
||||
switch attr.Key {
|
||||
case OwnerAttributeName:
|
||||
{
|
||||
if attr.Value.String == nil || bondObj.Owner != *attr.Value.String {
|
||||
return false
|
||||
}
|
||||
}
|
||||
default:
|
||||
{
|
||||
// Only attributes explicitly listed in the switch are queryable.
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func getAuctionBid(bid *auctiontypes.Bid) *AuctionBid {
|
||||
return &AuctionBid{
|
||||
BidderAddress: bid.BidderAddress,
|
||||
Status: bid.Status,
|
||||
CommitHash: bid.CommitHash,
|
||||
CommitTime: bid.GetCommitTime(),
|
||||
RevealTime: bid.GetRevealTime(),
|
||||
CommitFee: getGQLCoin(bid.CommitFee),
|
||||
RevealFee: getGQLCoin(bid.RevealFee),
|
||||
BidAmount: getGQLCoin(bid.BidAmount),
|
||||
}
|
||||
}
|
||||
|
||||
func GetGQLAuction(auction *auctiontypes.Auction, bids []*auctiontypes.Bid) (*Auction, error) {
|
||||
if auction == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
gqlAuction := Auction{
|
||||
ID: auction.Id,
|
||||
Status: auction.Status,
|
||||
OwnerAddress: auction.OwnerAddress,
|
||||
CreateTime: auction.GetCreateTime(),
|
||||
CommitsEndTime: auction.GetCommitsEndTime(),
|
||||
RevealsEndTime: auction.GetRevealsEndTime(),
|
||||
CommitFee: getGQLCoin(auction.CommitFee),
|
||||
RevealFee: getGQLCoin(auction.RevealFee),
|
||||
MinimumBid: getGQLCoin(auction.MinimumBid),
|
||||
WinnerAddress: auction.WinnerAddress,
|
||||
WinnerBid: getGQLCoin(auction.WinningBid),
|
||||
WinnerPrice: getGQLCoin(auction.WinningPrice),
|
||||
}
|
||||
|
||||
auctionBids := make([]*AuctionBid, len(bids))
|
||||
for index, entry := range bids {
|
||||
auctionBids[index] = getAuctionBid(entry)
|
||||
}
|
||||
|
||||
gqlAuction.Bids = auctionBids
|
||||
|
||||
return &gqlAuction, nil
|
||||
}
|
||||
|
||||
func getReferences(ctx context.Context, resolver QueryResolver, r *nstypes.RecordType) ([]*Record, error) {
|
||||
var ids []string
|
||||
|
||||
for _, value := range r.Attributes {
|
||||
switch value.(type) {
|
||||
case interface{}:
|
||||
if obj, ok := value.(map[string]interface{}); ok {
|
||||
if _, ok := obj["/"]; ok && len(obj) == 1 {
|
||||
if _, ok := obj["/"].(string); ok {
|
||||
ids = append(ids, obj["/"].(string))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resolver.GetRecordsByIds(ctx, ids)
|
||||
}
|
||||
|
||||
func getAttributes(r *nstypes.RecordType) ([]*KeyValue, error) {
|
||||
return mapToKeyValuePairs(r.Attributes)
|
||||
}
|
||||
|
||||
func mapToKeyValuePairs(attrs map[string]interface{}) ([]*KeyValue, error) {
|
||||
var kvPairs []*KeyValue
|
||||
|
||||
trueVal := true
|
||||
falseVal := false
|
||||
|
||||
for key, value := range attrs {
|
||||
kvPair := &KeyValue{
|
||||
Key: key,
|
||||
Value: &Value{},
|
||||
}
|
||||
|
||||
switch val := value.(type) {
|
||||
case nil:
|
||||
kvPair.Value.Null = &trueVal
|
||||
case int:
|
||||
kvPair.Value.Int = &val
|
||||
case float64:
|
||||
kvPair.Value.Float = &val
|
||||
case string:
|
||||
kvPair.Value.String = &val
|
||||
case bool:
|
||||
kvPair.Value.Boolean = &val
|
||||
case interface{}:
|
||||
if obj, ok := value.(map[string]interface{}); ok {
|
||||
if _, ok := obj["/"]; ok && len(obj) == 1 {
|
||||
if _, ok := obj["/"].(string); ok {
|
||||
kvPair.Value.Reference = &Reference{
|
||||
ID: obj["/"].(string),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bytes, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jsonStr := string(bytes)
|
||||
kvPair.Value.JSON = &jsonStr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if kvPair.Value.Null == nil {
|
||||
kvPair.Value.Null = &falseVal
|
||||
}
|
||||
|
||||
valueType := reflect.ValueOf(value)
|
||||
if valueType.Kind() == reflect.Slice {
|
||||
bytes, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jsonStr := string(bytes)
|
||||
kvPair.Value.JSON = &jsonStr
|
||||
}
|
||||
|
||||
kvPairs = append(kvPairs, kvPair)
|
||||
}
|
||||
|
||||
return kvPairs, nil
|
||||
}
|
||||
|
||||
func parseRequestAttributes(attrs []*KeyValueInput) []*nstypes.QueryListRecordsRequest_KeyValueInput {
|
||||
kvPairs := []*nstypes.QueryListRecordsRequest_KeyValueInput{}
|
||||
|
||||
for _, value := range attrs {
|
||||
kvPair := &nstypes.QueryListRecordsRequest_KeyValueInput{
|
||||
Key: value.Key,
|
||||
Value: &nstypes.QueryListRecordsRequest_ValueInput{},
|
||||
}
|
||||
|
||||
if value.Value.String != nil {
|
||||
kvPair.Value.String_ = *value.Value.String
|
||||
kvPair.Value.Type = "string"
|
||||
}
|
||||
|
||||
if value.Value.Int != nil {
|
||||
kvPair.Value.Int = int64(*value.Value.Int)
|
||||
kvPair.Value.Type = "int"
|
||||
}
|
||||
|
||||
if value.Value.Float != nil {
|
||||
kvPair.Value.Float = *value.Value.Float
|
||||
kvPair.Value.Type = "float"
|
||||
}
|
||||
|
||||
if value.Value.Boolean != nil {
|
||||
kvPair.Value.Boolean = *value.Value.Boolean
|
||||
kvPair.Value.Type = "boolean"
|
||||
}
|
||||
|
||||
if value.Value.Reference != nil {
|
||||
reference := &nstypes.QueryListRecordsRequest_ReferenceInput{
|
||||
Id: value.Value.Reference.ID,
|
||||
}
|
||||
|
||||
kvPair.Value.Reference = reference
|
||||
kvPair.Value.Type = "reference"
|
||||
}
|
||||
|
||||
// TODO: Handle arrays.
|
||||
|
||||
kvPairs = append(kvPairs, kvPair)
|
||||
}
|
||||
|
||||
return kvPairs
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package gql
|
||||
|
||||
// NameServiceVersion is the registry API version.
|
||||
const NameServiceVersion = "0.3.0"
|
||||
@@ -0,0 +1,238 @@
|
||||
# Reference to another record.
|
||||
type Reference {
|
||||
id: String! # ID of linked record.
|
||||
}
|
||||
|
||||
# Reference to another record.
|
||||
input ReferenceInput {
|
||||
id: String!
|
||||
}
|
||||
|
||||
# Bonds contain funds that are used to pay rent on record registration and renewal.
|
||||
type Bond {
|
||||
id: String! # Primary key, auto-generated by the server.
|
||||
owner: String! # Bond owner cosmos-sdk address.
|
||||
balance: [Coin!] # Current balance for each coin type.
|
||||
}
|
||||
|
||||
# OwnerBonds contains the bonds related the owner
|
||||
type OwnerBonds {
|
||||
owner: String!
|
||||
bonds: [Bond!]
|
||||
}
|
||||
|
||||
# Mutations require payment in coins (e.g. 100wire).
|
||||
# Used by the wallet to get the account balance for display and mutations.
|
||||
type Coin {
|
||||
type: String! # e.g. 'WIRE'
|
||||
quantity: String! # e.g. 1000000
|
||||
}
|
||||
# Represents an account on the blockchain.
|
||||
# Mutations have to be signed by a particular account.
|
||||
type Account {
|
||||
address: String! # Blockchain address.
|
||||
pubKey: String # Public key.
|
||||
number: String! # Account number.
|
||||
sequence: String! # Sequence number used to prevent replays.
|
||||
balance: [Coin!] # Current balance for each coin type.
|
||||
}
|
||||
|
||||
# Value of a given type.
|
||||
type Value {
|
||||
null: Boolean
|
||||
|
||||
int: Int
|
||||
float: Float
|
||||
string: String
|
||||
boolean: Boolean
|
||||
json: String
|
||||
|
||||
reference: Reference
|
||||
|
||||
values: [Value]
|
||||
}
|
||||
# Value of a given type used as input to queries.
|
||||
input ValueInput {
|
||||
null: Boolean
|
||||
|
||||
int: Int
|
||||
float: Float
|
||||
string: String
|
||||
boolean: Boolean
|
||||
|
||||
reference: ReferenceInput
|
||||
|
||||
values: [ValueInput]
|
||||
}
|
||||
|
||||
# Key/value pair.
|
||||
type KeyValue {
|
||||
key: String!
|
||||
value: Value!
|
||||
}
|
||||
|
||||
# Key/value pair for inputs.
|
||||
input KeyValueInput {
|
||||
key: String!
|
||||
value: ValueInput!
|
||||
}
|
||||
|
||||
# Status information about a node (https://docs.tendermint.com/master/rpc/#/Info/status).
|
||||
type NodeInfo {
|
||||
id: String! # Tendermint Node ID.
|
||||
network: String! # Name of the network/blockchain.
|
||||
moniker: String! # Name of the node.
|
||||
}
|
||||
|
||||
# Node sync status.
|
||||
type SyncInfo {
|
||||
latest_block_hash: String!
|
||||
latest_block_height: String!
|
||||
latest_block_time: String!
|
||||
catching_up: Boolean!
|
||||
}
|
||||
|
||||
# Validator set info (https://docs.tendermint.com/master/rpc/#/Info/validators).
|
||||
type ValidatorInfo {
|
||||
address: String!
|
||||
voting_power: String!
|
||||
proposer_priority: String
|
||||
}
|
||||
|
||||
# Network/peer info (https://docs.tendermint.com/master/rpc/#/Info/net_info).
|
||||
type PeerInfo {
|
||||
node: NodeInfo!
|
||||
is_outbound: Boolean!
|
||||
remote_ip: String!
|
||||
}
|
||||
|
||||
# Vulcanize laconic status.
|
||||
type Status {
|
||||
version: String!
|
||||
node: NodeInfo!
|
||||
sync: SyncInfo!
|
||||
validator: ValidatorInfo
|
||||
validators: [ValidatorInfo]!
|
||||
num_peers: String!
|
||||
peers: [PeerInfo]
|
||||
disk_usage: String!
|
||||
}
|
||||
|
||||
# An auction bid.
|
||||
type AuctionBid {
|
||||
bidderAddress: String!
|
||||
status: String!
|
||||
commitHash: String!
|
||||
commitTime: String!
|
||||
commitFee: Coin!
|
||||
revealTime: String!
|
||||
revealFee: Coin!
|
||||
bidAmount: Coin!
|
||||
}
|
||||
|
||||
# A sealed-bid, 2nd price auction.
|
||||
type Auction {
|
||||
id: String! # Auction ID.
|
||||
status: String! # Auction status (commit, reveal, expired).
|
||||
ownerAddress: String! # Auction owner time.
|
||||
createTime: String! # Create time.
|
||||
commitsEndTime: String! # Commit phase end time.
|
||||
revealsEndTime: String! # Reveal phase end time.
|
||||
commitFee: Coin! # Fee required to bid/participate in the auction.
|
||||
revealFee: Coin! # Reveal fee (paid back to bidders only if they unseal/reveal the bid).
|
||||
minimumBid: Coin! # Minimum bid amount.
|
||||
winnerAddress: String! # Winner address.
|
||||
winnerBid: Coin! # The winning bid amount.
|
||||
winnerPrice: Coin! # The price that the winner actually pays (2nd highest bid).
|
||||
bids: [AuctionBid] # Bids make in the auction.
|
||||
}
|
||||
|
||||
# Record defines the basic properties of an entity in the graph database.
|
||||
type Record {
|
||||
id: String! # Computed attribute: Multibase encoded content hash (https://github.com/multiformats/multibase).
|
||||
names: [String!] # Names pointing to this CID (reverse lookup).
|
||||
bondId: String! # Associated bond ID.
|
||||
createTime: String! # Record create time.
|
||||
expiryTime: String! # Record expiry time.
|
||||
owners: [String!] # Addresses of record owners.
|
||||
attributes: [KeyValue] # Record attributes.
|
||||
references: [Record] # Record references.
|
||||
}
|
||||
|
||||
# Name authority record.
|
||||
type AuthorityRecord {
|
||||
ownerAddress: String! # Owner address.
|
||||
ownerPublicKey: String! # Owner public key.
|
||||
height: String! # Height at which record was created.
|
||||
status: String! # Status (active, auction, expired).
|
||||
bondId: String! # Associated bond ID.
|
||||
expiryTime: String! # Authority expiry time.
|
||||
auction: Auction # Authority auction.
|
||||
}
|
||||
|
||||
# Name record entry, created at a particular height.
|
||||
type NameRecordEntry {
|
||||
id: String! # Target record ID.
|
||||
height: String! # Height at which record was created.
|
||||
}
|
||||
|
||||
# Name record stores the latest and historical name -> record ID mappings.
|
||||
type NameRecord {
|
||||
latest: NameRecordEntry! # Latest mame record entry.
|
||||
history: [NameRecordEntry] # Historical name record entries.
|
||||
}
|
||||
|
||||
type Query {
|
||||
#
|
||||
# Status API.
|
||||
#
|
||||
getStatus: Status!
|
||||
|
||||
# Get blockchain accounts.
|
||||
getAccounts(addresses: [String!]): [Account]
|
||||
|
||||
# Get bonds by IDs.
|
||||
getBondsByIds(ids: [String!]): [Bond]
|
||||
|
||||
# Query bonds.
|
||||
queryBonds(attributes: [KeyValueInput]): [Bond]
|
||||
|
||||
# Query bonds by owner.
|
||||
queryBondsByOwner(ownerAddresses: [String!]): [OwnerBonds]
|
||||
|
||||
#
|
||||
# GraphDB API.
|
||||
#
|
||||
|
||||
# Get records by IDs.
|
||||
getRecordsByIds(ids: [String!]): [Record]
|
||||
|
||||
# Query records.
|
||||
queryRecords(
|
||||
# Multiple attribute conditions are in a logical AND.
|
||||
attributes: [KeyValueInput]
|
||||
|
||||
# Whether to query all records, not just named ones (false by default).
|
||||
all: Boolean
|
||||
): [Record]
|
||||
|
||||
#
|
||||
# Naming API.
|
||||
#
|
||||
|
||||
# Lookup authority information.
|
||||
lookupAuthorities(names: [String!]): [AuthorityRecord]!
|
||||
|
||||
# Lookup name to record mapping information.
|
||||
lookupNames(names: [String!]): [NameRecord]!
|
||||
|
||||
# Resolve names to records.
|
||||
resolveNames(names: [String!]): [Record]!
|
||||
|
||||
#
|
||||
# Auctions API.
|
||||
#
|
||||
|
||||
# Get auctions by IDs.
|
||||
getAuctionsByIds(ids: [String!]): [Auction]
|
||||
}
|
||||
Reference in New Issue
Block a user