diff --git a/README.md b/README.md index 37032ed..1561720 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Follow these steps to run the tests: - Run tests: ```bash - yarn test:expiry + yarn test:nameservice-expiry ``` ## Development @@ -76,11 +76,15 @@ Follow these steps to run the tests: ## Known Issues -- [Util](./src/util.ts) `getContentId` method does not generate same CID compared to that in chiba-clonk. - -- Passing a float type value in [watcher attributes](./src/testing/data/watcher.yml) throws error when sending setRecord message. +- Passing a float type value in [watcher attributes](./src/testing/data/watcher.yml) throws error when sending `setRecord` message. ``` failed to execute message; message index: 0: Invalid signature.: unauthorized ``` -- When sending setRecord message, an integer value passed in watcher attributes is parsed as float type in chiba-clonk while [unmarshalling json](https://pkg.go.dev/encoding/json#Unmarshal). +- When sending `setRecord` message, an integer value passed in watcher attributes is parsed as float type in chiba-clonk while [unmarshalling json](https://pkg.go.dev/encoding/json#Unmarshal). + +- `setRecord` message throws error when fileds in [Record](./src/types.ts) message are not assigned. + ``` + failed to pack and hash typedData primary type: provided data '' doesn't match type 'string' [tharsis/ethermint/ethereum/eip712/eip712.go:33] + ``` + Passing dummy values to work around issue. diff --git a/package.json b/package.json index 2e6a37f..15663c2 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "scripts": { "test": "jest --runInBand --verbose", "test:auctions": "TEST_AUCTIONS_ENABLED=1 jest --runInBand --verbose src/auction.test.ts", - "test:expiry": "TEST_NAMESERVICE_EXPIRY=1 jest --runInBand --verbose src/nameservice-expiry.test.ts", + "test:nameservice-expiry": "TEST_NAMESERVICE_EXPIRY=1 jest --runInBand --verbose src/nameservice-expiry.test.ts", "build": "tsc" } } diff --git a/src/index.test.ts b/src/index.test.ts new file mode 100644 index 0000000..1c1baae --- /dev/null +++ b/src/index.test.ts @@ -0,0 +1,46 @@ +import { Account } from './account'; +import { Registry } from './index'; +import { getConfig } from './testing/helper'; + +const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); + +jest.setTimeout(90 * 1000); + +const registryTests = () => { + let registry: Registry; + + beforeAll(async () => { + registry = new Registry(restEndpoint, gqlEndpoint, chainId); + + }); + + test('Get account info.', async() => { + const account = new Account(Buffer.from(privateKey, 'hex')); + const accounts = await registry.getAccounts([account.formattedCosmosAddress]); + expect(accounts).toHaveLength(1) + const [accountObj] = accounts; + expect(accountObj.address).toBe(account.formattedCosmosAddress); + expect(accountObj.pubKey).toBe(account.encodedPubkey); + expect(accountObj.number).toBe('0'); + expect(accountObj.sequence).toBeDefined(); + expect(accountObj.balance).toHaveLength(1); + const [{ type, quantity }] = accountObj.balance + expect(type).toBe('aphoton'); + expect(quantity).toBeDefined(); + }) + + test('Get account balance.', async() => { + const mnenonic1 = Account.generateMnemonic(); + const otherAccount = await Account.generateFromMnemonic(mnenonic1); + await registry.sendCoins({ denom: 'aphoton', amount: '10000000000000000000000000', destinationAddress: otherAccount.formattedCosmosAddress }, privateKey, fee); + + const [accountObj] = await registry.getAccounts([otherAccount.formattedCosmosAddress]); + expect(accountObj).toBeDefined(); + expect(accountObj.address).toBe(otherAccount.formattedCosmosAddress); + const [{ type, quantity }] = accountObj.balance + expect(type).toBe('aphoton'); + expect(quantity).toBe('10000000000000000000000000'); + }) +} + +describe('Registry', registryTests); diff --git a/src/index.ts b/src/index.ts index 38fa588..bf15f26 100644 --- a/src/index.ts +++ b/src/index.ts @@ -125,10 +125,10 @@ export class Registry { } /** - * Get account by addresses. + * Get accounts by addresses. */ - async getAccount(address: string) { - return this._client.getAccount(address); + async getAccounts(addresses: string[]) { + return this._client.getAccounts(addresses); } /** @@ -166,14 +166,7 @@ export class Registry { async sendCoins(params: MessageSendParams, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createMessageSend(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -187,10 +180,14 @@ export class Registry { async getNextBondId(privateKey: string) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountObj } } = await this.getAccount(account.formattedCosmosAddress); + const accounts = await this.getAccounts([account.formattedCosmosAddress]); + if (!accounts.length) { + throw new Error('Account does not exist.'); + } + const [accountObj] = accounts; const nextSeq = parseInt(accountObj.sequence, 10) + 1; - result = sha256(`${accountObj.address}:${accountObj.account_number}:${nextSeq}`); + result = sha256(`${accountObj.address}:${accountObj.number}:${nextSeq}`); return result; } @@ -215,14 +212,7 @@ export class Registry { async createBond(params: MessageMsgCreateBond, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgCreateBond(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -236,14 +226,7 @@ export class Registry { async refillBond(params: MessageMsgRefillBond, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgRefillBond(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -257,14 +240,7 @@ export class Registry { async withdrawBond(params: MessageMsgWithdrawBond, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgWithdrawBond(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -278,14 +254,7 @@ export class Registry { async cancelBond(params: MessageMsgCancelBond, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgCancelBond(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -299,14 +268,7 @@ export class Registry { async reserveAuthority(params: { name: string, owner?: string }, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msgParams = { name: params.name, @@ -325,14 +287,7 @@ export class Registry { async setAuthorityBond(params: MessageMsgSetAuthorityBond, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgSetAuthorityBond(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -346,14 +301,7 @@ export class Registry { async commitBid(params: MessageMsgCommitBid, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgCommitBid(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -367,14 +315,7 @@ export class Registry { async revealBid(params: MessageMsgRevealBid, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgRevealBid(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -402,14 +343,7 @@ export class Registry { async setName(params: MessageMsgSetName, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgSetName(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -430,14 +364,7 @@ export class Registry { async deleteName(params: MessageMsgDeleteName, privateKey: string, fee: Fee) { let result; const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgDeleteName(this._chain, sender, fee, '', params) result = await this._submitTx(msg, privateKey, sender); @@ -483,14 +410,7 @@ export class Registry { } const account = new Account(Buffer.from(privateKey, 'hex')); - const { account: { base_account: accountInfo } } = await this.getAccount(account.formattedCosmosAddress); - - const sender = { - accountAddress: account.formattedCosmosAddress, - sequence: accountInfo.sequence, - accountNumber: accountInfo.account_number, - pubkey: account.encodedPubkey, - } + const sender = await this._getSender(account); const msg = createTxMsgSetRecord(this._chain, sender, fee, '', params) return this._submitTx(msg, privateKey, sender); @@ -499,7 +419,7 @@ export class Registry { /** * Submit a generic Tx to the chain. */ - async _submitTx(message: any, privateKey: string, sender: Sender) { + async _submitTx(message: any, privateKey: string, sender: Sender) { // Check private key. if (!isKeyValid(privateKey)) { throw new Error('Registry privateKey should be a hex string.'); @@ -534,6 +454,25 @@ export class Registry { return Number(ethChainId) } + + /** + * Get sender used for creating message. + */ + async _getSender (account: Account) { + const accounts = await this.getAccounts([account.formattedCosmosAddress]); + if (!accounts.length) { + throw new Error('Account does not exist.'); + } + + const [{ number, sequence }] = accounts; + + return { + accountAddress: account.formattedCosmosAddress, + sequence: sequence, + accountNumber: number, + pubkey: account.encodedPubkey, + } + } } export { Account } diff --git a/src/nameservice-expiry.test.ts b/src/nameservice-expiry.test.ts index 86fce74..e395db7 100644 --- a/src/nameservice-expiry.test.ts +++ b/src/nameservice-expiry.test.ts @@ -86,12 +86,12 @@ const nameserviceExpiryTests = () => { setTimeout(done, 60 * 1000); }); - test('Check record deleted without balance', async() => { + test('Check record deleted without bond balance', async() => { const records = await registry.queryRecords({ type: 'watcher', version: watcher.record.version }, true); expect(records).toHaveLength(0); }) - test('Check authority expired without balance', async() => { + test('Check authority expired without bond balance', async() => { const [authority] = await registry.lookupAuthorities([authorityName]); expect(authority.status).toBe('expired'); }) @@ -109,7 +109,7 @@ if (!process.env.TEST_NAMESERVICE_EXPIRY) { Run tests: - yarn test:expiry + yarn test:nameservice-expiry */ describe('Nameservice Expiry', nameserviceExpiryTests) diff --git a/src/naming.test.ts b/src/naming.test.ts index 1a52278..1c042ad 100644 --- a/src/naming.test.ts +++ b/src/naming.test.ts @@ -107,7 +107,7 @@ const namingTests = () => { test('Set name for unbonded authority', async () => { crn = `crn://${authorityName}/app/test`; assert(watcherId) - await expect(registry.setName({ crn: crn, cid: watcherId }, privateKey, fee)).rejects.toThrow('Authority bond not found.'); + await expect(registry.setName({ crn, cid: watcherId }, privateKey, fee)).rejects.toThrow('Authority bond not found.'); }); test('Set authority bond', async () => { @@ -116,7 +116,7 @@ const namingTests = () => { test('Set name', async () => { crn = `crn://${authorityName}/app/test`; - await registry.setName({ crn: crn, cid: watcherId }, privateKey, fee); + await registry.setName({ crn, cid: watcherId }, privateKey, fee); // Query records should return it (some CRN points to it). const records = await registry.queryRecords({ type: 'watcher', version: watcher.record.version }); @@ -159,7 +159,7 @@ const namingTests = () => { ) const updatedWatcherId = result.data.id; - await registry.setName({ crn: crn, cid: updatedWatcherId }, privateKey, fee); + await registry.setName({ crn, cid: updatedWatcherId }, privateKey, fee); const records = await registry.lookupNames([crn], true); expect(records).toHaveLength(1); @@ -216,7 +216,7 @@ const namingTests = () => { }); test('Delete name', async () => { - await registry.deleteName({ crn: crn }, privateKey, fee); + await registry.deleteName({ crn }, privateKey, fee); let records = await registry.lookupNames([crn], true); expect(records).toBeDefined(); @@ -240,7 +240,7 @@ const namingTests = () => { }); test('Delete already deleted name', async () => { - await registry.deleteName({ crn: crn }, privateKey, fee); + await registry.deleteName({ crn }, privateKey, fee); const records = await registry.lookupNames([crn], true); expect(records).toBeDefined(); diff --git a/src/registry-client.ts b/src/registry-client.ts index 706ecef..9d09f38 100644 --- a/src/registry-client.ts +++ b/src/registry-client.ts @@ -133,15 +133,32 @@ export class RegistryClient { }); } + /** - * Fetch Account. + * Fetch Accounts. */ - async getAccount(address: string) { - assert(address); + async getAccounts(addresses: string[]) { + assert(addresses); + assert(addresses.length); - let { data } = await axios.get(`${this._restEndpoint}${generateEndpointAccount(address)}`) + const query = `query ($addresses: [String!]) { + getAccounts(addresses: $addresses) { + address + pubKey + number + sequence + balance { + type + quantity + } + } + }`; - return data + const variables = { + addresses + }; + + return RegistryClient.getResult(this._graph(query)(variables), 'getAccounts'); } /**