diff --git a/src/account.ts b/src/account.ts index eae01c9..070f4f2 100644 --- a/src/account.ts +++ b/src/account.ts @@ -118,6 +118,13 @@ export class Account { return this._privateKey.toString('hex'); } + /** + * Get cosmos address. + */ + getCosmosAddress() { + return this._formattedCosmosAddress; + } + /** * Get record signature. */ diff --git a/src/index.ts b/src/index.ts index bf15f26..c7862fc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -94,7 +94,8 @@ export const createBid = async (chainId: string, auctionId: string, bidderAddres export const isKeyValid = (key: string) => key && key.match(/^[0-9a-fA-F]{64}$/); export class Registry { - _endpoint: string + _endpoints: {[key: string]: string} + _chainID: string _chain: Chain _client: RegistryClient @@ -115,8 +116,13 @@ export class Registry { throw new Error('Path to a GQL endpoint should be provided.'); } - this._endpoint = restUrl; + this._endpoints = { + rest: restUrl, + gql: gqlUrl + }; + this._client = new RegistryClient(restUrl, gqlUrl); + this._chainID = chainId; this._chain = { cosmosChainId: chainId, @@ -131,6 +137,28 @@ export class Registry { return this._client.getAccounts(addresses); } + get endpoints() { + return this._endpoints; + } + + get chainID() { + return this._chainID; + } + + /** + * Get server status. + */ + async getStatus() { + return this._client.getStatus(); + } + + /** + * Get records by ids. + */ + async getRecordsByIds(ids: string[], refs = false) { + return this._client.getRecordsByIds(ids, refs); + } + /** * Get records by attributes. */ diff --git a/src/naming.test.ts b/src/naming.test.ts index 1c042ad..284e43f 100644 --- a/src/naming.test.ts +++ b/src/naming.test.ts @@ -99,7 +99,7 @@ const namingTests = () => { const [record] = await registry.lookupAuthorities([subAuthority]); expect(record).toBeDefined(); expect(record.ownerAddress).toBeDefined(); - expect(record.ownerAddress).toBe(otherAccount1.formattedCosmosAddress); + expect(record.ownerAddress).toBe(otherAccount1.getCosmosAddress()); expect(record.ownerPublicKey).toBeDefined(); expect(Number(record.height)).toBeGreaterThan(0); }); diff --git a/src/registry-client.ts b/src/registry-client.ts index 9d09f38..79cc5f7 100644 --- a/src/registry-client.ts +++ b/src/registry-client.ts @@ -133,6 +133,51 @@ export class RegistryClient { }); } + /** + * Get server status. + */ + async getStatus() { + const query = `query { + getStatus { + version + node { + id + network + moniker + } + sync { + latest_block_hash + latest_block_height + latest_block_time + catching_up + } + validator { + address + voting_power + } + validators { + address + voting_power + proposer_priority + } + num_peers + peers { + node { + id + network + moniker + } + is_outbound + remote_ip + } + disk_usage + } + }`; + + const { getStatus: status } = await this._graph(query)(); + + return status; + } /** * Fetch Accounts. @@ -161,6 +206,33 @@ export class RegistryClient { return RegistryClient.getResult(this._graph(query)(variables), 'getAccounts'); } + /** + * Get records by ids. + */ + async getRecordsByIds(ids: string[], refs = false) { + assert(ids); + assert(ids.length); + + const query = `query ($ids: [String!]) { + getRecordsByIds(ids: $ids) { + id + names + owners + bondId + createTime + expiryTime + ${attributeField} + ${refs ? refsField : ''} + } + }`; + + const variables = { + ids + }; + + return RegistryClient.getResult(this._graph(query)(variables), 'getRecordsByIds', RegistryClient.prepareAttributes('attributes')); + } + /** * Get records by attributes. */ diff --git a/src/sdk.test.ts b/src/sdk.test.ts new file mode 100644 index 0000000..cc31e43 --- /dev/null +++ b/src/sdk.test.ts @@ -0,0 +1,79 @@ +import path from 'path'; + +import { Registry } from './index'; +import { getConfig, ensureUpdatedConfig, provisionBondId } from './testing/helper'; + +const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); + +jest.setTimeout(40 * 1000); + +const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); + +describe('Querying', () => { + let watcher: any; + let registry: Registry; + let bondId: string; + + beforeAll(async () => { + registry = new Registry(restEndpoint, gqlEndpoint, chainId); + bondId = await provisionBondId(registry, privateKey, fee); + + 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(); + }); + + test('Endpoint and chain ID.', async () => { + expect(registry.endpoints.rest).toBe(restEndpoint); + expect(registry.endpoints.gql).toBe(gqlEndpoint); + expect(registry.chainID).toBe(chainId); + }); + + xtest('Get status.', async () => { + const status = await registry.getStatus(); + expect(status).toBeDefined(); + expect(status.version).toBeDefined(); + }); + + test('List records.', async () => { + const records = await registry.queryRecords({}, true); + expect(records.length).toBeGreaterThanOrEqual(1); + }); + + test('Query records by reference.', async () => { + const { protocol } = watcher.record; + const records = await registry.queryRecords({ protocol }, true); + expect(records.length).toBeGreaterThanOrEqual(1); + + const { attributes: { protocol: recordProtocol } } = records[0]; + expect(protocol['/']).toBe(recordProtocol['/']); + }); + + test('Query records by attributes.', async () => { + const { version, name } = watcher.record; + const records = await registry.queryRecords({ version, name }, true); + expect(records.length).toBe(1); + + [ watcher ] = records; + const { attributes: { version: recordVersion, name: recordName } } = watcher; + expect(recordVersion).toBe(version); + expect(recordName).toBe(name); + }); + + 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); + }); + + test('Query records passing refs true.', async () => { + const [record] = await registry.getRecordsByIds([watcher.id], true); + expect(record.id).toBe(watcher.id); + expect(record.references).toBeDefined(); + expect(record.references).toHaveLength(1); + }); +}); diff --git a/src/testing/helper.ts b/src/testing/helper.ts index 75e3854..f5f44aa 100644 --- a/src/testing/helper.ts +++ b/src/testing/helper.ts @@ -1,6 +1,9 @@ import assert from 'assert'; import yaml from 'node-yaml'; import semver from 'semver'; +import { Fee } from '@tharsis/transactions'; + +import { Registry } from '../index'; export const ensureUpdatedConfig = async (path: string) => { const conf = await yaml.read(path); @@ -17,6 +20,19 @@ export const getBaseConfig = async (path: string) => { return conf; }; +/** + * Provision a bond for record registration. + */ +export const provisionBondId = async (registry: Registry, privateKey: string, fee: Fee) => { + let bonds = await registry.queryBonds(); + if (!bonds.length) { + await registry.createBond({ denom: 'uwire', amount: '1000000000' }, privateKey, fee); + bonds = await registry.queryBonds(); + } + + return bonds[0].id; +}; + export const getConfig = () => { assert(process.env.PRIVATE_KEY);