Skip to content

Commit

Permalink
[DPA-1157]: feat: introduce cosmosKeys & starknetKeys graphql query (#…
Browse files Browse the repository at this point in the history
…14764)

* feat(cosmos): introduce cosmosKeys graphql query

Similar to eTHKeys and solanaKeys, we need cosmosKeys that will be used by the operator ui to show a list of addresses.

JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1157

* feat(starknet): introduce starknetKeys graphql query

Similar to eTHKeys and solanaKeys, we need starknetKeys that will be used by the operator ui to show a list of addresses.

JIRA: https://smartcontract-it.atlassian.net/browse/DPA-1157
  • Loading branch information
graham-chainlink authored Oct 15, 2024
1 parent a3b552f commit 56d4b84
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/stale-pugs-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

#added introduce cosmosKeys and starknetKeys graphql query
43 changes: 43 additions & 0 deletions core/web/resolver/cosmos_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package resolver

import (
"github.com/graph-gophers/graphql-go"

"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey"
)

type CosmosKeyResolver struct {
key cosmoskey.Key
}

func NewCosmosKey(key cosmoskey.Key) *CosmosKeyResolver {
return &CosmosKeyResolver{key: key}
}

func NewCosmosKeys(keys []cosmoskey.Key) []*CosmosKeyResolver {
var resolvers []*CosmosKeyResolver

for _, k := range keys {
resolvers = append(resolvers, NewCosmosKey(k))
}

return resolvers
}

func (r *CosmosKeyResolver) ID() graphql.ID {
return graphql.ID(r.key.PublicKeyStr())
}

// -- GetCosmosKeys Query --

type CosmosKeysPayloadResolver struct {
keys []cosmoskey.Key
}

func NewCosmosKeysPayload(keys []cosmoskey.Key) *CosmosKeysPayloadResolver {
return &CosmosKeysPayloadResolver{keys: keys}
}

func (r *CosmosKeysPayloadResolver) Results() []*CosmosKeyResolver {
return NewCosmosKeys(r.keys)
}
74 changes: 74 additions & 0 deletions core/web/resolver/cosmos_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package resolver

import (
"context"
"errors"
"fmt"
"testing"

gqlerrors "github.com/graph-gophers/graphql-go/errors"

"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey"
)

func TestResolver_CosmosKeys(t *testing.T) {
t.Parallel()

query := `
query GetCosmosKeys {
cosmosKeys {
results {
id
}
}
}`
k := cosmoskey.MustNewInsecure(keystest.NewRandReaderFromSeed(1))
result := fmt.Sprintf(`
{
"cosmosKeys": {
"results": [
{
"id": "%s"
}
]
}
}`, k.PublicKeyStr())
gError := errors.New("error")

testCases := []GQLTestCase{
unauthorizedTestCase(GQLTestCase{query: query}, "cosmosKeys"),
{
name: "success",
authenticated: true,
before: func(ctx context.Context, f *gqlTestFramework) {
f.Mocks.cosmos.On("GetAll").Return([]cosmoskey.Key{k}, nil)
f.Mocks.keystore.On("Cosmos").Return(f.Mocks.cosmos)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
},
query: query,
result: result,
},
{
name: "no keys returned by GetAll",
authenticated: true,
before: func(ctx context.Context, f *gqlTestFramework) {
f.Mocks.cosmos.On("GetAll").Return([]cosmoskey.Key{}, gError)
f.Mocks.keystore.On("Cosmos").Return(f.Mocks.cosmos)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
},
query: query,
result: `null`,
errors: []*gqlerrors.QueryError{
{
Extensions: nil,
ResolverError: gError,
Path: []interface{}{"cosmosKeys"},
Message: gError.Error(),
},
},
},
}

RunGQLTests(t, testCases)
}
24 changes: 24 additions & 0 deletions core/web/resolver/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,30 @@ func (r *Resolver) AptosKeys(ctx context.Context) (*AptosKeysPayloadResolver, er
return NewAptosKeysPayload(keys), nil
}

func (r *Resolver) CosmosKeys(ctx context.Context) (*CosmosKeysPayloadResolver, error) {
if err := authenticateUser(ctx); err != nil {
return nil, err
}
keys, err := r.App.GetKeyStore().Cosmos().GetAll()
if err != nil {
return nil, err
}

return NewCosmosKeysPayload(keys), nil
}

func (r *Resolver) StarkNetKeys(ctx context.Context) (*StarkNetKeysPayloadResolver, error) {
if err := authenticateUser(ctx); err != nil {
return nil, err
}
keys, err := r.App.GetKeyStore().StarkNet().GetAll()
if err != nil {
return nil, err
}

return NewStarkNetKeysPayload(keys), nil
}

