Add nameservice tests for reserve and lookup authority

This commit is contained in:
nabarun 2022-04-05 11:01:10 +05:30 committed by Ashwin Phatak
parent 36b633b908
commit 65e90e7af0
5 changed files with 285 additions and 2 deletions

View File

@ -12,6 +12,7 @@ import { createTxMsgCancelBond, createTxMsgCreateBond, createTxMsgRefillBond, cr
import { RegistryClient } from "./registry-client"; import { RegistryClient } from "./registry-client";
import { Account } from "./account"; import { Account } from "./account";
import { createTransaction } from "./txbuilder"; import { createTransaction } from "./txbuilder";
import { createTxMsgReserveAuthority, MessageMsgReserveAuthority } from './nameservice';
const DEFAULT_WRITE_ERROR = 'Unable to write to chiba-clonk.'; const DEFAULT_WRITE_ERROR = 'Unable to write to chiba-clonk.';
@ -215,6 +216,39 @@ export class Registry {
return parseTxResponse(result); return parseTxResponse(result);
} }
/**
* Reserve authority.
*/
async reserveAuthority(params: MessageMsgReserveAuthority, senderAddress: string, privateKey: string, fee: Fee) {
let result;
try {
const { account: { base_account: accountInfo } } = await this.getAccount(senderAddress);
const sender = {
accountAddress: accountInfo.address,
sequence: accountInfo.sequence,
accountNumber: accountInfo.account_number,
pubkey: accountInfo.pub_key.key,
}
const msg = createTxMsgReserveAuthority(this._chain, sender, fee, '', params)
result = await this._submitTx(msg, privateKey, sender);
} catch (err: any) {
const error = err[0] || err;
throw new Error(Registry.processWriteError(error));
}
return parseTxResponse(result);
}
/**
* Lookup authorities by names.
*/
async lookupAuthorities(names: string[], auction = false) {
return this._client.lookupAuthorities(names, auction);
}
/** /**
* Submit a generic Tx to the chain. * Submit a generic Tx to the chain.
*/ */
@ -237,3 +271,5 @@ export class Registry {
return response; return response;
} }
} }
export { Account }

118
src/nameservice.ts Normal file
View File

@ -0,0 +1,118 @@
import {
createEIP712,
generateFee,
generateMessage,
generateTypes,
} from '@tharsis/eip712'
import {
Chain,
Sender,
Fee,
} from '@tharsis/transactions'
import { createTransaction } from '@tharsis/proto'
import * as nameserviceTx from './proto/vulcanize/nameservice/v1beta1/tx'
const MSG_RESERVE_AUTHORITY_TYPES = {
MsgValue: [
{ name: 'name', type: 'string' },
{ name: 'signer', type: 'string' },
{ name: 'owner', type: 'string' },
],
}
export interface MessageMsgReserveAuthority {
name: string
owner: string
}
export function createTxMsgReserveAuthority(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgReserveAuthority,
) {
// EIP712
const feeObject = generateFee(
fee.amount,
fee.denom,
fee.gas,
sender.accountAddress,
)
const types = generateTypes(MSG_RESERVE_AUTHORITY_TYPES)
const msg = createMsgReserveAuthority(
params.name,
sender.accountAddress,
params.owner
)
const messages = generateMessage(
sender.accountNumber.toString(),
sender.sequence.toString(),
chain.cosmosChainId,
memo,
feeObject,
msg,
)
const eipToSign = createEIP712(types, chain.chainId, messages)
// Cosmos
const msgCosmos = protoCreateMsgReserveAuthority(
params.name,
sender.accountAddress,
params.owner
)
const tx = createTransaction(
msgCosmos,
memo,
fee.amount,
fee.denom,
parseInt(fee.gas, 10),
'ethsecp256',
sender.pubkey,
sender.sequence,
sender.accountNumber,
chain.cosmosChainId,
)
return {
signDirect: tx.signDirect,
legacyAmino: tx.legacyAmino,
eipToSign,
}
}
function createMsgReserveAuthority(
name: string,
signer: string,
owner: string
) {
return {
type: 'nameservice/ReserveAuthority',
value: {
name,
signer,
owner
},
}
}
const protoCreateMsgReserveAuthority = (
name: string,
signer: string,
owner: string,
) => {
const reserveAuthorityMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgReserveAuthority({
name,
signer,
owner
})
return {
message: reserveAuthorityMessage,
path: 'vulcanize.nameservice.v1beta1.MsgReserveAuthority',
}
}

