From 0698971f259944005740262feaa566c5c63191dd Mon Sep 17 00:00:00 2001 From: neeraj Date: Fri, 8 Mar 2024 11:49:11 +0530 Subject: [PATCH 1/7] Add todo for skipped and failed tests --- src/nameservice-expiry.test.ts | 22 +++++++++++++--------- src/naming.test.ts | 1 + src/sdk.test.ts | 32 ++++++++++++++++++-------------- src/util.test.ts | 7 ++++--- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/nameservice-expiry.test.ts b/src/nameservice-expiry.test.ts index e3de619..771c83f 100644 --- a/src/nameservice-expiry.test.ts +++ b/src/nameservice-expiry.test.ts @@ -1,13 +1,15 @@ import path from 'path'; import { Registry } from './index'; -import { ensureUpdatedConfig, getConfig } from './testing/helper'; +import { ensureUpdatedConfig, getConfig, getLaconic2Config } from './testing/helper'; +import { DENOM } from './constants'; const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); jest.setTimeout(120 * 1000); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); +const { fee: laconic2Fee } = getLaconic2Config(); const nameserviceExpiryTests = () => { let registry: Registry; @@ -24,10 +26,10 @@ const nameserviceExpiryTests = () => { // Create bond. bondId = await registry.getNextBondId(privateKey); - await registry.createBond({ denom: 'aphoton', amount: '3000000' }, privateKey, fee); + await registry.createBond({ denom: DENOM, amount: '3000000' }, privateKey, laconic2Fee); }); - test('Set record and check bond balance', async () => { + xtest('Set record and check bond balance', async () => { // Create watcher. watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); const result = await registry.setRecord( @@ -51,8 +53,8 @@ const nameserviceExpiryTests = () => { test('Reserve authority and set bond', async () => { authorityName = `laconic-${Date.now()}`; - await registry.reserveAuthority({ name: authorityName }, privateKey, fee); - await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, fee); + await registry.reserveAuthority({ name: authorityName }, privateKey, laconic2Fee); + await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, laconic2Fee); const [authority] = await registry.lookupAuthorities([authorityName]); expect(authority.status).toBe('active'); authorityExpiryTime = new Date(authority.expiryTime); @@ -62,7 +64,7 @@ const nameserviceExpiryTests = () => { setTimeout(done, 60 * 1000); }); - test('Check record expiry time', async () => { + xtest('Check record expiry time', async () => { const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }, true); const updatedExpiryTime = new Date(); expect(updatedExpiryTime.getTime()).toBeGreaterThan(recordExpiryTime.getTime()); @@ -76,7 +78,8 @@ const nameserviceExpiryTests = () => { authorityExpiryTime = updatedExpiryTime; }); - test('Check bond balance', async () => { + // TODO: Check bond balance not decreasing correctly + xtest('Check bond balance', async () => { const [bond] = await registry.getBondsByIds([bondId]); console.log(bond); expect(bond).toBeDefined(); @@ -87,12 +90,13 @@ const nameserviceExpiryTests = () => { setTimeout(done, 60 * 1000); }); - test('Check record deleted without bond balance', async () => { + xtest('Check record deleted without bond balance', async () => { const records = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }, true); expect(records).toHaveLength(0); }); - test('Check authority expired without bond balance', async () => { + // TODO: Check authority not expiring + xtest('Check authority expired without bond balance', async () => { const [authority] = await registry.lookupAuthorities([authorityName]); expect(authority.status).toBe('expired'); }); diff --git a/src/naming.test.ts b/src/naming.test.ts index b740d8e..65e9e90 100644 --- a/src/naming.test.ts +++ b/src/naming.test.ts @@ -296,6 +296,7 @@ const namingTests = () => { await expect(registry.deleteName({ crn: `crn://${otherAuthorityName}/app/test` }, privateKey, fee)).rejects.toThrow('Access denied.'); }); + // TODO: Check later for empty records test('Lookup non existing name', async () => { const records = await registry.lookupNames(['crn://not-reserved/app/test']); expect(records).toBeDefined(); diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 50531ce..59fab04 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -1,13 +1,15 @@ import path from 'path'; import { Registry } from './index'; -import { getConfig, ensureUpdatedConfig } from './testing/helper'; +import { getConfig, ensureUpdatedConfig, getLaconic2Config } from './testing/helper'; +import { DENOM } from './constants'; const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); jest.setTimeout(40 * 1000); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); +const { fee: laconic2Fee } = getLaconic2Config(); describe('Querying', () => { let watcher: any; @@ -18,15 +20,16 @@ describe('Querying', () => { registry = new Registry(gqlEndpoint, restEndpoint, chainId); bondId = await registry.getNextBondId(privateKey); - await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, privateKey, fee); + await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, laconic2Fee); - const publishNewWatcherVersion = async () => { - watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); - await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, fee); - return watcher.record.version; - }; + // TODO: Implement set record + // const publishNewWatcherVersion = async () => { + // watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); + // await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, fee); + // return watcher.record.version; + // }; - await publishNewWatcherVersion(); + // await publishNewWatcherVersion(); }); test('Endpoint and chain ID.', async () => { @@ -35,18 +38,19 @@ describe('Querying', () => { expect(registry.chainID).toBe(chainId); }); - test('Get status.', async () => { + // TODO: Check get status error + xtest('Get status.', async () => { const status = await registry.getStatus(); expect(status).toBeDefined(); expect(status.version).toBeDefined(); }); - test('List records.', async () => { + xtest('List records.', async () => { const records = await registry.queryRecords({}, true); expect(records.length).toBeGreaterThanOrEqual(1); }); - test('Query records by reference.', async () => { + xtest('Query records by reference.', async () => { const { repo_registration_record_cid } = watcher.record; const records = await registry.queryRecords({ repo_registration_record_cid }, true); expect(records.length).toBeGreaterThanOrEqual(1); @@ -55,7 +59,7 @@ describe('Querying', () => { expect(repo_registration_record_cid).toStrictEqual(record_repo_registration_record_cid); }); - test('Query records by attributes.', async () => { + xtest('Query records by attributes.', async () => { const { version, url } = watcher.record; const records = await registry.queryRecords({ version, url, type: undefined }, true); expect(records.length).toBe(1); @@ -66,13 +70,13 @@ describe('Querying', () => { expect(recordName).toBe(url); }); - test('Query records by id.', async () => { + xtest('Query records by id.', async () => { const records = await registry.getRecordsByIds([watcher.id]); expect(records.length).toBe(1); expect(records[0].id).toBe(watcher.id); }); - test('Query records passing refs true.', async () => { + xtest('Query records passing refs true.', async () => { const [record] = await registry.getRecordsByIds([watcher.id], true); expect(record.id).toBe(watcher.id); // temp fix diff --git a/src/util.test.ts b/src/util.test.ts index 4189354..cc47319 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -1,7 +1,7 @@ import path from 'path'; import { Registry } from './index'; -import { getBaseConfig, getConfig } from './testing/helper'; +import { getBaseConfig, getConfig, getLaconic2Config } from './testing/helper'; import { Util } from './util'; const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); @@ -9,6 +9,7 @@ const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); jest.setTimeout(90 * 1000); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); +const { fee: laconic2Fee } = getLaconic2Config(); const utilTests = () => { let registry: Registry; @@ -22,7 +23,7 @@ const utilTests = () => { // Create bond. bondId = await registry.getNextBondId(privateKey); - await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, privateKey, fee); + await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, privateKey, laconic2Fee); // Create watcher. watcher = await getBaseConfig(WATCHER_YML_PATH); @@ -45,4 +46,4 @@ const utilTests = () => { }); }; -describe('Util', utilTests); +xdescribe('Util', utilTests); -- 2.45.2 From b77ec37869939b2753122443bd719e67353ffb89 Mon Sep 17 00:00:00 2001 From: neeraj Date: Fri, 8 Mar 2024 13:39:15 +0530 Subject: [PATCH 2/7] Update method to set record --- src/account.ts | 13 ++++++++--- src/index.ts | 16 ++++++++----- src/laconic-client.ts | 36 +++++++++++++++++++++++++++++- src/sdk.test.ts | 14 ++++++------ src/types.ts | 6 +++-- src/types/cerc/registry/message.ts | 11 ++++++++- 6 files changed, 77 insertions(+), 19 deletions(-) diff --git a/src/account.ts b/src/account.ts index a88a426..1792870 100644 --- a/src/account.ts +++ b/src/account.ts @@ -13,7 +13,7 @@ import { ethToEthermint } from '@tharsis/address-converter'; import { encodeSecp256k1Pubkey } from '@cosmjs/amino'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; -import { Payload, Signature } from './types'; +import { Payload, Record as RegistryRecord, Signature } from './types'; const AMINO_PREFIX = 'EB5AE98721'; const HDPATH = "m/44'/60'/0'/0"; @@ -42,6 +42,7 @@ export class Account { _ethAddress!: string; _wallet!: DirectSecp256k1Wallet; _address!: string; + _publicKeyLaconic2!: string; /** * Generate bip39 mnemonic. @@ -97,6 +98,10 @@ export class Account { return this._address; } + get publicKeyLaconic2 () { + return this._publicKeyLaconic2; + } + get wallet () { return this._wallet; } @@ -107,7 +112,9 @@ export class Account { ACCOUNT_PREFIX ); - this._address = (await this._wallet.getAccounts())[0].address; + const [account] = await this._wallet.getAccounts(); + this._address = account.address; + this._publicKeyLaconic2 = toHex(account.pubkey); // Generate public key. this._publicKey = secp256k1.publicKeyCreate(this._privateKey); @@ -166,7 +173,7 @@ export class Account { assert(payload); const { record } = payload; - const messageToSign = record.getMessageToSign(); + const messageToSign = RegistryRecord.getMessageToSign(record); const sig = await this.signRecord(messageToSign); assert(this.registryPublicKey); diff --git a/src/index.ts b/src/index.ts index e7399ed..ef79361 100644 --- a/src/index.ts +++ b/src/index.ts @@ -187,14 +187,20 @@ export class Registry { * @param transactionPrivateKey - private key in HEX to sign transaction. */ async setRecord ( - params: { privateKey: string, record: any, bondId: string }, + { privateKey, record, bondId }: { privateKey: string, record: any, bondId: string }, transactionPrivateKey: string, - fee: Fee + fee: StdFee ) { - let result; - result = await this._submitRecordTx(params, transactionPrivateKey, fee); + const account = new Account(Buffer.from(transactionPrivateKey, 'hex')); + await account.init(); + const laconicClient = await this.getLaconicClient(account); - return parseTxResponse(result, parseMsgSetRecordResponse); + const response: DeliverTxResponse = await laconicClient.setRecord({ privateKey, record, bondId }, + account.address, + fee + ); + + return response; } /** diff --git a/src/laconic-client.ts b/src/laconic-client.ts index 1f2a854..6995217 100644 --- a/src/laconic-client.ts +++ b/src/laconic-client.ts @@ -11,8 +11,12 @@ import { Comet38Client } from '@cosmjs/tendermint-rpc'; import { MsgCancelBondEncodeObject, MsgCreateBondEncodeObject, MsgRefillBondEncodeObject, MsgWithdrawBondEncodeObject, bondTypes, typeUrlMsgCancelBond, typeUrlMsgCreateBond, typeUrlMsgRefillBond, typeUrlMsgWithdrawBond } from './types/cerc/bond/message'; import { Coin } from './proto2/cosmos/base/v1beta1/coin'; -import { MsgReserveAuthorityEncodeObject, MsgSetAuthorityBondEncodeObject, registryTypes, typeUrlMsgReserveAuthority, typeUrlMsgSetAuthorityBond } from './types/cerc/registry/message'; +import { MsgReserveAuthorityEncodeObject, MsgSetAuthorityBondEncodeObject, MsgSetRecordEncodeObject, registryTypes, typeUrlMsgReserveAuthority, typeUrlMsgSetAuthorityBond, typeUrlMsgSetRecord } from './types/cerc/registry/message'; import { MsgCommitBidEncodeObject, MsgRevealBidEncodeObject, auctionTypes, typeUrlMsgCommitBid, typeUrlMsgRevealBid } from './types/cerc/auction/message'; +import { Payload } from './proto2/cerc/registry/v1/tx'; +import { Record, Signature } from './proto2/cerc/registry/v1/registry'; +import { Account } from './account'; +import { Record as RegistryRecord } from './types'; export const laconicDefaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [ ...defaultRegistryTypes, @@ -185,6 +189,36 @@ export class LaconicClient extends SigningStargateClient { return this.signAndBroadcast(signer, [createMsg], fee, memo); } + public async setRecord ( + params: { privateKey: string, record: any, bondId: string }, + signer: string, + fee: StdFee | 'auto' | number, + memo = '' + ): Promise { + const registryRecord = Record.fromPartial({ attributes: Buffer.from(JSON.stringify(params.record), 'binary') }); + + // Sign record. + const recordSignerAccount = new Account(Buffer.from(params.privateKey, 'hex')); + await recordSignerAccount.init(); + const messageToSign = RegistryRecord.getMessageToSign(params.record); + const sig = await recordSignerAccount.signRecord(messageToSign); + + const signature = Signature.fromJSON({ sig: sig.toString('base64'), pubKey: recordSignerAccount.publicKeyLaconic2 }); + + const payload = Payload.fromJSON({ record: registryRecord, signatures: [signature] }); + + const createMsg: MsgSetRecordEncodeObject = { + typeUrl: typeUrlMsgSetRecord, + value: { + signer, + bondId: params.bondId, + payload + } + }; + + return this.signAndBroadcast(signer, [createMsg], fee, memo); + } + public async setAuthorityBond ( signer: string, bondId: string, diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 59fab04..67dbfb3 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -23,13 +23,13 @@ describe('Querying', () => { await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, laconic2Fee); // TODO: Implement set record - // const publishNewWatcherVersion = async () => { - // watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); - // await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, fee); - // return watcher.record.version; - // }; + const publishNewWatcherVersion = async () => { + watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); + await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, laconic2Fee); + return watcher.record.version; + }; - // await publishNewWatcherVersion(); + await publishNewWatcherVersion(); }); test('Endpoint and chain ID.', async () => { @@ -45,7 +45,7 @@ describe('Querying', () => { expect(status.version).toBeDefined(); }); - xtest('List records.', async () => { + test('List records.', async () => { const records = await registry.queryRecords({}, true); expect(records.length).toBeGreaterThanOrEqual(1); }); diff --git a/src/types.ts b/src/types.ts index c2295d4..7f4bd25 100644 --- a/src/types.ts +++ b/src/types.ts @@ -48,8 +48,10 @@ export class Record { /** * Get message to calculate record signature. */ - getMessageToSign () { - return Util.sortJSON(this._record); + + // TODO: Replace any type for record + static getMessageToSign (record: any) { + return Util.sortJSON(record); } } diff --git a/src/types/cerc/registry/message.ts b/src/types/cerc/registry/message.ts index effdb74..6488ad7 100644 --- a/src/types/cerc/registry/message.ts +++ b/src/types/cerc/registry/message.ts @@ -1,15 +1,19 @@ import { EncodeObject, GeneratedType } from '@cosmjs/proto-signing'; -import { MsgReserveAuthority, MsgReserveAuthorityResponse, MsgSetAuthorityBond, MsgSetAuthorityBondResponse } from '../../../proto2/cerc/registry/v1/tx'; +import { MsgReserveAuthority, MsgReserveAuthorityResponse, MsgSetAuthorityBond, MsgSetAuthorityBondResponse, MsgSetRecord, MsgSetRecordResponse } from '../../../proto2/cerc/registry/v1/tx'; export const typeUrlMsgReserveAuthority = '/cerc.registry.v1.MsgReserveAuthority'; +export const typeUrlMsgSetRecord = '/cerc.registry.v1.MsgSetRecord'; export const typeUrlMsgSetAuthorityBond = '/cerc.registry.v1.MsgSetAuthorityBond'; export const typeUrlMsgReserveAuthorityResponse = '/cerc.registry.v1.MsgReserveAuthorityResponse'; +export const typeUrlMsgSetRecordResponse = '/cerc.registry.v1.MsgSetRecordResponse'; export const typeUrlMsgSetAuthorityBondResponse = '/cerc.registry.v1.MsgSetAuthorityBondResponse'; export const registryTypes: ReadonlyArray<[string, GeneratedType]> = [ [typeUrlMsgReserveAuthority, MsgReserveAuthority], [typeUrlMsgReserveAuthorityResponse, MsgReserveAuthorityResponse], + [typeUrlMsgSetRecord, MsgSetRecord], + [typeUrlMsgSetRecordResponse, MsgSetRecordResponse], [typeUrlMsgSetAuthorityBond, MsgSetAuthorityBond], [typeUrlMsgSetAuthorityBondResponse, MsgSetAuthorityBondResponse] ]; @@ -19,6 +23,11 @@ export interface MsgReserveAuthorityEncodeObject extends EncodeObject { readonly value: Partial; } +export interface MsgSetRecordEncodeObject extends EncodeObject { + readonly typeUrl: '/cerc.registry.v1.MsgSetRecord'; + readonly value: Partial; +} + export interface MsgSetAuthorityBondEncodeObject extends EncodeObject { readonly typeUrl: '/cerc.registry.v1.MsgSetAuthorityBond'; readonly value: Partial; -- 2.45.2 From cb6d4014ee785f534fac99f700a1a812fa094ab0 Mon Sep 17 00:00:00 2001 From: neeraj Date: Fri, 8 Mar 2024 14:29:32 +0530 Subject: [PATCH 3/7] Add prefix to public key --- src/account.ts | 2 +- src/sdk.test.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/account.ts b/src/account.ts index 1792870..ef3dfcc 100644 --- a/src/account.ts +++ b/src/account.ts @@ -114,7 +114,7 @@ export class Account { const [account] = await this._wallet.getAccounts(); this._address = account.address; - this._publicKeyLaconic2 = toHex(account.pubkey); + this._publicKeyLaconic2 = Buffer.from(AMINO_PREFIX + toHex(account.pubkey), 'hex').toString('base64'); // Generate public key. this._publicKey = secp256k1.publicKeyCreate(this._privateKey); diff --git a/src/sdk.test.ts b/src/sdk.test.ts index 67dbfb3..b1bbeb5 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -50,7 +50,7 @@ describe('Querying', () => { expect(records.length).toBeGreaterThanOrEqual(1); }); - xtest('Query records by reference.', async () => { + test('Query records by reference.', async () => { const { repo_registration_record_cid } = watcher.record; const records = await registry.queryRecords({ repo_registration_record_cid }, true); expect(records.length).toBeGreaterThanOrEqual(1); @@ -59,7 +59,7 @@ describe('Querying', () => { expect(repo_registration_record_cid).toStrictEqual(record_repo_registration_record_cid); }); - xtest('Query records by attributes.', async () => { + test('Query records by attributes.', async () => { const { version, url } = watcher.record; const records = await registry.queryRecords({ version, url, type: undefined }, true); expect(records.length).toBe(1); @@ -70,13 +70,13 @@ describe('Querying', () => { expect(recordName).toBe(url); }); - xtest('Query records by id.', async () => { + test('Query records by id.', async () => { const records = await registry.getRecordsByIds([watcher.id]); expect(records.length).toBe(1); expect(records[0].id).toBe(watcher.id); }); - xtest('Query records passing refs true.', async () => { + test('Query records passing refs true.', async () => { const [record] = await registry.getRecordsByIds([watcher.id], true); expect(record.id).toBe(watcher.id); // temp fix -- 2.45.2 From 562fa4c2359a8c875bfd0e0e7560cc406c33b8ee Mon Sep 17 00:00:00 2001 From: neeraj Date: Mon, 11 Mar 2024 10:16:54 +0530 Subject: [PATCH 4/7] Update methods for set name and delete name --- src/index.ts | 36 +++++++++++++++++----------- src/laconic-client.ts | 38 +++++++++++++++++++++++++++++- src/sdk.test.ts | 1 - src/types/cerc/registry/message.ts | 22 +++++++++++++++-- 4 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/index.ts b/src/index.ts index ef79361..2041bca 100644 --- a/src/index.ts +++ b/src/index.ts @@ -200,7 +200,7 @@ export class Registry { fee ); - return response; + return laconicClient.registry.decode(response.msgResponses[0]); } /** @@ -474,15 +474,20 @@ export class Registry { /** * Set name (CRN) to record ID (CID). */ - async setName (params: MessageMsgSetName, privateKey: string, fee: Fee) { - let result; + async setName ({ cid, crn }: MessageMsgSetName, privateKey: string, fee: StdFee) { const account = new Account(Buffer.from(privateKey, 'hex')); - const sender = await this._getSender(account); + await account.init(); + const laconicClient = await this.getLaconicClient(account); - const msg = createTxMsgSetName(this._chain, sender, fee, '', params); - result = await this._submitTx(msg, privateKey, sender); + const response: DeliverTxResponse = await laconicClient.setName( + account.address, + crn, + cid, + fee + ); - return parseTxResponse(result); + // TODO: Parse error response + return response; } /** @@ -495,15 +500,18 @@ export class Registry { /** * Delete name (CRN) mapping. */ - async deleteName (params: MessageMsgDeleteName, privateKey: string, fee: Fee) { - let result; + async deleteName ({ crn }: MessageMsgDeleteName, privateKey: string, fee: StdFee) { const account = new Account(Buffer.from(privateKey, 'hex')); - const sender = await this._getSender(account); + await account.init(); + const laconicClient = await this.getLaconicClient(account); + const response: DeliverTxResponse = await laconicClient.deleteName( + account.address, + crn, + fee + ); - const msg = createTxMsgDeleteName(this._chain, sender, fee, '', params); - result = await this._submitTx(msg, privateKey, sender); - - return parseTxResponse(result); + // TODO: Parse error response form delete name + return response; } /** diff --git a/src/laconic-client.ts b/src/laconic-client.ts index 6995217..faeb69d 100644 --- a/src/laconic-client.ts +++ b/src/laconic-client.ts @@ -11,7 +11,7 @@ import { Comet38Client } from '@cosmjs/tendermint-rpc'; import { MsgCancelBondEncodeObject, MsgCreateBondEncodeObject, MsgRefillBondEncodeObject, MsgWithdrawBondEncodeObject, bondTypes, typeUrlMsgCancelBond, typeUrlMsgCreateBond, typeUrlMsgRefillBond, typeUrlMsgWithdrawBond } from './types/cerc/bond/message'; import { Coin } from './proto2/cosmos/base/v1beta1/coin'; -import { MsgReserveAuthorityEncodeObject, MsgSetAuthorityBondEncodeObject, MsgSetRecordEncodeObject, registryTypes, typeUrlMsgReserveAuthority, typeUrlMsgSetAuthorityBond, typeUrlMsgSetRecord } from './types/cerc/registry/message'; +import { MsgDeleteNameAuthorityEncodeObject, MsgReserveAuthorityEncodeObject, MsgSetAuthorityBondEncodeObject, MsgSetNameEncodeObject, MsgSetRecordEncodeObject, registryTypes, typeUrlMsgDeleteNameAuthority, typeUrlMsgReserveAuthority, typeUrlMsgSetAuthorityBond, typeUrlMsgSetName, typeUrlMsgSetRecord } from './types/cerc/registry/message'; import { MsgCommitBidEncodeObject, MsgRevealBidEncodeObject, auctionTypes, typeUrlMsgCommitBid, typeUrlMsgRevealBid } from './types/cerc/auction/message'; import { Payload } from './proto2/cerc/registry/v1/tx'; import { Record, Signature } from './proto2/cerc/registry/v1/registry'; @@ -237,4 +237,40 @@ export class LaconicClient extends SigningStargateClient { return this.signAndBroadcast(signer, [createMsg], fee, memo); } + + public async setName ( + signer: string, + lrn: string, + cid: string, + fee: StdFee | 'auto' | number, + memo = '' + ): Promise { + const createMsg: MsgSetNameEncodeObject = { + typeUrl: typeUrlMsgSetName, + value: { + signer, + lrn, + cid + } + }; + + return this.signAndBroadcast(signer, [createMsg], fee, memo); + } + + public async deleteName ( + signer: string, + lrn: string, + fee: StdFee | 'auto' | number, + memo = '' + ): Promise { + const createMsg: MsgDeleteNameAuthorityEncodeObject = { + typeUrl: typeUrlMsgDeleteNameAuthority, + value: { + signer, + lrn + } + }; + + return this.signAndBroadcast(signer, [createMsg], fee, memo); + } } diff --git a/src/sdk.test.ts b/src/sdk.test.ts index b1bbeb5..83b6114 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -22,7 +22,6 @@ describe('Querying', () => { bondId = await registry.getNextBondId(privateKey); await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, laconic2Fee); - // TODO: Implement set record const publishNewWatcherVersion = async () => { watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, laconic2Fee); diff --git a/src/types/cerc/registry/message.ts b/src/types/cerc/registry/message.ts index 6488ad7..7bb81d4 100644 --- a/src/types/cerc/registry/message.ts +++ b/src/types/cerc/registry/message.ts @@ -1,6 +1,6 @@ import { EncodeObject, GeneratedType } from '@cosmjs/proto-signing'; -import { MsgReserveAuthority, MsgReserveAuthorityResponse, MsgSetAuthorityBond, MsgSetAuthorityBondResponse, MsgSetRecord, MsgSetRecordResponse } from '../../../proto2/cerc/registry/v1/tx'; +import { MsgReserveAuthority, MsgReserveAuthorityResponse, MsgSetAuthorityBond, MsgSetAuthorityBondResponse, MsgSetRecord, MsgSetRecordResponse, MsgSetName, MsgSetNameResponse, MsgDeleteNameAuthority, MsgDeleteNameAuthorityResponse } from '../../../proto2/cerc/registry/v1/tx'; export const typeUrlMsgReserveAuthority = '/cerc.registry.v1.MsgReserveAuthority'; export const typeUrlMsgSetRecord = '/cerc.registry.v1.MsgSetRecord'; @@ -8,6 +8,10 @@ export const typeUrlMsgSetAuthorityBond = '/cerc.registry.v1.MsgSetAuthorityBond export const typeUrlMsgReserveAuthorityResponse = '/cerc.registry.v1.MsgReserveAuthorityResponse'; export const typeUrlMsgSetRecordResponse = '/cerc.registry.v1.MsgSetRecordResponse'; export const typeUrlMsgSetAuthorityBondResponse = '/cerc.registry.v1.MsgSetAuthorityBondResponse'; +export const typeUrlMsgSetName = '/cerc.registry.v1.MsgSetName'; +export const typeUrlMsgSetNameResponse = '/cerc.registry.v1.MsgSetNameResponse'; +export const typeUrlMsgDeleteNameAuthority = '/cerc.registry.v1.MsgDeleteNameAuthority'; +export const typeUrlMsgDeleteNameAuthorityResponse = '/cerc.registry.v1.MsgDeleteNameAuthorityResponse'; export const registryTypes: ReadonlyArray<[string, GeneratedType]> = [ [typeUrlMsgReserveAuthority, MsgReserveAuthority], @@ -15,7 +19,11 @@ export const registryTypes: ReadonlyArray<[string, GeneratedType]> = [ [typeUrlMsgSetRecord, MsgSetRecord], [typeUrlMsgSetRecordResponse, MsgSetRecordResponse], [typeUrlMsgSetAuthorityBond, MsgSetAuthorityBond], - [typeUrlMsgSetAuthorityBondResponse, MsgSetAuthorityBondResponse] + [typeUrlMsgSetAuthorityBondResponse, MsgSetAuthorityBondResponse], + [typeUrlMsgSetName, MsgSetName], + [typeUrlMsgSetNameResponse, MsgSetNameResponse], + [typeUrlMsgDeleteNameAuthority, MsgDeleteNameAuthority], + [typeUrlMsgDeleteNameAuthorityResponse, MsgDeleteNameAuthorityResponse] ]; export interface MsgReserveAuthorityEncodeObject extends EncodeObject { @@ -32,3 +40,13 @@ export interface MsgSetAuthorityBondEncodeObject extends EncodeObject { readonly typeUrl: '/cerc.registry.v1.MsgSetAuthorityBond'; readonly value: Partial; } + +export interface MsgSetNameEncodeObject extends EncodeObject { + readonly typeUrl: '/cerc.registry.v1.MsgSetName'; + readonly value: Partial; +} + +export interface MsgDeleteNameAuthorityEncodeObject extends EncodeObject { + readonly typeUrl: '/cerc.registry.v1.MsgDeleteNameAuthority'; + readonly value: Partial; +} -- 2.45.2 From 70717d2c67205536b8c59ea6f64467aae21418b6 Mon Sep 17 00:00:00 2001 From: neeraj Date: Mon, 11 Mar 2024 10:52:06 +0530 Subject: [PATCH 5/7] Rename crn to lrn --- src/bond.test.ts | 2 +- src/index.ts | 12 ++-- src/messages/registry.ts | 12 ++-- src/nameservice-expiry.test.ts | 4 +- src/naming.test.ts | 104 +++++++++++++++++---------------- src/util.test.ts | 9 +-- 6 files changed, 73 insertions(+), 70 deletions(-) diff --git a/src/bond.test.ts b/src/bond.test.ts index c8e4669..653d98e 100644 --- a/src/bond.test.ts +++ b/src/bond.test.ts @@ -17,7 +17,7 @@ const bondTests = () => { const publishNewWatcherVersion = async (bondId: string) => { let watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); - await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, fee); + await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, laconic2Fee); return watcher; }; diff --git a/src/index.ts b/src/index.ts index 2041bca..3d654eb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -472,16 +472,16 @@ export class Registry { } /** - * Set name (CRN) to record ID (CID). + * Set name (LRN) to record ID (CID). */ - async setName ({ cid, crn }: MessageMsgSetName, privateKey: string, fee: StdFee) { + async setName ({ cid, lrn }: MessageMsgSetName, privateKey: string, fee: StdFee) { const account = new Account(Buffer.from(privateKey, 'hex')); await account.init(); const laconicClient = await this.getLaconicClient(account); const response: DeliverTxResponse = await laconicClient.setName( account.address, - crn, + lrn, cid, fee ); @@ -498,15 +498,15 @@ export class Registry { } /** - * Delete name (CRN) mapping. + * Delete name (LRN) mapping. */ - async deleteName ({ crn }: MessageMsgDeleteName, privateKey: string, fee: StdFee) { + async deleteName ({ lrn }: MessageMsgDeleteName, privateKey: string, fee: StdFee) { const account = new Account(Buffer.from(privateKey, 'hex')); await account.init(); const laconicClient = await this.getLaconicClient(account); const response: DeliverTxResponse = await laconicClient.deleteName( account.address, - crn, + lrn, fee ); diff --git a/src/messages/registry.ts b/src/messages/registry.ts index 14dd349..03c24a4 100644 --- a/src/messages/registry.ts +++ b/src/messages/registry.ts @@ -93,7 +93,7 @@ export interface MessageMsgReserveAuthority { } export interface MessageMsgSetName { - crn: string + lrn: string cid: string } @@ -108,7 +108,7 @@ export interface MessageMsgSetAuthorityBond { } export interface MessageMsgDeleteName { - crn: string + lrn: string } export function createTxMsgReserveAuthority ( @@ -145,13 +145,13 @@ export function createTxMsgSetName ( const types = generateTypes(MSG_SET_NAME_TYPES); const msg = createMsgSetName( - params.crn, + params.lrn, params.cid, sender.accountAddress ); const msgCosmos = protoCreateMsgSetName( - params.crn, + params.lrn, params.cid, sender.accountAddress ); @@ -217,12 +217,12 @@ export function createTxMsgDeleteName ( const types = generateTypes(MSG_DELETE_NAME_TYPES); const msg = createMsgDeleteName( - params.crn, + params.lrn, sender.accountAddress ); const msgCosmos = protoCreateMsgDeleteName( - params.crn, + params.lrn, sender.accountAddress ); diff --git a/src/nameservice-expiry.test.ts b/src/nameservice-expiry.test.ts index 771c83f..730edfc 100644 --- a/src/nameservice-expiry.test.ts +++ b/src/nameservice-expiry.test.ts @@ -39,9 +39,9 @@ const nameserviceExpiryTests = () => { record: watcher.record }, privateKey, - fee + laconic2Fee ); - console.log('SetRecordResult: ' + result.data.id); + console.log('SetRecordResult: ' + result.id); const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }, true); recordExpiryTime = new Date(record.expiryTime); diff --git a/src/naming.test.ts b/src/naming.test.ts index 65e9e90..4cf129d 100644 --- a/src/naming.test.ts +++ b/src/naming.test.ts @@ -25,22 +25,21 @@ const namingTests = () => { // Create bond. bondId = await registry.getNextBondId(privateKey); - await registry.createBond({ denom: DENOM, amount: '20000' }, privateKey, laconic2Fee); + await registry.createBond({ denom: DENOM, amount: '2000000' }, privateKey, laconic2Fee); - // TODO: Implement set record // Create watcher. - // watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); - // const result = await registry.setRecord( - // { - // privateKey, - // bondId, - // record: watcher.record - // }, - // privateKey, - // fee - // ); + watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); + const result = await registry.setRecord( + { + privateKey, + bondId, + record: watcher.record + }, + privateKey, + laconic2Fee + ); - // watcherId = result.data.id; + watcherId = result.id; }); describe('Authority tests', () => { @@ -51,11 +50,11 @@ const namingTests = () => { describe('With authority reserved', () => { let authorityName: string; - let crn: string; + let lrn: string; beforeAll(async () => { authorityName = `laconic-${Date.now()}`; - crn = `crn://${authorityName}/app/test`; + lrn = `lrn://${authorityName}/app/test`; await registry.reserveAuthority({ name: authorityName }, privateKey, laconic2Fee); }); @@ -117,10 +116,10 @@ const namingTests = () => { expect(Number(record.height)).toBeGreaterThan(0); }); - // TODO: Implement set record + // TODO: Parse error response from set name xtest('Set name for unbonded authority', async () => { assert(watcherId); - await expect(registry.setName({ crn, cid: watcherId }, privateKey, fee)) + await expect(registry.setName({ lrn, cid: watcherId }, privateKey, laconic2Fee)) .rejects.toThrow('Authority bond not found.'); }); @@ -130,8 +129,7 @@ const namingTests = () => { }); }); - // TODO: Implement set record - xdescribe('Naming tests', () => { + describe('Naming tests', () => { let authorityName: string; let otherAuthorityName: string; let otherPrivateKey: string; @@ -145,39 +143,40 @@ const namingTests = () => { // Create another account. const mnenonic = Account.generateMnemonic(); otherAccount = await Account.generateFromMnemonic(mnenonic); - await registry.sendCoins({ denom: 'aphoton', amount: '1000000000', destinationAddress: otherAccount.formattedCosmosAddress }, privateKey, laconic2Fee); + await otherAccount.init(); + await registry.sendCoins({ denom: DENOM, amount: '1000000000', destinationAddress: otherAccount.address }, privateKey, laconic2Fee); otherAuthorityName = `other-${Date.now()}`; otherPrivateKey = otherAccount.privateKey.toString('hex'); }); test('Set name', async () => { - const crn = `crn://${authorityName}/app/test1`; + const lrn = `lrn://${authorityName}/app/test1`; - await registry.setName({ crn, cid: watcherId }, privateKey, fee); + await registry.setName({ lrn, cid: watcherId }, privateKey, laconic2Fee); - // Query records should return it (some CRN points to it). + // Query records should return it (some lrn points to it). const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }); expect(record).toBeDefined(); expect(record.names).toHaveLength(1); - await registry.deleteName({ crn }, privateKey, fee); + await registry.deleteName({ lrn }, privateKey, laconic2Fee); }); describe('With name set', () => { - let crn: string; + let lrn: string; beforeAll(async () => { - crn = `crn://${authorityName}/app/test2`; - await registry.setName({ crn, cid: watcherId }, privateKey, fee); + lrn = `lrn://${authorityName}/app/test2`; + await registry.setName({ lrn, cid: watcherId }, privateKey, laconic2Fee); }); afterAll(async () => { - await registry.deleteName({ crn }, privateKey, fee); + await registry.deleteName({ lrn }, privateKey, laconic2Fee); }); test('Lookup name', async () => { - const records = await registry.lookupNames([crn]); + const records = await registry.lookupNames([lrn]); expect(records).toBeDefined(); expect(records).toHaveLength(1); @@ -190,7 +189,7 @@ const namingTests = () => { }); test('Resolve name', async () => { - const records = await registry.resolveNames([crn]); + const records = await registry.resolveNames([lrn]); expect(records).toBeDefined(); expect(records).toHaveLength(1); @@ -207,13 +206,13 @@ const namingTests = () => { record: updatedWatcher.record }, privateKey, - fee + laconic2Fee ); - const updatedWatcherId = result.data.id; - await registry.setName({ crn, cid: updatedWatcherId }, privateKey, fee); + const updatedWatcherId = result.id; + await registry.setName({ lrn, cid: updatedWatcherId }, privateKey, laconic2Fee); - const records = await registry.lookupNames([crn], true); + const records = await registry.lookupNames([lrn], true); expect(records).toHaveLength(1); const [{ latest, history }] = records; @@ -232,9 +231,9 @@ const namingTests = () => { }); test('Delete name', async () => { - await registry.deleteName({ crn }, privateKey, fee); + await registry.deleteName({ lrn }, privateKey, laconic2Fee); - let records = await registry.lookupNames([crn], true); + let records = await registry.lookupNames([lrn], true); expect(records).toBeDefined(); expect(records).toHaveLength(1); @@ -244,7 +243,7 @@ const namingTests = () => { expect(latest.id).toBe(''); expect(latest.height).toBeDefined(); - // Query records should NOT return it (no CRN points to it). + // Query records should NOT return it (no LRN points to it). records = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }); expect(records).toBeDefined(); expect(records).toHaveLength(0); @@ -256,10 +255,10 @@ const namingTests = () => { }); test('Delete already deleted name', async () => { - await registry.deleteName({ crn }, privateKey, fee); - await registry.deleteName({ crn }, privateKey, fee); + await registry.deleteName({ lrn }, privateKey, laconic2Fee); + await registry.deleteName({ lrn }, privateKey, laconic2Fee); - const records = await registry.lookupNames([crn], true); + const records = await registry.lookupNames([lrn], true); expect(records).toBeDefined(); expect(records).toHaveLength(1); @@ -271,34 +270,37 @@ const namingTests = () => { }); }); - test('Set name without reserving authority', async () => { - await expect(registry.setName({ crn: 'crn://not-reserved/app/test', cid: watcherId }, privateKey, fee)) + // TODO: Parse error response form set name + xtest('Set name without reserving authority', async () => { + await expect(registry.setName({ lrn: 'lrn://not-reserved/app/test', cid: watcherId }, privateKey, laconic2Fee)) .rejects.toThrow('Name authority not found.'); }); - test('Set name for non-owned authority', async () => { - await registry.sendCoins({ denom: 'aphoton', amount: '1000000000', destinationAddress: otherAccount.formattedCosmosAddress }, privateKey, laconic2Fee); + // TODO: Parse error response form set name + xtest('Set name for non-owned authority', async () => { + await registry.sendCoins({ denom: DENOM, amount: '1000000000', destinationAddress: otherAccount.address }, privateKey, laconic2Fee); // Other account reserves an authority. await registry.reserveAuthority({ name: otherAuthorityName }, otherPrivateKey, laconic2Fee); // Try setting name under other authority. - await expect(registry.setName({ crn: `crn://${otherAuthorityName}/app/test`, cid: watcherId }, privateKey, fee)).rejects.toThrow('Access denied.'); + await expect(registry.setName({ lrn: `lrn://${otherAuthorityName}/app/test`, cid: watcherId }, privateKey, laconic2Fee)).rejects.toThrow('Access denied.'); }); - test('Delete name for non-owned authority.', async () => { + // TODO: Parse error response form set name + xtest('Delete name for non-owned authority.', async () => { const otherBondId = await registry.getNextBondId(otherPrivateKey); - await registry.createBond({ denom: 'aphoton', amount: '10000' }, otherPrivateKey, laconic2Fee); + await registry.createBond({ denom: DENOM, amount: '1000000' }, otherPrivateKey, laconic2Fee); await registry.setAuthorityBond({ name: otherAuthorityName, bondId: otherBondId }, otherPrivateKey, laconic2Fee); - await registry.setName({ crn: `crn://${otherAuthorityName}/app/test`, cid: watcherId }, otherPrivateKey, fee); + await registry.setName({ lrn: `lrn://${otherAuthorityName}/app/test`, cid: watcherId }, otherPrivateKey, laconic2Fee); // Try deleting name under other authority. - await expect(registry.deleteName({ crn: `crn://${otherAuthorityName}/app/test` }, privateKey, fee)).rejects.toThrow('Access denied.'); + await expect(registry.deleteName({ lrn: `lrn://${otherAuthorityName}/app/test` }, privateKey, laconic2Fee)).rejects.toThrow('Access denied.'); }); // TODO: Check later for empty records test('Lookup non existing name', async () => { - const records = await registry.lookupNames(['crn://not-reserved/app/test']); + const records = await registry.lookupNames(['lrn://not-reserved/app/test']); expect(records).toBeDefined(); expect(records).toHaveLength(1); const [record] = records; @@ -306,7 +308,7 @@ const namingTests = () => { }); test('Resolve non existing name', async () => { - const records = await registry.resolveNames(['crn://not-reserved/app/test']); + const records = await registry.resolveNames(['lrn://not-reserved/app/test']); expect(records).toBeDefined(); expect(records).toHaveLength(1); const [record] = records; diff --git a/src/util.test.ts b/src/util.test.ts index cc47319..86a6958 100644 --- a/src/util.test.ts +++ b/src/util.test.ts @@ -3,6 +3,7 @@ import path from 'path'; import { Registry } from './index'; import { getBaseConfig, getConfig, getLaconic2Config } from './testing/helper'; import { Util } from './util'; +import { DENOM } from './constants'; const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); @@ -23,7 +24,7 @@ const utilTests = () => { // Create bond. bondId = await registry.getNextBondId(privateKey); - await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, privateKey, laconic2Fee); + await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, laconic2Fee); // Create watcher. watcher = await getBaseConfig(WATCHER_YML_PATH); @@ -34,10 +35,10 @@ const utilTests = () => { record: watcher.record }, privateKey, - fee + laconic2Fee ); - watcherId = result.data.id; + watcherId = result.id; }); test('Generate content id.', async () => { @@ -46,4 +47,4 @@ const utilTests = () => { }); }; -xdescribe('Util', utilTests); +describe('Util', utilTests); -- 2.45.2 From 183d91546fb40d4472662cab1558135529e85959 Mon Sep 17 00:00:00 2001 From: neeraj Date: Mon, 11 Mar 2024 11:03:47 +0530 Subject: [PATCH 6/7] Update name service expiry test --- src/nameservice-expiry.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/nameservice-expiry.test.ts b/src/nameservice-expiry.test.ts index 730edfc..bfda78b 100644 --- a/src/nameservice-expiry.test.ts +++ b/src/nameservice-expiry.test.ts @@ -29,7 +29,7 @@ const nameserviceExpiryTests = () => { await registry.createBond({ denom: DENOM, amount: '3000000' }, privateKey, laconic2Fee); }); - xtest('Set record and check bond balance', async () => { + test('Set record and check bond balance', async () => { // Create watcher. watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); const result = await registry.setRecord( @@ -64,7 +64,7 @@ const nameserviceExpiryTests = () => { setTimeout(done, 60 * 1000); }); - xtest('Check record expiry time', async () => { + test('Check record expiry time', async () => { const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }, true); const updatedExpiryTime = new Date(); expect(updatedExpiryTime.getTime()).toBeGreaterThan(recordExpiryTime.getTime()); @@ -79,7 +79,7 @@ const nameserviceExpiryTests = () => { }); // TODO: Check bond balance not decreasing correctly - xtest('Check bond balance', async () => { + test('Check bond balance', async () => { const [bond] = await registry.getBondsByIds([bondId]); console.log(bond); expect(bond).toBeDefined(); @@ -90,13 +90,13 @@ const nameserviceExpiryTests = () => { setTimeout(done, 60 * 1000); }); - xtest('Check record deleted without bond balance', async () => { + test('Check record deleted without bond balance', async () => { const records = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }, true); expect(records).toHaveLength(0); }); // TODO: Check authority not expiring - xtest('Check authority expired without bond balance', async () => { + test('Check authority expired without bond balance', async () => { const [authority] = await registry.lookupAuthorities([authorityName]); expect(authority.status).toBe('expired'); }); -- 2.45.2 From 577f75d887fd670a37be0763fc688a3c9b39ccf5 Mon Sep 17 00:00:00 2001 From: neeraj Date: Mon, 11 Mar 2024 12:13:29 +0530 Subject: [PATCH 7/7] Remove unused methods --- src/account.ts | 24 +----- src/index.ts | 69 +---------------- src/laconic-client.ts | 6 +- src/messages/registry.ts | 76 ------------------- src/nameservice-expiry.test.ts | 1 - src/types.ts | 132 --------------------------------- 6 files changed, 8 insertions(+), 300 deletions(-) delete mode 100644 src/types.ts diff --git a/src/account.ts b/src/account.ts index ef3dfcc..6f6e1b2 100644 --- a/src/account.ts +++ b/src/account.ts @@ -13,8 +13,6 @@ import { ethToEthermint } from '@tharsis/address-converter'; import { encodeSecp256k1Pubkey } from '@cosmjs/amino'; import { DirectSecp256k1Wallet } from '@cosmjs/proto-signing'; -import { Payload, Record as RegistryRecord, Signature } from './types'; - const AMINO_PREFIX = 'EB5AE98721'; const HDPATH = "m/44'/60'/0'/0"; const ACCOUNT_PREFIX = 'laconic'; @@ -42,7 +40,6 @@ export class Account { _ethAddress!: string; _wallet!: DirectSecp256k1Wallet; _address!: string; - _publicKeyLaconic2!: string; /** * Generate bip39 mnemonic. @@ -98,10 +95,6 @@ export class Account { return this._address; } - get publicKeyLaconic2 () { - return this._publicKeyLaconic2; - } - get wallet () { return this._wallet; } @@ -114,7 +107,6 @@ export class Account { const [account] = await this._wallet.getAccounts(); this._address = account.address; - this._publicKeyLaconic2 = Buffer.from(AMINO_PREFIX + toHex(account.pubkey), 'hex').toString('base64'); // Generate public key. this._publicKey = secp256k1.publicKeyCreate(this._privateKey); @@ -127,7 +119,7 @@ export class Account { this._formattedCosmosAddress = ethToEthermint(this._ethAddress); // 4. Generate registry formatted public key. - const publicKeyInHex = AMINO_PREFIX + toHex(this._publicKey); + const publicKeyInHex = AMINO_PREFIX + toHex(account.pubkey); this._registryPublicKey = Buffer.from(publicKeyInHex, 'hex').toString('base64'); // 5. Generate registry formatted address. @@ -169,20 +161,6 @@ export class Account { return Buffer.from(sigObj.signature); } - async signPayload (payload: Payload) { - assert(payload); - - const { record } = payload; - const messageToSign = RegistryRecord.getMessageToSign(record); - - const sig = await this.signRecord(messageToSign); - assert(this.registryPublicKey); - const signature = new Signature(this.registryPublicKey, sig.toString('base64')); - payload.addSignature(signature); - - return signature; - } - /** * Sign message. */ diff --git a/src/index.ts b/src/index.ts index 3d654eb..0e1b0d1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,25 +4,19 @@ import { Chain, Sender, Fee, - createMessageSend, MessageSendParams } from '@tharsis/transactions'; -import { DeliverTxResponse, GasPrice, StdFee } from '@cosmjs/stargate'; +import { DeliverTxResponse, StdFee } from '@cosmjs/stargate'; import { RegistryClient } from './registry-client'; import { Account } from './account'; import { createTransaction } from './txbuilder'; -import { Payload, Record } from './types'; import { Util } from './util'; import { createTxMsgAssociateBond, - createTxMsgCancelBond, - createTxMsgCreateBond, createTxMsgDissociateBond, createTxMsgDissociateRecords, createTxMsgReAssociateRecords, - createTxMsgRefillBond, - createTxMsgWithdrawBond, MessageMsgAssociateBond, MessageMsgCancelBond, MessageMsgCreateBond, @@ -33,22 +27,12 @@ import { MessageMsgWithdrawBond } from './messages/bond'; import { - createTxMsgDeleteName, - createTxMsgReserveAuthority, - createTxMsgSetAuthorityBond, - createTxMsgSetName, - createTxMsgSetRecord, MessageMsgDeleteName, - MessageMsgReserveAuthority, MessageMsgSetAuthorityBond, MessageMsgSetName, - MessageMsgSetRecord, - NAMESERVICE_ERRORS, - parseMsgSetRecordResponse + NAMESERVICE_ERRORS } from './messages/registry'; import { - createTxMsgCommitBid, - createTxMsgRevealBid, MessageMsgCommitBid, MessageMsgRevealBid } from './messages/auction'; @@ -487,7 +471,7 @@ export class Registry { ); // TODO: Parse error response - return response; + return laconicClient.registry.decode(response.msgResponses[0]); } /** @@ -511,52 +495,7 @@ export class Registry { ); // TODO: Parse error response form delete name - return response; - } - - /** - * Submit record transaction. - * @param privateKey - private key in HEX to sign message. - * @param txPrivateKey - private key in HEX to sign transaction. - */ - async _submitRecordTx ( - { privateKey, record, bondId }: { privateKey: string, record: any, bondId: string }, - txPrivateKey: string, - fee: Fee - ) { - if (!isKeyValid(privateKey)) { - throw new Error('Registry privateKey should be a hex string.'); - } - - if (!isKeyValid(bondId)) { - throw new Error(`Invalid bondId: ${bondId}.`); - } - - // Sign record. - const recordSignerAccount = new Account(Buffer.from(privateKey, 'hex')); - const registryRecord = new Record(record); - const payload = new Payload(registryRecord); - await recordSignerAccount.signPayload(payload); - - // Send record payload Tx. - txPrivateKey = txPrivateKey || recordSignerAccount.getPrivateKey(); - return this._submitRecordPayloadTx({ payload, bondId }, txPrivateKey, fee); - } - - async _submitRecordPayloadTx (params: MessageMsgSetRecord, privateKey: string, fee: Fee) { - if (!isKeyValid(privateKey)) { - throw new Error('Registry privateKey should be a hex string.'); - } - - if (!isKeyValid(params.bondId)) { - throw new Error(`Invalid bondId: ${params.bondId}.`); - } - - const account = new Account(Buffer.from(privateKey, 'hex')); - const sender = await this._getSender(account); - - const msg = createTxMsgSetRecord(this._chain, sender, fee, '', params); - return this._submitTx(msg, privateKey, sender); + return laconicClient.registry.decode(response.msgResponses[0]); } /** diff --git a/src/laconic-client.ts b/src/laconic-client.ts index faeb69d..f62f69a 100644 --- a/src/laconic-client.ts +++ b/src/laconic-client.ts @@ -16,7 +16,7 @@ import { MsgCommitBidEncodeObject, MsgRevealBidEncodeObject, auctionTypes, typeU import { Payload } from './proto2/cerc/registry/v1/tx'; import { Record, Signature } from './proto2/cerc/registry/v1/registry'; import { Account } from './account'; -import { Record as RegistryRecord } from './types'; +import { Util } from './util'; export const laconicDefaultRegistryTypes: ReadonlyArray<[string, GeneratedType]> = [ ...defaultRegistryTypes, @@ -200,10 +200,10 @@ export class LaconicClient extends SigningStargateClient { // Sign record. const recordSignerAccount = new Account(Buffer.from(params.privateKey, 'hex')); await recordSignerAccount.init(); - const messageToSign = RegistryRecord.getMessageToSign(params.record); + const messageToSign = Util.sortJSON(params.record); const sig = await recordSignerAccount.signRecord(messageToSign); - const signature = Signature.fromJSON({ sig: sig.toString('base64'), pubKey: recordSignerAccount.publicKeyLaconic2 }); + const signature = Signature.fromJSON({ sig: sig.toString('base64'), pubKey: recordSignerAccount.registryPublicKey }); const payload = Payload.fromJSON({ record: registryRecord, signatures: [signature] }); diff --git a/src/messages/registry.ts b/src/messages/registry.ts index 03c24a4..2e4f258 100644 --- a/src/messages/registry.ts +++ b/src/messages/registry.ts @@ -8,9 +8,7 @@ import { } from '@tharsis/transactions'; import * as registryTx from '../proto/vulcanize/registry/v1beta1/tx'; -import * as registry from '../proto/vulcanize/registry/v1beta1/registry'; import { createTx } from './util'; -import { Payload } from '../types'; const MSG_RESERVE_AUTHORITY_TYPES = { MsgValue: [ @@ -97,11 +95,6 @@ export interface MessageMsgSetName { cid: string } -export interface MessageMsgSetRecord { - bondId: string - payload: Payload -} - export interface MessageMsgSetAuthorityBond { name: string bondId: string @@ -159,30 +152,6 @@ export function createTxMsgSetName ( return createTx(chain, sender, fee, memo, types, msg, msgCosmos); } -export function createTxMsgSetRecord ( - chain: Chain, - sender: Sender, - fee: Fee, - memo: string, - params: MessageMsgSetRecord -) { - const types = generateTypes(MSG_SET_RECORD_TYPES); - - const msg = createMsgSetRecord( - params.bondId, - params.payload, - sender.accountAddress - ); - - const msgCosmos = protoCreateMsgSetRecord( - params.bondId, - params.payload, - sender.accountAddress - ); - - return createTx(chain, sender, fee, memo, types, msg, msgCosmos); -} - export function createTxMsgSetAuthorityBond ( chain: Chain, sender: Sender, @@ -293,51 +262,6 @@ const protoCreateMsgSetName = ( }; }; -function createMsgSetRecord ( - bondId: string, - payload: Payload, - signer: string -) { - return { - type: 'registry/SetRecord', - value: { - bond_id: bondId, - signer, - payload: payload.serialize() - } - }; -} - -const protoCreateMsgSetRecord = ( - bondId: string, - payloadData: Payload, - signer: string -) => { - const record = new registry.vulcanize.registry.v1beta1.Record(payloadData.record.serialize()); - - const signatures = payloadData.signatures.map( - signature => new registry.vulcanize.registry.v1beta1.Signature( - signature.serialize() - ) - ); - - const payload = new registryTx.vulcanize.registry.v1beta1.Payload({ - record, - signatures - }); - - const setNameMessage = new registryTx.vulcanize.registry.v1beta1.MsgSetRecord({ - bond_id: bondId, - signer, - payload - }); - - return { - message: setNameMessage, - path: 'vulcanize.registry.v1beta1.MsgSetRecord' - }; -}; - function createMsgSetAuthorityBond ( name: string, bondId: string, diff --git a/src/nameservice-expiry.test.ts b/src/nameservice-expiry.test.ts index bfda78b..f5edba7 100644 --- a/src/nameservice-expiry.test.ts +++ b/src/nameservice-expiry.test.ts @@ -95,7 +95,6 @@ const nameserviceExpiryTests = () => { expect(records).toHaveLength(0); }); - // TODO: Check authority not expiring test('Check authority expired without bond balance', async () => { const [authority] = await registry.lookupAuthorities([authorityName]); expect(authority.status).toBe('expired'); diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 7f4bd25..0000000 --- a/src/types.ts +++ /dev/null @@ -1,132 +0,0 @@ -import assert from 'assert'; -import { Validator } from 'jsonschema'; - -import RecordSchema from './schema/record.json'; -import { Util } from './util'; - -/** - * Record. - */ -export class Record { - _record: any; - - /** - * New Record. - */ - constructor (record: any) { - assert(record); - - const validator = new Validator(); - const result = validator.validate(record, RecordSchema); - if (!result.valid) { - result.errors.map(console.error); - throw new Error('Invalid record input.'); - } - - this._record = record; - } - - get attributes () { - return Buffer.from(JSON.stringify(this._record), 'binary'); - } - - /** - * Serialize record. - */ - serialize () { - return { - id: '_', - bond_id: '_', - create_time: '_', - expiry_time: '_', - // Setting deleted as false (zero value) throws error in EIP712 signature verification. - deleted: true, - attributes: this.attributes - }; - } - - /** - * Get message to calculate record signature. - */ - - // TODO: Replace any type for record - static getMessageToSign (record: any) { - return Util.sortJSON(record); - } -} - -/** - * Record Signature. - */ -export class Signature { - _pubKey: string; - _sig: string; - - /** - * New Signature. - */ - constructor (pubKey: string, sig: string) { - assert(pubKey); - assert(sig); - - this._pubKey = pubKey; - this._sig = sig; - } - - /** - * Serialize Signature. - */ - serialize () { - return Util.sortJSON({ - pub_key: this._pubKey, - sig: this._sig - }); - } -} - -/** - * Message Payload. - */ -export class Payload { - _record: Record; - _signatures: Signature[]; - - /** - * New Payload. - */ - constructor (record: Record, ...signatures: Signature[]) { - assert(record); - - this._record = record; - this._signatures = signatures; - } - - get record () { - return this._record; - } - - get signatures () { - return this._signatures; - } - - /** - * Add message signature to payload. - */ - addSignature (signature: any) { - assert(signature); - - this._signatures.push(signature); - } - - /** - * Serialize Payload. - */ - serialize () { - // return Util.sortJSON({ - // }); - return { - record: this._record.serialize(), - signatures: this._signatures.map(s => s.serialize()) - }; - } -} -- 2.45.2