func (r *Resolver) SQLLogging(ctx context.Context) (*GetSQLLoggingPayloadResolver, error) {
if err := authenticateUser(ctx); err != nil {
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions core/web/resolver/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ type mocks struct {
vrf *keystoreMocks.VRF
solana *keystoreMocks.Solana
aptos *keystoreMocks.Aptos
cosmos *keystoreMocks.Cosmos
starknet *keystoreMocks.StarkNet
chain *legacyEvmORMMocks.Chain
legacyEVMChains *legacyEvmORMMocks.LegacyChainContainer
relayerChainInterops *chainlinkMocks.FakeRelayerChainInteroperators
Expand Down Expand Up @@ -108,6 +110,8 @@ func setupFramework(t *testing.T) *gqlTestFramework {
vrf: keystoreMocks.NewVRF(t),
solana: keystoreMocks.NewSolana(t),
aptos: keystoreMocks.NewAptos(t),
cosmos: keystoreMocks.NewCosmos(t),
starknet: keystoreMocks.NewStarkNet(t),
chain: legacyEvmORMMocks.NewChain(t),
legacyEVMChains: legacyEvmORMMocks.NewLegacyChainContainer(t),
relayerChainInterops: &chainlinkMocks.FakeRelayerChainInteroperators{},
Expand Down
43 changes: 43 additions & 0 deletions core/web/resolver/starknet_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package resolver

import (
"github.com/graph-gophers/graphql-go"

"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey"
)

type StarkNetKeyResolver struct {
key starkkey.Key
}

func NewStarkNetKey(key starkkey.Key) *StarkNetKeyResolver {
return &StarkNetKeyResolver{key: key}
}

func NewStarkNetKeys(keys []starkkey.Key) []*StarkNetKeyResolver {
var resolvers []*StarkNetKeyResolver

for _, k := range keys {
resolvers = append(resolvers, NewStarkNetKey(k))
}

return resolvers
}

func (r *StarkNetKeyResolver) ID() graphql.ID {
return graphql.ID(r.key.StarkKeyStr())
}

// -- GetStarkNetKeys Query --

type StarkNetKeysPayloadResolver struct {
keys []starkkey.Key
}

func NewStarkNetKeysPayload(keys []starkkey.Key) *StarkNetKeysPayloadResolver {
return &StarkNetKeysPayloadResolver{keys: keys}
}

func (r *StarkNetKeysPayloadResolver) Results() []*StarkNetKeyResolver {
return NewStarkNetKeys(r.keys)
}
74 changes: 74 additions & 0 deletions core/web/resolver/starknet_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package resolver

import (
"context"
"errors"
"fmt"
"testing"

gqlerrors "github.com/graph-gophers/graphql-go/errors"

"github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest"
"github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey"
)

func TestResolver_StarkNetKeys(t *testing.T) {
t.Parallel()

query := `
query GetStarkNetKeys {
starknetKeys {
results {
id
}
}
}`
k := starkkey.MustNewInsecure(keystest.NewRandReaderFromSeed(1))
result := fmt.Sprintf(`
{
"starknetKeys": {
"results": [
{
"id": "%s"
}
]
}
}`, k.StarkKeyStr())
gError := errors.New("error")

testCases := []GQLTestCase{
unauthorizedTestCase(GQLTestCase{query: query}, "starknetKeys"),
{
name: "success",
authenticated: true,
before: func(ctx context.Context, f *gqlTestFramework) {
f.Mocks.starknet.On("GetAll").Return([]starkkey.Key{k}, nil)
f.Mocks.keystore.On("StarkNet").Return(f.Mocks.starknet)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
},
query: query,
result: result,
},
{
name: "no keys returned by GetAll",
authenticated: true,
before: func(ctx context.Context, f *gqlTestFramework) {
f.Mocks.starknet.On("GetAll").Return([]starkkey.Key{}, gError)
f.Mocks.keystore.On("StarkNet").Return(f.Mocks.starknet)
f.App.On("GetKeyStore").Return(f.Mocks.keystore)
},
query: query,
result: `null`,
errors: []*gqlerrors.QueryError{
{
Extensions: nil,
ResolverError: gError,
Path: []interface{}{"starknetKeys"},
Message: gError.Error(),
},
},
},
}

RunGQLTests(t, testCases)
}
2 changes: 2 additions & 0 deletions core/web/schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type Query {
p2pKeys: P2PKeysPayload!
solanaKeys: SolanaKeysPayload!
aptosKeys: AptosKeysPayload!
cosmosKeys: CosmosKeysPayload!
starknetKeys: StarkNetKeysPayload!
sqlLogging: GetSQLLoggingPayload!
vrfKey(id: ID!): VRFKeyPayload!
vrfKeys: VRFKeysPayload!
Expand Down
7 changes: 7 additions & 0 deletions core/web/schema/type/cosmos_key.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type CosmosKey {
id: ID!
}

type CosmosKeysPayload {
results: [CosmosKey!]!
}
7 changes: 7 additions & 0 deletions core/web/schema/type/starknet_key.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
type StarkNetKey {
id: ID!
}

type StarkNetKeysPayload {
results: [StarkNetKey!]!
}

0 comments on commit 56d4b84

Please sign in to comment.