2024-02-29 12:45:38 +00:00
|
|
|
package gql
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/base64"
|
|
|
|
"strconv"
|
2024-03-12 08:40:23 +00:00
|
|
|
"strings"
|
2024-02-29 12:45:38 +00:00
|
|
|
|
|
|
|
"github.com/cosmos/cosmos-sdk/client"
|
2024-03-07 09:11:53 +00:00
|
|
|
types "github.com/cosmos/cosmos-sdk/types"
|
2024-02-29 12:45:38 +00:00
|
|
|
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
|
|
|
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
|
|
|
|
2024-04-01 09:57:26 +00:00
|
|
|
auctiontypes "git.vdb.to/cerc-io/laconicd/x/auction"
|
|
|
|
bondtypes "git.vdb.to/cerc-io/laconicd/x/bond"
|
2024-07-04 13:40:10 +00:00
|
|
|
onboardingTypes "git.vdb.to/cerc-io/laconicd/x/onboarding"
|
2024-04-01 09:57:26 +00:00
|
|
|
registrytypes "git.vdb.to/cerc-io/laconicd/x/registry"
|
2024-02-29 12:45:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// 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 }
|
|
|
|
|
2024-08-02 09:15:08 +00:00
|
|
|
func (q queryResolver) GetAuthorities(ctx context.Context, owner *string) ([]*Authority, error) {
|
|
|
|
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
|
|
|
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
|
|
|
|
|
|
|
authoritiesReq := ®istrytypes.QueryAuthoritiesRequest{}
|
|
|
|
if owner != nil {
|
|
|
|
authoritiesReq.Owner = *owner
|
|
|
|
}
|
|
|
|
|
|
|
|
authoritiesResp, err := nsQueryClient.Authorities(ctx, authoritiesReq)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
authorities := make([]*Authority, len(authoritiesResp.GetAuthorities()))
|
|
|
|
for i, a := range authoritiesResp.Authorities {
|
|
|
|
entry, err := getAuthorityRecord(*a.Entry, auctionQueryClient)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
authorities[i] = &Authority{
|
|
|
|
Name: a.Name,
|
|
|
|
Entry: entry,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return authorities, nil
|
|
|
|
}
|
|
|
|
|
2024-02-29 12:45:38 +00:00
|
|
|
func (q queryResolver) LookupAuthorities(ctx context.Context, names []string) ([]*AuthorityRecord, error) {
|
|
|
|
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
|
|
|
auctionQueryClient := auctiontypes.NewQueryClient(q.ctx)
|
|
|
|
gqlResponse := []*AuthorityRecord{}
|
|
|
|
|
|
|
|
for _, name := range names {
|
|
|
|
res, err := nsQueryClient.Whois(context.Background(), ®istrytypes.QueryWhoisRequest{Name: name})
|
|
|
|
if err != nil {
|
2024-03-12 08:40:23 +00:00
|
|
|
if strings.Contains(err.Error(), "Name authority not found") {
|
|
|
|
gqlResponse = append(gqlResponse, nil)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2024-02-29 12:45:38 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
nameAuthority := res.GetNameAuthority()
|
2024-08-02 09:15:08 +00:00
|
|
|
gqlNameAuthorityRecord, err := getAuthorityRecord(nameAuthority, auctionQueryClient)
|
2024-02-29 12:45:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
gqlResponse = append(gqlResponse, gqlNameAuthorityRecord)
|
|
|
|
}
|
|
|
|
|
|
|
|
return gqlResponse, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q queryResolver) ResolveNames(ctx context.Context, names []string) ([]*Record, error) {
|
|
|
|
nsQueryClient := registrytypes.NewQueryClient(q.ctx)
|
|
|
|
var gqlResponse []*Record
|
|
|
|
for _, name := range names {
|
|
|
|
res, err := nsQueryClient.ResolveLrn(context.Background(), ®istrytypes.QueryResolveLrnRequest{Lrn: 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 := registrytypes.NewQueryClient(q.ctx)
|
|
|
|
var gqlResponse []*NameRecord
|
|
|
|
|
|
|
|
for _, name := range names {
|
|
|
|
res, err := nsQueryClient.LookupLrn(context.Background(), ®istrytypes.QueryLookupLrnRequest{Lrn: 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 := registrytypes.NewQueryClient(q.ctx)
|
|
|
|
|
|
|
|
res, err := nsQueryClient.Records(
|
|
|
|
context.Background(),
|
|
|
|
®istrytypes.QueryRecordsRequest{
|
|
|
|
Attributes: toRPCAttributes(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 := registrytypes.NewQueryClient(q.ctx)
|
|
|
|
gqlResponse := make([]*Record, len(ids))
|
|
|
|
|
|
|
|
for i, id := range ids {
|
2024-03-07 11:25:15 +00:00
|
|
|
res, err := nsQueryClient.GetRecord(context.Background(), ®istrytypes.QueryGetRecordRequest{Id: id})
|
2024-02-29 12:45:38 +00:00
|
|
|
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: RegistryVersion,
|
|
|
|
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
|
|
|
|
}
|
2024-03-07 09:11:53 +00:00
|
|
|
var account types.AccountI
|
2024-02-29 12:45:38 +00:00
|
|
|
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})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
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 {
|
2024-03-12 08:40:23 +00:00
|
|
|
if strings.Contains(err.Error(), "Bond not found") {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2024-02-29 12:45:38 +00:00
|
|
|
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)
|
2024-03-07 11:25:15 +00:00
|
|
|
bonds, err := bondQueryClient.Bonds(context.Background(), &bondtypes.QueryBondsRequest{})
|
2024-02-29 12:45:38 +00:00
|
|
|
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() {
|
|
|
|
// #nosec G601
|
|
|
|
bondObj, err := getGQLBond(&bond) //nolint: all
|
|
|
|
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 {
|
2024-03-07 11:25:15 +00:00
|
|
|
auctionObj, err := auctionQueryClient.GetAuction(context.Background(), &auctiontypes.QueryGetAuctionRequest{Id: id})
|
2024-02-29 12:45:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-03-07 11:25:15 +00:00
|
|
|
bidsObj, err := auctionQueryClient.GetBids(context.Background(), &auctiontypes.QueryGetBidsRequest{AuctionId: id})
|
2024-02-29 12:45:38 +00:00
|
|
|
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
|
|
|
|
}
|
2024-07-04 13:40:10 +00:00
|
|
|
|
|
|
|
func (q queryResolver) GetParticipants(ctx context.Context) ([]*Participant, error) {
|
|
|
|
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
|
|
|
participantResp, err := onboardingQueryClient.Participants(context.Background(), &onboardingTypes.QueryParticipantsRequest{})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
participants := make([]*Participant, len(participantResp.GetParticipants()))
|
|
|
|
for i, p := range participantResp.Participants {
|
|
|
|
participants[i] = &Participant{
|
2024-07-15 09:33:44 +00:00
|
|
|
CosmosAddress: p.CosmosAddress,
|
|
|
|
NitroAddress: p.NitroAddress,
|
2024-07-26 14:42:40 +00:00
|
|
|
Role: p.Role,
|
|
|
|
KycID: p.KycId,
|
2024-07-04 13:40:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return participants, nil
|
|
|
|
}
|
2024-07-29 10:28:30 +00:00
|
|
|
|
|
|
|
func (q queryResolver) GetParticipantByAddress(ctx context.Context, address string) (*Participant, error) {
|
|
|
|
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
|
|
|
participantResp, err := onboardingQueryClient.GetParticipantByAddress(ctx, &onboardingTypes.QueryGetParticipantByAddressRequest{Address: address})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
p := participantResp.Participant
|
|
|
|
participant := &Participant{
|
|
|
|
CosmosAddress: p.CosmosAddress,
|
|
|
|
NitroAddress: p.NitroAddress,
|
|
|
|
Role: p.Role,
|
|
|
|
KycID: p.KycId,
|
|
|
|
}
|
|
|
|
|
|
|
|
return participant, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q queryResolver) GetParticipantByNitroAddress(ctx context.Context, nitroAddress string) (*Participant, error) {
|
|
|
|
onboardingQueryClient := onboardingTypes.NewQueryClient(q.ctx)
|
2024-09-05 07:07:54 +00:00
|
|
|
participantResp, err := onboardingQueryClient.GetParticipantByNitroAddress(
|
|
|
|
ctx,
|
|
|
|
&onboardingTypes.QueryGetParticipantByNitroAddressRequest{
|
|
|
|
NitroAddress: nitroAddress,
|
|
|
|
},
|
|
|
|
)
|
2024-07-29 10:28:30 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
p := participantResp.Participant
|
|
|
|
participant := &Participant{
|
|
|
|
CosmosAddress: p.CosmosAddress,
|
|
|
|
NitroAddress: p.NitroAddress,
|
|
|
|
Role: p.Role,
|
|
|
|
KycID: p.KycId,
|
|
|
|
}
|
|
|
|
|
|
|
|
return participant, nil
|
|
|
|
}
|