diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 056bb47..da0099a 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -4,13 +4,14 @@ Run following scripts when [proto files](./proto/) are updated. -1. Install dependencies - ```bash - yarn - ``` +* Install dependencies: -2. Generate typescript code for the proto files + ```bash + yarn + ``` - ```bash - ./scripts/proto-gen.sh - ``` +* Generate typescript bindings for the proto files: + + ```bash + ./scripts/proto-gen.sh + ``` diff --git a/package.json b/package.json index 199abd6..63a8da6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cerc-io/registry-sdk", - "version": "0.2.2", + "version": "0.2.3", "main": "dist/index.js", "types": "dist/index.d.ts", "repository": "git@github.com:cerc-io/registry-sdk.git", diff --git a/proto/cerc/onboarding/v1/onboarding.proto b/proto/cerc/onboarding/v1/onboarding.proto index cda954a..002dc6a 100644 --- a/proto/cerc/onboarding/v1/onboarding.proto +++ b/proto/cerc/onboarding/v1/onboarding.proto @@ -8,28 +8,36 @@ option go_package = "git.vdb.to/cerc-io/laconicd/x/onboarding"; // Params defines the parameters of the onboarding module. message Params { - bool onboarding_enabled = 1 [ - (gogoproto.moretags) = "json:\"onboarding_enabled\" yaml:\"onboarding_enabled\"" - ]; + bool onboarding_enabled = 1 + [ (gogoproto.moretags) = + "json:\"onboarding_enabled\" yaml:\"onboarding_enabled\"" ]; } -// Participant defines the data that will be stored for each enrolled participant +// Participant defines the data that will be stored for each enrolled +// participant message Participant { - string cosmos_address = 1 [ - (gogoproto.moretags) = "json:\"cosmos_address\" yaml:\"cosmos_address\"" - ]; + // participant's cosmos (laconic) address + string cosmos_address = 1 + [ (gogoproto.moretags) = + "json:\"cosmos_address\" yaml:\"cosmos_address\"" ]; - string nitro_address = 2 [ - (gogoproto.moretags) = "json:\"nitro_address\" yaml:\"nitro_address\"" - ]; + // participant's Nitro address + string nitro_address = 2 + [ (gogoproto.moretags) = + "json:\"nitro_address\" yaml:\"nitro_address\"" ]; + + // participant's role (participant | validator) + string role = 3 [ (gogoproto.moretags) = "json:\"role\" yaml:\"role\"" ]; + + // participant's KYC receipt ID + string kyc_id = 4 + [ (gogoproto.moretags) = "json:\"kyc_id\" yaml:\"kyc_id\"" ]; } + // EthPayload defines the payload that is signed by the ethereum private key message EthPayload { - string address = 1 [ - (gogoproto.moretags) = "json:\"address\" yaml:\"address\"" - ]; + string address = 1 + [ (gogoproto.moretags) = "json:\"address\" yaml:\"address\"" ]; - string msg = 2 [ - (gogoproto.moretags) = "json:\"msg\" yaml:\"msg\"" - ]; + string msg = 2 [ (gogoproto.moretags) = "json:\"msg\" yaml:\"msg\"" ]; } diff --git a/proto/cerc/onboarding/v1/query.proto b/proto/cerc/onboarding/v1/query.proto index 1345bb8..bbcfc87 100644 --- a/proto/cerc/onboarding/v1/query.proto +++ b/proto/cerc/onboarding/v1/query.proto @@ -12,7 +12,8 @@ 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) { + rpc Participants(QueryParticipantsRequest) + returns (QueryParticipantsResponse) { option (google.api.http).get = "/cerc/onboarding/v1/participants"; } } diff --git a/proto/cerc/onboarding/v1/tx.proto b/proto/cerc/onboarding/v1/tx.proto index bf07de5..6e0eab6 100644 --- a/proto/cerc/onboarding/v1/tx.proto +++ b/proto/cerc/onboarding/v1/tx.proto @@ -15,9 +15,9 @@ service Msg { // OnboardParticipant defines a method for enrolling a new validator. rpc OnboardParticipant(MsgOnboardParticipant) - returns (MsgOnboardParticipantResponse) { - option (google.api.http).post = "/cerc/onboarding/v1/onboard_participant"; - }; + returns (MsgOnboardParticipantResponse) { + option (google.api.http).post = "/cerc/onboarding/v1/onboard_participant"; + }; } // MsgOnboardParticipant defines a SDK message for enrolling a new validator. @@ -28,7 +28,10 @@ message MsgOnboardParticipant { string participant = 1; EthPayload eth_payload = 2 [ (gogoproto.nullable) = false ]; string eth_signature = 3; + string role = 4; + string kyc_id = 5; } -// MsgOnboardParticipantResponse defines the Msg/OnboardParticipant response type. +// MsgOnboardParticipantResponse defines the Msg/OnboardParticipant response +// type. message MsgOnboardParticipantResponse {} diff --git a/proto/cerc/registry/v1/query.proto b/proto/cerc/registry/v1/query.proto index 3bc1909..1d3052f 100644 --- a/proto/cerc/registry/v1/query.proto +++ b/proto/cerc/registry/v1/query.proto @@ -58,6 +58,11 @@ service Query { returns (QueryGetRegistryModuleBalanceResponse) { option (google.api.http).get = "/cerc/registry/v1/balance"; } + + // Authorities queries all authorities + rpc Authorities(QueryAuthoritiesRequest) returns (QueryAuthoritiesResponse) { + option (google.api.http).get = "/cerc/registry/v1/authorities"; + } } // QueryParamsRequest is request type for registry params @@ -152,6 +157,16 @@ message QueryWhoisResponse { ]; } +// QueryAuthoritiesRequest is request type to get all authorities +message QueryAuthoritiesRequest { string owner = 1; } + +// QueryAuthoritiesResponse is response type for authorities request +message QueryAuthoritiesResponse { + repeated AuthorityEntry authorities = 1 [ (gogoproto.nullable) = false ]; + // pagination defines the pagination in the response. + cosmos.base.query.v1beta1.PageResponse pagination = 2; +} + // QueryLookupLrnRequest is request type for LookupLrn message QueryLookupLrnRequest { string lrn = 1; } diff --git a/src/index.ts b/src/index.ts index b3b128e..cf586ae 100644 --- a/src/index.ts +++ b/src/index.ts @@ -440,7 +440,7 @@ export class Registry { /** * Onboard participant. */ - async onboardParticipant ({ ethPayload, ethSignature }: MessageMsgOnboardParticipant, privateKey: string, fee: StdFee): Promise { + async onboardParticipant ({ ethPayload, ethSignature, role, kycId }: MessageMsgOnboardParticipant, privateKey: string, fee: StdFee): Promise { const account = new Account(Buffer.from(privateKey, 'hex')); await account.init(); const laconicClient = await this.getLaconicClient(account); @@ -449,6 +449,8 @@ export class Registry { account.address, ethPayload, ethSignature, + role, + kycId, fee ); } diff --git a/src/laconic-client.ts b/src/laconic-client.ts index a96b4eb..551393d 100644 --- a/src/laconic-client.ts +++ b/src/laconic-client.ts @@ -394,6 +394,8 @@ export class LaconicClient extends SigningStargateClient { signer: string, ethPayload: EthPayload, ethSignature: string, + role: string, + kycId: string, fee: StdFee | 'auto' | number, memo = '' ) { @@ -402,7 +404,9 @@ export class LaconicClient extends SigningStargateClient { value: { participant: signer, ethPayload, - ethSignature + ethSignature, + role, + kycId } }; diff --git a/src/onboarding.test.ts b/src/onboarding.test.ts index 3f6ac4b..3c7c80e 100644 --- a/src/onboarding.test.ts +++ b/src/onboarding.test.ts @@ -10,6 +10,9 @@ const { chainId, rpcEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); jest.setTimeout(90 * 1000); +const DUMMY_ROLE = 'validator'; +const DUMMY_KYC_ID = 'dummyKycId'; + const onboardingEnabledTests = () => { let registry: Registry; let ethWallet: Wallet; @@ -32,7 +35,9 @@ const onboardingEnabledTests = () => { await registry.onboardParticipant({ ethPayload, - ethSignature + ethSignature, + role: DUMMY_ROLE, + kycId: DUMMY_KYC_ID }, privateKey, fee); }); @@ -41,10 +46,12 @@ const onboardingEnabledTests = () => { const cosmosAccount = await DirectSecp256k1Wallet.fromKey(account._privateKey, 'laconic'); const [cosmosWallet] = await cosmosAccount.getAccounts(); - const expectedParticipants = [ + const expectedParticipants: Participant[] = [ { cosmosAddress: cosmosWallet.address, - nitroAddress: ethWallet.address + nitroAddress: ethWallet.address, + role: DUMMY_ROLE, + kycId: DUMMY_KYC_ID } ]; const participants = await registry.getParticipants(); @@ -76,7 +83,9 @@ const onboardingDisabledTests = () => { try { await registry.onboardParticipant({ ethPayload, - ethSignature + ethSignature, + role: DUMMY_ROLE, + kycId: DUMMY_KYC_ID }, privateKey, fee); } catch (error: any) { expect(error.toString()).toContain(errorMsg); diff --git a/src/proto/cerc/onboarding/v1/onboarding.ts b/src/proto/cerc/onboarding/v1/onboarding.ts index 445b4cf..4c65d15 100644 --- a/src/proto/cerc/onboarding/v1/onboarding.ts +++ b/src/proto/cerc/onboarding/v1/onboarding.ts @@ -9,10 +9,19 @@ export interface Params { onboardingEnabled: boolean; } -/** Participant defines the data that will be stored for each enrolled participant */ +/** + * Participant defines the data that will be stored for each enrolled + * participant + */ export interface Participant { + /** participant's cosmos (laconic) address */ cosmosAddress: string; + /** participant's Nitro address */ nitroAddress: string; + /** participant's role (participant | validator) */ + role: string; + /** participant's KYC receipt ID */ + kycId: string; } /** EthPayload defines the payload that is signed by the ethereum private key */ @@ -77,7 +86,7 @@ export const Params = { }; function createBaseParticipant(): Participant { - return { cosmosAddress: "", nitroAddress: "" }; + return { cosmosAddress: "", nitroAddress: "", role: "", kycId: "" }; } export const Participant = { @@ -91,6 +100,12 @@ export const Participant = { if (message.nitroAddress !== "") { writer.uint32(18).string(message.nitroAddress); } + if (message.role !== "") { + writer.uint32(26).string(message.role); + } + if (message.kycId !== "") { + writer.uint32(34).string(message.kycId); + } return writer; }, @@ -107,6 +122,12 @@ export const Participant = { case 2: message.nitroAddress = reader.string(); break; + case 3: + message.role = reader.string(); + break; + case 4: + message.kycId = reader.string(); + break; default: reader.skipType(tag & 7); break; @@ -123,6 +144,8 @@ export const Participant = { nitroAddress: isSet(object.nitroAddress) ? String(object.nitroAddress) : "", + role: isSet(object.role) ? String(object.role) : "", + kycId: isSet(object.kycId) ? String(object.kycId) : "", }; }, @@ -132,6 +155,8 @@ export const Participant = { (obj.cosmosAddress = message.cosmosAddress); message.nitroAddress !== undefined && (obj.nitroAddress = message.nitroAddress); + message.role !== undefined && (obj.role = message.role); + message.kycId !== undefined && (obj.kycId = message.kycId); return obj; }, @@ -141,6 +166,8 @@ export const Participant = { const message = createBaseParticipant(); message.cosmosAddress = object.cosmosAddress ?? ""; message.nitroAddress = object.nitroAddress ?? ""; + message.role = object.role ?? ""; + message.kycId = object.kycId ?? ""; return message; }, }; diff --git a/src/proto/cerc/onboarding/v1/tx.ts b/src/proto/cerc/onboarding/v1/tx.ts index 3897ffd..085a6d5 100644 --- a/src/proto/cerc/onboarding/v1/tx.ts +++ b/src/proto/cerc/onboarding/v1/tx.ts @@ -11,13 +11,24 @@ export interface MsgOnboardParticipant { participant: string; ethPayload?: EthPayload; ethSignature: string; + role: string; + kycId: string; } -/** MsgOnboardParticipantResponse defines the Msg/OnboardParticipant response type. */ +/** + * MsgOnboardParticipantResponse defines the Msg/OnboardParticipant response + * type. + */ export interface MsgOnboardParticipantResponse {} function createBaseMsgOnboardParticipant(): MsgOnboardParticipant { - return { participant: "", ethPayload: undefined, ethSignature: "" }; + return { + participant: "", + ethPayload: undefined, + ethSignature: "", + role: "", + kycId: "", + }; } export const MsgOnboardParticipant = { @@ -34,6 +45,12 @@ export const MsgOnboardParticipant = { if (message.ethSignature !== "") { writer.uint32(26).string(message.ethSignature); } + if (message.role !== "") { + writer.uint32(34).string(message.role); + } + if (message.kycId !== "") { + writer.uint32(42).string(message.kycId); + } return writer; }, @@ -56,6 +73,12 @@ export const MsgOnboardParticipant = { case 3: message.ethSignature = reader.string(); break; + case 4: + message.role = reader.string(); + break; + case 5: + message.kycId = reader.string(); + break; default: reader.skipType(tag & 7); break; @@ -73,6 +96,8 @@ export const MsgOnboardParticipant = { ethSignature: isSet(object.ethSignature) ? String(object.ethSignature) : "", + role: isSet(object.role) ? String(object.role) : "", + kycId: isSet(object.kycId) ? String(object.kycId) : "", }; }, @@ -86,6 +111,8 @@ export const MsgOnboardParticipant = { : undefined); message.ethSignature !== undefined && (obj.ethSignature = message.ethSignature); + message.role !== undefined && (obj.role = message.role); + message.kycId !== undefined && (obj.kycId = message.kycId); return obj; }, @@ -99,6 +126,8 @@ export const MsgOnboardParticipant = { ? EthPayload.fromPartial(object.ethPayload) : undefined; message.ethSignature = object.ethSignature ?? ""; + message.role = object.role ?? ""; + message.kycId = object.kycId ?? ""; return message; }, }; diff --git a/src/proto/cerc/registry/v1/query.ts b/src/proto/cerc/registry/v1/query.ts index 7f00354..f1fa3e9 100644 --- a/src/proto/cerc/registry/v1/query.ts +++ b/src/proto/cerc/registry/v1/query.ts @@ -5,6 +5,7 @@ import { NameAuthority, NameRecord, NameEntry, + AuthorityEntry, } from "./registry"; import { PageRequest, @@ -118,6 +119,18 @@ export interface QueryWhoisResponse { nameAuthority?: NameAuthority; } +/** QueryAuthoritiesRequest is request type to get all authorities */ +export interface QueryAuthoritiesRequest { + owner: string; +} + +/** QueryAuthoritiesResponse is response type for authorities request */ +export interface QueryAuthoritiesResponse { + authorities: AuthorityEntry[]; + /** pagination defines the pagination in the response. */ + pagination?: PageResponse; +} + /** QueryLookupLrnRequest is request type for LookupLrn */ export interface QueryLookupLrnRequest { lrn: string; @@ -1460,6 +1473,151 @@ export const QueryWhoisResponse = { }, }; +function createBaseQueryAuthoritiesRequest(): QueryAuthoritiesRequest { + return { owner: "" }; +} + +export const QueryAuthoritiesRequest = { + encode( + message: QueryAuthoritiesRequest, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + if (message.owner !== "") { + writer.uint32(10).string(message.owner); + } + return writer; + }, + + decode( + input: _m0.Reader | Uint8Array, + length?: number + ): QueryAuthoritiesRequest { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryAuthoritiesRequest(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.owner = reader.string(); + break; + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }, + + fromJSON(object: any): QueryAuthoritiesRequest { + return { + owner: isSet(object.owner) ? String(object.owner) : "", + }; + }, + + toJSON(message: QueryAuthoritiesRequest): unknown { + const obj: any = {}; + message.owner !== undefined && (obj.owner = message.owner); + return obj; + }, + + fromPartial, I>>( + object: I + ): QueryAuthoritiesRequest { + const message = createBaseQueryAuthoritiesRequest(); + message.owner = object.owner ?? ""; + return message; + }, +}; + +function createBaseQueryAuthoritiesResponse(): QueryAuthoritiesResponse { + return { authorities: [], pagination: undefined }; +} + +export const QueryAuthoritiesResponse = { + encode( + message: QueryAuthoritiesResponse, + writer: _m0.Writer = _m0.Writer.create() + ): _m0.Writer { + for (const v of message.authorities) { + AuthorityEntry.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 + ): QueryAuthoritiesResponse { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseQueryAuthoritiesResponse(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + message.authorities.push( + AuthorityEntry.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): QueryAuthoritiesResponse { + return { + authorities: Array.isArray(object?.authorities) + ? object.authorities.map((e: any) => AuthorityEntry.fromJSON(e)) + : [], + pagination: isSet(object.pagination) + ? PageResponse.fromJSON(object.pagination) + : undefined, + }; + }, + + toJSON(message: QueryAuthoritiesResponse): unknown { + const obj: any = {}; + if (message.authorities) { + obj.authorities = message.authorities.map((e) => + e ? AuthorityEntry.toJSON(e) : undefined + ); + } else { + obj.authorities = []; + } + message.pagination !== undefined && + (obj.pagination = message.pagination + ? PageResponse.toJSON(message.pagination) + : undefined); + return obj; + }, + + fromPartial, I>>( + object: I + ): QueryAuthoritiesResponse { + const message = createBaseQueryAuthoritiesResponse(); + message.authorities = + object.authorities?.map((e) => AuthorityEntry.fromPartial(e)) || []; + message.pagination = + object.pagination !== undefined && object.pagination !== null + ? PageResponse.fromPartial(object.pagination) + : undefined; + return message; + }, +}; + function createBaseQueryLookupLrnRequest(): QueryLookupLrnRequest { return { lrn: "" }; } @@ -1907,6 +2065,10 @@ export interface Query { GetRegistryModuleBalance( request: QueryGetRegistryModuleBalanceRequest ): Promise; + /** Authorities queries all authorities */ + Authorities( + request: QueryAuthoritiesRequest + ): Promise; } export class QueryClientImpl implements Query { @@ -1922,6 +2084,7 @@ export class QueryClientImpl implements Query { this.LookupLrn = this.LookupLrn.bind(this); this.ResolveLrn = this.ResolveLrn.bind(this); this.GetRegistryModuleBalance = this.GetRegistryModuleBalance.bind(this); + this.Authorities = this.Authorities.bind(this); } Params(request: QueryParamsRequest): Promise { const data = QueryParamsRequest.encode(request).finish(); @@ -2026,6 +2189,20 @@ export class QueryClientImpl implements Query { QueryGetRegistryModuleBalanceResponse.decode(new _m0.Reader(data)) ); } + + Authorities( + request: QueryAuthoritiesRequest + ): Promise { + const data = QueryAuthoritiesRequest.encode(request).finish(); + const promise = this.rpc.request( + "cerc.registry.v1.Query", + "Authorities", + data + ); + return promise.then((data) => + QueryAuthoritiesResponse.decode(new _m0.Reader(data)) + ); + } } interface Rpc { diff --git a/src/registry-client.ts b/src/registry-client.ts index bf28a75..5191be2 100644 --- a/src/registry-client.ts +++ b/src/registry-client.ts @@ -426,6 +426,8 @@ export class RegistryClient { getParticipants { cosmosAddress nitroAddress + role + kycId } }`; diff --git a/src/types/cerc/onboarding/message.ts b/src/types/cerc/onboarding/message.ts index edbeccf..750fca2 100644 --- a/src/types/cerc/onboarding/message.ts +++ b/src/types/cerc/onboarding/message.ts @@ -12,7 +12,7 @@ export const onboardingTypes: ReadonlyArray<[string, GeneratedType]> = [ export interface MsgOnboardParticipantEncodeObject extends EncodeObject { readonly typeUrl: '/cerc.onboarding.v1.MsgOnboardParticipant'; - readonly value: Partial; + readonly value: MsgOnboardParticipant; } interface ethPayload { @@ -23,4 +23,6 @@ interface ethPayload { export interface MessageMsgOnboardParticipant { ethPayload: ethPayload ethSignature: string + role: string + kycId: string }