53
src/naming.test.ts Normal file
View File

@ -0,0 +1,53 @@
import { Registry } from './index';
import { getConfig, wait } from './testing/helper';
jest.setTimeout(120 * 1000);
const { mockServer, chibaClonk: { chainId, restEndpoint, gqlEndpoint, privateKey, accountAddress, fee } } = getConfig();
const namingTests = () => {
let registry: Registry;
let bondId: string;
let authorityName: string;
beforeAll(async () => {
registry = new Registry(restEndpoint, gqlEndpoint, chainId);
// Create bond.
bondId = await registry.getNextBondId(accountAddress);
await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, accountAddress, privateKey, fee);
await wait(5000)
});
test('Reserve authority.', async () => {
authorityName = `dxos-${Date.now()}`;
await registry.reserveAuthority({ name: authorityName, owner: accountAddress }, accountAddress, privateKey, fee);
await wait(5000)
});
test('Lookup authority.', async () => {
const [record] = await registry.lookupAuthorities([authorityName]);
expect(record).toBeDefined();
expect(record.ownerAddress).not.toBe('');
expect(record.ownerPublicKey).not.toBe('');
expect(Number(record.height)).toBeGreaterThan(0);
});
test('Lookup non existing authority', async () => {
const [record] = await registry.lookupAuthorities(['does-not-exist']);
expect(record.ownerAddress).toBe('');
expect(record.ownerPublicKey).toBe('');
expect(Number(record.height)).toBe(0);
});
};
if (mockServer || process.env.WIRE_AUCTIONS_ENABLED) {
// Required as jest complains if file has no tests.
test('skipping naming tests', () => {});
} else {
describe('Naming', namingTests);
}

View File

@ -5,6 +5,55 @@ import { generateEndpointAccount, generateEndpointBroadcast, generatePostBodyBro
import { Util } from './util'; import { Util } from './util';
const auctionFields = `
id
status
ownerAddress
createTime
commitsEndTime
revealsEndTime
commitFee {
type
quantity
}
revealFee {
type
quantity
}
minimumBid {
type
quantity
}
winnerAddress
winnerBid {
type
quantity
}
winnerPrice {
type
quantity
}
bids {
bidderAddress
status
commitHash
commitTime
revealTime
commitFee {
type
quantity
}
revealFee {
type
quantity
}
bidAmount {
type
quantity
}
}
`;
/** /**
* Registry * Registry
*/ */
@ -51,6 +100,33 @@ export class RegistryClient {
return data return data
} }
/**
* Lookup authorities by names.
*/
async lookupAuthorities(names: string[], auction = false) {
assert(names.length);
const query = `query ($names: [String!]) {
lookupAuthorities(names: $names) {
ownerAddress
ownerPublicKey
height
status
bondId
expiryTime
${auction ? ('auction { ' + auctionFields + ' }') : ''}
}
}`;
const variables = {
names
};
const result = await this._graph(query)(variables);
return result['lookupAuthorities'];
}
/** /**
* Get bonds by ids. * Get bonds by ids.
*/ */

View File

@ -1,5 +1,5 @@
const DEFAULT_PRIVATE_KEY = '3d8e23810daecb66ec4ca97805f6bbfc102015c3f22cdda1a783b1d074c43bdd'; const DEFAULT_PRIVATE_KEY = '39e06e1471f69a76491e60d1d22908789bf7801039a9ac2197ed432ad45d2daf';
const DEFAULT_ADDRESS = 'ethm1lrdrh056ce23h9d9d5rx34tp0uwj0u9zumynx3' const DEFAULT_ADDRESS = 'ethm1p9fqwtlypqptuqgndpce5g6wncj4py9z30wfkt'
export const wait = (time: number) => new Promise(resolve => setTimeout(resolve, time)) export const wait = (time: number) => new Promise(resolve => setTimeout(resolve, time))