diff --git a/.changeset/four-buses-invite.md b/.changeset/four-buses-invite.md new file mode 100644 index 00000000000..2f657dd4503 --- /dev/null +++ b/.changeset/four-buses-invite.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added Introduce aptosKeys Graphql query diff --git a/core/web/resolver/aptos_key.go b/core/web/resolver/aptos_key.go new file mode 100644 index 00000000000..862f7b57fc7 --- /dev/null +++ b/core/web/resolver/aptos_key.go @@ -0,0 +1,47 @@ +package resolver + +import ( + "github.com/graph-gophers/graphql-go" + + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/aptoskey" +) + +type AptosKeyResolver struct { + key aptoskey.Key +} + +func NewAptosKey(key aptoskey.Key) *AptosKeyResolver { + return &AptosKeyResolver{key: key} +} + +func NewAptosKeys(keys []aptoskey.Key) []*AptosKeyResolver { + var resolvers []*AptosKeyResolver + + for _, k := range keys { + resolvers = append(resolvers, NewAptosKey(k)) + } + + return resolvers +} + +func (r *AptosKeyResolver) ID() graphql.ID { + return graphql.ID(r.key.PublicKeyStr()) +} + +func (r *AptosKeyResolver) Account() string { + return r.key.Account() +} + +// -- GetAptosKeys Query -- + +type AptosKeysPayloadResolver struct { + keys []aptoskey.Key +} + +func NewAptosKeysPayload(keys []aptoskey.Key) *AptosKeysPayloadResolver { + return &AptosKeysPayloadResolver{keys: keys} +} + +func (r *AptosKeysPayloadResolver) Results() []*AptosKeyResolver { + return NewAptosKeys(r.keys) +} diff --git a/core/web/resolver/aptos_key_test.go b/core/web/resolver/aptos_key_test.go new file mode 100644 index 00000000000..051c696239d --- /dev/null +++ b/core/web/resolver/aptos_key_test.go @@ -0,0 +1,76 @@ +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/aptoskey" +) + +func TestResolver_AptosKeys(t *testing.T) { + t.Parallel() + + query := ` + query GetAptosKeys { + aptosKeys { + results { + id + account + } + } + }` + k := aptoskey.MustNewInsecure(keystest.NewRandReaderFromSeed(1)) + result := fmt.Sprintf(` + { + "aptosKeys": { + "results": [ + { + "id": "%s", + "account": "%s" + } + ] + } + }`, k.PublicKeyStr(), k.Account()) + gError := errors.New("error") + + testCases := []GQLTestCase{ + unauthorizedTestCase(GQLTestCase{query: query}, "aptosKeys"), + { + name: "success", + authenticated: true, + before: func(ctx context.Context, f *gqlTestFramework) { + f.Mocks.aptos.On("GetAll").Return([]aptoskey.Key{k}, nil) + f.Mocks.keystore.On("Aptos").Return(f.Mocks.aptos) + 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.aptos.On("GetAll").Return([]aptoskey.Key{}, gError) + f.Mocks.keystore.On("Aptos").Return(f.Mocks.aptos) + f.App.On("GetKeyStore").Return(f.Mocks.keystore) + }, + query: query, + result: `null`, + errors: []*gqlerrors.QueryError{ + { + Extensions: nil, + ResolverError: gError, + Path: []interface{}{"aptosKeys"}, + Message: gError.Error(), + }, + }, + }, + } + + RunGQLTests(t, testCases) +} diff --git a/core/web/resolver/query.go b/core/web/resolver/query.go index 9de678adc51..b44ac751db9 100644 --- a/core/web/resolver/query.go +++ b/core/web/resolver/query.go @@ -552,6 +552,19 @@ func (r *Resolver) SolanaKeys(ctx context.Context) (*SolanaKeysPayloadResolver, return NewSolanaKeysPayload(keys), nil } +func (r *Resolver) AptosKeys(ctx context.Context) (*AptosKeysPayloadResolver, error) { + if err := authenticateUser(ctx); err != nil { + return nil, err + } + + keys, err := r.App.GetKeyStore().Aptos().GetAll() + if err != nil { + return nil, err + } + + return NewAptosKeysPayload(keys), nil +} + func (r *Resolver) SQLLogging(ctx context.Context) (*GetSQLLoggingPayloadResolver, error) { if err := authenticateUser(ctx); err != nil { return nil, err diff --git a/core/web/resolver/resolver_test.go b/core/web/resolver/resolver_test.go index 9f3445e1cee..a8af6eae7ff 100644 --- a/core/web/resolver/resolver_test.go +++ b/core/web/resolver/resolver_test.go @@ -51,6 +51,7 @@ type mocks struct { p2p *keystoreMocks.P2P vrf *keystoreMocks.VRF solana *keystoreMocks.Solana + aptos *keystoreMocks.Aptos chain *legacyEvmORMMocks.Chain legacyEVMChains *legacyEvmORMMocks.LegacyChainContainer relayerChainInterops *chainlinkMocks.FakeRelayerChainInteroperators @@ -106,6 +107,7 @@ func setupFramework(t *testing.T) *gqlTestFramework { p2p: keystoreMocks.NewP2P(t), vrf: keystoreMocks.NewVRF(t), solana: keystoreMocks.NewSolana(t), + aptos: keystoreMocks.NewAptos(t), chain: legacyEvmORMMocks.NewChain(t), legacyEVMChains: legacyEvmORMMocks.NewLegacyChainContainer(t), relayerChainInterops: &chainlinkMocks.FakeRelayerChainInteroperators{}, diff --git a/core/web/schema/schema.graphql b/core/web/schema/schema.graphql index 2d0a5a1b1ab..845570c727f 100644 --- a/core/web/schema/schema.graphql +++ b/core/web/schema/schema.graphql @@ -33,6 +33,7 @@ type Query { ocr2KeyBundles: OCR2KeyBundlesPayload! p2pKeys: P2PKeysPayload! solanaKeys: SolanaKeysPayload! + aptosKeys: AptosKeysPayload! sqlLogging: GetSQLLoggingPayload! vrfKey(id: ID!): VRFKeyPayload! vrfKeys: VRFKeysPayload! diff --git a/core/web/schema/type/aptos_key.graphql b/core/web/schema/type/aptos_key.graphql new file mode 100644 index 00000000000..e75c2514c4a --- /dev/null +++ b/core/web/schema/type/aptos_key.graphql @@ -0,0 +1,8 @@ +type AptosKey { + id: ID! + account: String! +} + +type AptosKeysPayload { + results: [AptosKey!]! +} diff --git a/integration-tests/web/sdk/internal/schema.graphql b/integration-tests/web/sdk/internal/schema.graphql index be09d61ec78..2dabf2c774c 100644 --- a/integration-tests/web/sdk/internal/schema.graphql +++ b/integration-tests/web/sdk/internal/schema.graphql @@ -33,6 +33,7 @@ type Query { ocr2KeyBundles: OCR2KeyBundlesPayload! p2pKeys: P2PKeysPayload! solanaKeys: SolanaKeysPayload! + aptosKeys: AptosKeysPayload! sqlLogging: GetSQLLoggingPayload! vrfKey(id: ID!): VRFKeyPayload! vrfKeys: VRFKeysPayload! @@ -99,6 +100,14 @@ type DeleteAPITokenSuccess { } union DeleteAPITokenPayload = DeleteAPITokenSuccess | InputErrors +type AptosKey { + id: ID! + account: String! +} + +type AptosKeysPayload { + results: [AptosKey!]! +} type Bridge { id: ID! name: String!