From 51fed6aa6212c93f97bdf104f9143a270491eeea Mon Sep 17 00:00:00 2001 From: Isha Venikar <145848618+IshaVenikar@users.noreply.github.com> Date: Thu, 4 Jul 2024 19:33:10 +0530 Subject: [PATCH] Add a method to get registered participants (#6) * Add getParticipant query method for getting participants list * Add check to verify the list of registered participants in onboarding-test * Modify test messages * Add updated proto files and regenerate ts bindings * Update proto files and regenerate ts bindings * Fix imports --- proto/cerc/onboarding/v1/onboarding.proto | 6 +- proto/cerc/onboarding/v1/query.proto | 28 +++ proto/cerc/onboarding/v1/tx.proto | 3 +- src/index.ts | 7 + src/onboarding.test.ts | 29 ++- src/proto/cerc/onboarding/v1/onboarding.ts | 32 ++- src/proto/cerc/onboarding/v1/query.ts | 248 +++++++++++++++++++++ src/proto/cerc/onboarding/v1/tx.ts | 17 +- src/registry-client.ts | 20 +- src/testing/data/watcher.yml | 2 +- 10 files changed, 357 insertions(+), 35 deletions(-) diff --git a/proto/cerc/onboarding/v1/onboarding.proto b/proto/cerc/onboarding/v1/onboarding.proto index 371de6e..876cc7e 100644 --- a/proto/cerc/onboarding/v1/onboarding.proto +++ b/proto/cerc/onboarding/v1/onboarding.proto @@ -7,7 +7,11 @@ import "gogoproto/gogo.proto"; option go_package = "git.vdb.to/cerc-io/laconicd/x/onboarding"; // Params defines the parameters of the onboarding module. -message Params {} +message Params { + bool onboarding_enabled = 1 [ + (gogoproto.moretags) = "json:\"onboarding_enabled\" yaml:\"onboarding_enabled\"" + ]; +} // Participant defines the data that will be stored for each enrolled participant message Participant { diff --git a/proto/cerc/onboarding/v1/query.proto b/proto/cerc/onboarding/v1/query.proto index e3801fe..1345bb8 100644 --- a/proto/cerc/onboarding/v1/query.proto +++ b/proto/cerc/onboarding/v1/query.proto @@ -2,4 +2,32 @@ syntax = "proto3"; package cerc.onboarding.v1; +import "gogoproto/gogo.proto"; +import "cosmos/base/query/v1beta1/pagination.proto"; +import "cerc/onboarding/v1/onboarding.proto"; +import "google/api/annotations.proto"; + option go_package = "git.vdb.to/cerc-io/laconicd/x/onboarding"; + +// Query defines the gRPC querier service for onboarding module +service Query { + // Participants queries Participants list + rpc Participants(QueryParticipantsRequest) returns (QueryParticipantsResponse) { + option (google.api.http).get = "/cerc/onboarding/v1/participants"; + } +} + +// QueryParticipantsRequest queries participants +message QueryParticipantsRequest { + // pagination defines an optional pagination for the request. + cosmos.base.query.v1beta1.PageRequest pagination = 1; +} + +// QueryParticipantsResponse is response type for get the participants +message QueryParticipantsResponse { + repeated Participant participants = 1 + [ (gogoproto.moretags) = "json:\"participants\" yaml:\"participants\"" ]; + + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} diff --git a/proto/cerc/onboarding/v1/tx.proto b/proto/cerc/onboarding/v1/tx.proto index 18e87cd..bf07de5 100644 --- a/proto/cerc/onboarding/v1/tx.proto +++ b/proto/cerc/onboarding/v1/tx.proto @@ -3,8 +3,8 @@ syntax = "proto3"; package cerc.onboarding.v1; import "cosmos/msg/v1/msg.proto"; -import "gogoproto/gogo.proto"; import "google/api/annotations.proto"; +import "gogoproto/gogo.proto"; import "cerc/onboarding/v1/onboarding.proto"; option go_package = "git.vdb.to/cerc-io/laconicd/x/onboarding"; @@ -28,7 +28,6 @@ message MsgOnboardParticipant { string participant = 1; EthPayload eth_payload = 2 [ (gogoproto.nullable) = false ]; string eth_signature = 3; - string message = 4; } // MsgOnboardParticipantResponse defines the Msg/OnboardParticipant response type. diff --git a/src/index.ts b/src/index.ts index 0f3014f..e94de8a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -453,6 +453,13 @@ export class Registry { fee ); } + + /** + * Query participants. + */ + async getParticipants () { + return this._client.getParticipants(); + } } export { Account }; diff --git a/src/onboarding.test.ts b/src/onboarding.test.ts index f299ec2..ea8f1f1 100644 --- a/src/onboarding.test.ts +++ b/src/onboarding.test.ts @@ -1,5 +1,7 @@ import { Wallet } from 'ethers'; +import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; + import { Registry, Account } from './index'; import { getConfig } from './testing/helper'; @@ -9,31 +11,46 @@ jest.setTimeout(90 * 1000); const onboardingTests = () => { let registry: Registry; + let ethWallet: Wallet; beforeAll(async () => { registry = new Registry(gqlEndpoint, rpcEndpoint, chainId); }); test('Onboard participant.', async () => { - const mnenonic = Account.generateMnemonic(); - let wallet = Wallet.fromMnemonic(mnenonic); + const mnemonic = Account.generateMnemonic(); + ethWallet = Wallet.fromMnemonic(mnemonic); const ethPayload = { - address: wallet.address, + address: ethWallet.address, msg: 'Message signed by ethereum private key' }; const message = JSON.stringify(ethPayload); - - const ethSignature = await wallet.signMessage(message); + const ethSignature = await ethWallet.signMessage(message); await registry.onboardParticipant({ ethPayload, ethSignature, message: 'Message signed by cosmos private key' }, privateKey, fee); + }); - // TODO: Verify participant getting stored in state + describe('With participants enrolled', () => { + test('Query participants.', async () => { + const account = new Account(Buffer.from(privateKey, 'hex')); + const cosmosAccount = await DirectSecp256k1Wallet.fromKey(account._privateKey, 'laconic'); + const [cosmosWallet] = await cosmosAccount.getAccounts(); + + const expectedParticipants = [ + { + cosmos_address: cosmosWallet.address, + ethereum_address: ethWallet.address + } + ]; + const participants = await registry.getParticipants(); + expect(participants).toEqual(expectedParticipants); + }); }); }; diff --git a/src/proto/cerc/onboarding/v1/onboarding.ts b/src/proto/cerc/onboarding/v1/onboarding.ts index fba3b5f..9c514e6 100644 --- a/src/proto/cerc/onboarding/v1/onboarding.ts +++ b/src/proto/cerc/onboarding/v1/onboarding.ts @@ -5,7 +5,9 @@ import _m0 from "protobufjs/minimal"; export const protobufPackage = "cerc.onboarding.v1"; /** Params defines the parameters of the onboarding module. */ -export interface Params {} +export interface Params { + onboardingEnabled: boolean; +} /** Participant defines the data that will be stored for each enrolled participant */ export interface Participant { @@ -20,11 +22,17 @@ export interface EthPayload { } function createBaseParams(): Params { - return {}; + return { onboardingEnabled: false }; } export const Params = { - encode(_: Params, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + encode( + message: Params, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (message.onboardingEnabled === true) { + writer.uint32(8).bool(message.onboardingEnabled); + } return writer; }, @@ -35,6 +43,9 @@ export const Params = { while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { + case 1: + message.onboardingEnabled = reader.bool(); + break; default: reader.skipType(tag & 7); break; @@ -43,17 +54,24 @@ export const Params = { return message; }, - fromJSON(_: any): Params { - return {}; + fromJSON(object: any): Params { + return { + onboardingEnabled: isSet(object.onboardingEnabled) + ? Boolean(object.onboardingEnabled) + : false, + }; }, - toJSON(_: Params): unknown { + toJSON(message: Params): unknown { const obj: any = {}; + message.onboardingEnabled !== undefined && + (obj.onboardingEnabled = message.onboardingEnabled); return obj; }, - fromPartial, I>>(_: I): Params { + fromPartial, I>>(object: I): Params { const message = createBaseParams(); + message.onboardingEnabled = object.onboardingEnabled ?? false; return message; }, }; diff --git a/src/proto/cerc/onboarding/v1/query.ts b/src/proto/cerc/onboarding/v1/query.ts index 8cf9ffe..7c0d0e0 100644 --- a/src/proto/cerc/onboarding/v1/query.ts +++ b/src/proto/cerc/onboarding/v1/query.ts @@ -1,2 +1,250 @@ /* eslint-disable */ +import { + PageRequest, + PageResponse, +} from "../../../cosmos/base/query/v1beta1/pagination"; +import Long from "long"; +import { Participant } from "./onboarding"; +import _m0 from "protobufjs/minimal"; + export const protobufPackage = "cerc.onboarding.v1"; + +/** QueryParticipantsRequest queries participants */ +export interface QueryParticipantsRequest { + /** pagination defines an optional pagination for the request. */ + pagination?: PageRequest; +} + +/** QueryParticipantsResponse is response type for get the participants */ +export interface QueryParticipantsResponse { + participants: Participant[]; + /** pagination defines the pagination in the response. */ + pagination?: PageResponse; +} + +function createBaseQueryParticipantsRequest(): QueryParticipantsRequest { + return { pagination: undefined }; +} + +export const QueryParticipantsRequest = { + encode( + message: QueryParticipantsRequest, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (message.pagination !== undefined) { + PageRequest.encode(message.pagination, writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode( + input: _m0.Reader | Uint8Array, + length?: number + ): QueryParticipantsRequest { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryParticipantsRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.pagination = PageRequest.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): QueryParticipantsRequest { + return { + pagination: isSet(object.pagination) + ? PageRequest.fromJSON(object.pagination) + : undefined, + }; + }, + + toJSON(message: QueryParticipantsRequest): unknown { + const obj: any = {}; + message.pagination !== undefined && + (obj.pagination = message.pagination + ? PageRequest.toJSON(message.pagination) + : undefined); + return obj; + }, + + fromPartial, I>>( + object: I + ): QueryParticipantsRequest { + const message = createBaseQueryParticipantsRequest(); + message.pagination = + object.pagination !== undefined && object.pagination !== null + ? PageRequest.fromPartial(object.pagination) + : undefined; + return message; + }, +}; + +function createBaseQueryParticipantsResponse(): QueryParticipantsResponse { + return { participants: [], pagination: undefined }; +} + +export const QueryParticipantsResponse = { + encode( + message: QueryParticipantsResponse, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + for (const v of message.participants) { + Participant.encode(v!, writer.uint32(10).fork()).ldelim(); + } + if (message.pagination !== undefined) { + PageResponse.encode( + message.pagination, + writer.uint32(18).fork() + ).ldelim(); + } + return writer; + }, + + decode( + input: _m0.Reader | Uint8Array, + length?: number + ): QueryParticipantsResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryParticipantsResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.participants.push( + Participant.decode(reader, reader.uint32()) + ); + break; + case 2: + message.pagination = PageResponse.decode(reader, reader.uint32()); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): QueryParticipantsResponse { + return { + participants: Array.isArray(object?.participants) + ? object.participants.map((e: any) => Participant.fromJSON(e)) + : [], + pagination: isSet(object.pagination) + ? PageResponse.fromJSON(object.pagination) + : undefined, + }; + }, + + toJSON(message: QueryParticipantsResponse): unknown { + const obj: any = {}; + if (message.participants) { + obj.participants = message.participants.map((e) => + e ? Participant.toJSON(e) : undefined + ); + } else { + obj.participants = []; + } + message.pagination !== undefined && + (obj.pagination = message.pagination + ? PageResponse.toJSON(message.pagination) + : undefined); + return obj; + }, + + fromPartial, I>>( + object: I + ): QueryParticipantsResponse { + const message = createBaseQueryParticipantsResponse(); + message.participants = + object.participants?.map((e) => Participant.fromPartial(e)) || []; + message.pagination = + object.pagination !== undefined && object.pagination !== null + ? PageResponse.fromPartial(object.pagination) + : undefined; + return message; + }, +}; + +/** Query defines the gRPC querier service for onboarding module */ +export interface Query { + /** Participants queries Participants list */ + Participants( + request: QueryParticipantsRequest + ): Promise; +} + +export class QueryClientImpl implements Query { + private readonly rpc: Rpc; + constructor(rpc: Rpc) { + this.rpc = rpc; + this.Participants = this.Participants.bind(this); + } + Participants( + request: QueryParticipantsRequest + ): Promise { + const data = QueryParticipantsRequest.encode(request).finish(); + const promise = this.rpc.request( + "cerc.onboarding.v1.Query", + "Participants", + data + ); + return promise.then((data) => + QueryParticipantsResponse.decode(new _m0.Reader(data)) + ); + } +} + +interface Rpc { + request( + service: string, + method: string, + data: Uint8Array + ): Promise; +} + +type Builtin = + | Date + | Function + | Uint8Array + | string + | number + | boolean + | undefined; + +export type DeepPartial = T extends Builtin + ? T + : T extends Long + ? string | number | Long + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial; + +type KeysOfUnion = T extends T ? keyof T : never; +export type Exact = P extends Builtin + ? P + : P & { [K in keyof P]: Exact } & { + [K in Exclude>]: never; + }; + +if (_m0.util.Long !== Long) { + _m0.util.Long = Long as any; + _m0.configure(); +} + +function isSet(value: any): boolean { + return value !== null && value !== undefined; +} diff --git a/src/proto/cerc/onboarding/v1/tx.ts b/src/proto/cerc/onboarding/v1/tx.ts index 977498f..3897ffd 100644 --- a/src/proto/cerc/onboarding/v1/tx.ts +++ b/src/proto/cerc/onboarding/v1/tx.ts @@ -11,19 +11,13 @@ export interface MsgOnboardParticipant { participant: string; ethPayload?: EthPayload; ethSignature: string; - message: string; } /** MsgOnboardParticipantResponse defines the Msg/OnboardParticipant response type. */ export interface MsgOnboardParticipantResponse {} function createBaseMsgOnboardParticipant(): MsgOnboardParticipant { - return { - participant: "", - ethPayload: undefined, - ethSignature: "", - message: "", - }; + return { participant: "", ethPayload: undefined, ethSignature: "" }; } export const MsgOnboardParticipant = { @@ -40,9 +34,6 @@ export const MsgOnboardParticipant = { if (message.ethSignature !== "") { writer.uint32(26).string(message.ethSignature); } - if (message.message !== "") { - writer.uint32(34).string(message.message); - } return writer; }, @@ -65,9 +56,6 @@ export const MsgOnboardParticipant = { case 3: message.ethSignature = reader.string(); break; - case 4: - message.message = reader.string(); - break; default: reader.skipType(tag & 7); break; @@ -85,7 +73,6 @@ export const MsgOnboardParticipant = { ethSignature: isSet(object.ethSignature) ? String(object.ethSignature) : "", - message: isSet(object.message) ? String(object.message) : "", }; }, @@ -99,7 +86,6 @@ export const MsgOnboardParticipant = { : undefined); message.ethSignature !== undefined && (obj.ethSignature = message.ethSignature); - message.message !== undefined && (obj.message = message.message); return obj; }, @@ -113,7 +99,6 @@ export const MsgOnboardParticipant = { ? EthPayload.fromPartial(object.ethPayload) : undefined; message.ethSignature = object.ethSignature ?? ""; - message.message = object.message ?? ""; return message; }, }; diff --git a/src/registry-client.ts b/src/registry-client.ts index 69d9ab5..4d2caef 100644 --- a/src/registry-client.ts +++ b/src/registry-client.ts @@ -241,7 +241,7 @@ export class RegistryClient { /** * Get records by attributes. */ - async queryRecords (attributes: {[key: string]: any}, all = false, refs = false) { + async queryRecords (attributes: { [key: string]: any }, all = false, refs = false) { if (!attributes) { attributes = {}; } @@ -397,7 +397,7 @@ export class RegistryClient { } /** - * Get records by attributes. + * Get bonds by attributes. */ async queryBonds (attributes = {}) { const query = `query ($attributes: [KeyValueInput!]) { @@ -417,4 +417,20 @@ export class RegistryClient { return RegistryClient.getResult(this._graph(query)(variables), 'queryBonds'); } + + /** + * Get participants. + */ + async getParticipants () { + const query = `query { + getParticipants { + cosmos_address + ethereum_address + } + }`; + + const variables = {}; + + return RegistryClient.getResult(this._graph(query)(variables), 'getParticipants'); + } } diff --git a/src/testing/data/watcher.yml b/src/testing/data/watcher.yml index dddddab..23356e5 100644 --- a/src/testing/data/watcher.yml +++ b/src/testing/data/watcher.yml @@ -7,4 +7,4 @@ record: /: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9 tls_cert_cid: /: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR - version: 1.0.28 + version: 1.0.30