Implement methods and tests for associate/dissociate bonds and records (#4)

* Implement methods for bond associate and dissociate

* Uncomment test for getStatus GQL query
This commit is contained in:
nikugogoi 2022-04-27 15:30:21 +05:30 committed by GitHub
parent 3d103b5fca
commit 27a176fbad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 404 additions and 3 deletions

View File

@ -1,5 +1,9 @@
import path from 'path';
import { Registry } from './index'; import { Registry } from './index';
import { getConfig } from './testing/helper'; import { ensureUpdatedConfig, getConfig } from './testing/helper';
const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig();
@ -7,10 +11,23 @@ jest.setTimeout(90 * 1000);
const bondTests = () => { const bondTests = () => {
let registry: Registry; let registry: Registry;
let watcher: any;
let version1: string;
let version2: string;
let bondId1: string; let bondId1: string;
let bondId2: string;
let bondOwner: string; let bondOwner: string;
const publishNewWatcherVersion = async (bondId: string) => {
watcher = await ensureUpdatedConfig(WATCHER_YML_PATH);
await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, fee);
return watcher.record.version;
};
beforeAll(async () => { beforeAll(async () => {
registry = new Registry(restEndpoint, gqlEndpoint, chainId); registry = new Registry(restEndpoint, gqlEndpoint, chainId);
}); });
@ -72,6 +89,60 @@ const bondTests = () => {
expect(bond.owner).toBe(""); expect(bond.owner).toBe("");
expect(bond.balance).toHaveLength(0); expect(bond.balance).toHaveLength(0);
}); });
test('Associate/Dissociate bond.', async () => {
bondId1 = await registry.getNextBondId(privateKey);
expect(bondId1).toBeDefined();
await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, privateKey, fee);
// Create a new record.
version1 = await publishNewWatcherVersion(bondId1);
let [record1] = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version1 }, true);
expect(record1.bondId).toBe(bondId1);
// Dissociate record, query and confirm.
await registry.dissociateBond({ recordId: record1.id }, privateKey, fee);
[record1] = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version1 }, true);
expect(record1.bondId).toBe('');
// Associate record with bond, query and confirm.
await registry.associateBond({ recordId: record1.id, bondId: bondId1 }, privateKey, fee);
[record1] = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version1 }, true);
expect(record1.bondId).toBe(bondId1);
});
test('Reassociate/Dissociate records.', async () => {
// Create a new record version.
version2 = await publishNewWatcherVersion(bondId1);
// Check version1, version2 as associated with bondId1.
let records;
records = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version1 }, true);
expect(records[0].bondId).toBe(bondId1);
records = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version2 }, true);
expect(records[0].bondId).toBe(bondId1);
// Create another bond.
bondId2 = await registry.getNextBondId(privateKey);
expect(bondId2).toBeDefined();
await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, privateKey, fee);
const [bond] = await registry.getBondsByIds([bondId2]);
expect(bond.id).toBe(bondId2);
// Reassociate records from bondId1 to bondId2, verify change.
await registry.reassociateRecords({ oldBondId: bondId1, newBondId: bondId2 }, privateKey, fee);
records = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version1 }, true);
expect(records[0].bondId).toBe(bondId2);
records = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version2 }, true);
expect(records[0].bondId).toBe(bondId2);
// Dissociate all records from bond, verify change.
await registry.dissociateRecords({ bondId: bondId2 }, privateKey, fee);
records = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version1 }, true);
expect(records[0].bondId).toBe('');
records = await registry.queryRecords({ type: watcher.record.type, name: watcher.record.name, version: version2 }, true);
expect(records[0].bondId).toBe('');
});
}; };
describe('Bonds', bondTests); describe('Bonds', bondTests);

View File

@ -15,12 +15,20 @@ import { createTransaction } from "./txbuilder";
import { Payload, Record } from './types'; import { Payload, Record } from './types';
import { Util } from './util'; import { Util } from './util';
import { import {
createTxMsgAssociateBond,
createTxMsgCancelBond, createTxMsgCancelBond,
createTxMsgCreateBond, createTxMsgCreateBond,
createTxMsgDissociateBond,
createTxMsgDissociateRecords,
createTxMsgReAssociateRecords,
createTxMsgRefillBond, createTxMsgRefillBond,
createTxMsgWithdrawBond, createTxMsgWithdrawBond,
MessageMsgAssociateBond,
MessageMsgCancelBond, MessageMsgCancelBond,
MessageMsgCreateBond, MessageMsgCreateBond,
MessageMsgDissociateBond,
MessageMsgDissociateRecords,
MessageMsgReAssociateRecords,
MessageMsgRefillBond, MessageMsgRefillBond,
MessageMsgWithdrawBond MessageMsgWithdrawBond
} from "./messages/bond"; } from "./messages/bond";
@ -104,6 +112,10 @@ export class Registry {
// https://gist.github.com/nikugogoi/de55d390574ded3466abad8bffd81952#file-txresponse-js-L7 // https://gist.github.com/nikugogoi/de55d390574ded3466abad8bffd81952#file-txresponse-js-L7
const errorMessage = NAMESERVICE_ERRORS.find(message => error.includes(message)) const errorMessage = NAMESERVICE_ERRORS.find(message => error.includes(message))
if (!errorMessage) {
console.error(error)
}
return errorMessage || DEFAULT_WRITE_ERROR; return errorMessage || DEFAULT_WRITE_ERROR;
} }
@ -290,6 +302,62 @@ export class Registry {
return parseTxResponse(result); return parseTxResponse(result);
} }
/**
* Associate record with bond.
*/
async associateBond(params: MessageMsgAssociateBond, privateKey: string, fee: Fee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex'));
const sender = await this._getSender(account);
const msg = createTxMsgAssociateBond(this._chain, sender, fee, '', params)
result = await this._submitTx(msg, privateKey, sender);
return parseTxResponse(result);
}
/**
* Dissociate record from bond.
*/
async dissociateBond(params: MessageMsgDissociateBond, privateKey: string, fee: Fee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex'));
const sender = await this._getSender(account);
const msg = createTxMsgDissociateBond(this._chain, sender, fee, '', params)
result = await this._submitTx(msg, privateKey, sender);
return parseTxResponse(result);
}
/**
* Dissociate all records from bond.
*/
async dissociateRecords(params: MessageMsgDissociateRecords, privateKey: string, fee: Fee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex'));
const sender = await this._getSender(account);
const msg = createTxMsgDissociateRecords(this._chain, sender, fee, '', params)
result = await this._submitTx(msg, privateKey, sender);
return parseTxResponse(result);
}
/**
* Reassociate records (switch bond).
*/
async reassociateRecords(params: MessageMsgReAssociateRecords, privateKey: string, fee: Fee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex'));
const sender = await this._getSender(account);
const msg = createTxMsgReAssociateRecords(this._chain, sender, fee, '', params)
result = await this._submitTx(msg, privateKey, sender);
return parseTxResponse(result);
}
/** /**
* Reserve authority. * Reserve authority.
*/ */
@ -425,6 +493,7 @@ export class Registry {
await recordSignerAccount.signPayload(payload); await recordSignerAccount.signPayload(payload);
// Send record payload Tx. // Send record payload Tx.
txPrivateKey = txPrivateKey || recordSignerAccount.getPrivateKey();
return this._submitRecordPayloadTx({ payload, bondId }, txPrivateKey, fee); return this._submitRecordPayloadTx({ payload, bondId }, txPrivateKey, fee);
} }

View File

@ -8,6 +8,7 @@ import {
} from '@tharsis/transactions' } from '@tharsis/transactions'
import * as bondTx from '../proto/vulcanize/bond/v1beta1/tx' import * as bondTx from '../proto/vulcanize/bond/v1beta1/tx'
import * as nameserviceTx from '../proto/vulcanize/nameservice/v1beta1/tx'
import * as coin from '../proto/cosmos/base/v1beta1/coin' import * as coin from '../proto/cosmos/base/v1beta1/coin'
import { createTx } from './util' import { createTx } from './util'
@ -53,6 +54,36 @@ const MSG_CANCEL_BOND_TYPES = {
] ]
} }
const MSG_ASSOCIATE_BOND_TYPES = {
MsgValue: [
{ name: 'record_id', type: 'string' },
{ name: 'bond_id', type: 'string' },
{ name: 'signer', type: 'string' },
]
}
const MSG_DISSOCIATE_BOND_TYPES = {
MsgValue: [
{ name: 'record_id', type: 'string' },
{ name: 'signer', type: 'string' },
]
}
const MSG_DISSOCIATE_RECORDS_TYPES = {
MsgValue: [
{ name: 'bond_id', type: 'string' },
{ name: 'signer', type: 'string' },
]
}
const MSG_REASSOCIATE_RECORDS_TYPES = {
MsgValue: [
{ name: 'new_bond_id', type: 'string' },
{ name: 'old_bond_id', type: 'string' },
{ name: 'signer', type: 'string' },
]
}
export interface MessageMsgCreateBond { export interface MessageMsgCreateBond {
amount: string amount: string
denom: string denom: string
@ -74,6 +105,24 @@ export interface MessageMsgCancelBond {
id: string id: string
} }
export interface MessageMsgAssociateBond {
bondId: string,
recordId: string
}
export interface MessageMsgDissociateBond {
recordId: string
}
export interface MessageMsgDissociateRecords {
bondId: string
}
export interface MessageMsgReAssociateRecords {
newBondId: string
oldBondId: string
}
export function createTxMsgCreateBond( export function createTxMsgCreateBond(
chain: Chain, chain: Chain,
sender: Sender, sender: Sender,
@ -172,6 +221,98 @@ export function createTxMsgCancelBond(
return createTx(chain, sender, fee, memo, types, msg, msgCosmos) return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
} }
export function createTxMsgAssociateBond(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgAssociateBond,
) {
const types = generateTypes(MSG_ASSOCIATE_BOND_TYPES)
const msg = createMsgAssociateBond(
params.recordId,
params.bondId,
sender.accountAddress
)
const msgCosmos = protoCreateMsgAssociateBond(
params.recordId,
params.bondId,
sender.accountAddress
)
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
export function createTxMsgDissociateBond(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgDissociateBond,
) {
const types = generateTypes(MSG_DISSOCIATE_BOND_TYPES)
const msg = createMsgDissociateBond(
params.recordId,
sender.accountAddress
)
const msgCosmos = protoCreateMsgDissociateBond(
params.recordId,
sender.accountAddress
)
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
export function createTxMsgDissociateRecords(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgDissociateRecords,
) {
const types = generateTypes(MSG_DISSOCIATE_RECORDS_TYPES)
const msg = createMsgDissociateRecords(
params.bondId,
sender.accountAddress
)
const msgCosmos = protoCreateMsgDissociateRecords(
params.bondId,
sender.accountAddress
)
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
export function createTxMsgReAssociateRecords(
chain: Chain,
sender: Sender,
fee: Fee,
memo: string,
params: MessageMsgReAssociateRecords,
) {
const types = generateTypes(MSG_REASSOCIATE_RECORDS_TYPES)
const msg = createMsgReAssociateRecords(
params.newBondId,
params.oldBondId,
sender.accountAddress
)
const msgCosmos = protoCreateMsgReAssociateRecords(
params.newBondId,
params.oldBondId,
sender.accountAddress
)
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
}
function createMsgCreateBond( function createMsgCreateBond(
signer: string, signer: string,
amount: string, amount: string,
@ -327,3 +468,123 @@ const protoCreateMsgCancelBond = (
path: 'vulcanize.bond.v1beta1.MsgCancelBond', path: 'vulcanize.bond.v1beta1.MsgCancelBond',
} }
} }
function createMsgAssociateBond(
recordId: string,
bondId: string,
signer: string
) {
return {
type: 'nameservice/AssociateBond',
value: {
record_id: recordId,
bond_id: bondId,
signer
},
}
}
const protoCreateMsgAssociateBond = (
recordId: string,
bondId: string,
signer: string
) => {
const associateBondMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgAssociateBond({
record_id: recordId,
bond_id: bondId,
signer
})
return {
message: associateBondMessage,
path: 'vulcanize.nameservice.v1beta1.MsgAssociateBond',
}
}
function createMsgDissociateBond(
recordId: string,
signer: string
) {
return {
type: 'nameservice/DissociateBond',
value: {
record_id: recordId,
signer
},
}
}
const protoCreateMsgDissociateBond = (
recordId: string,
signer: string
) => {
const dissociateBondMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgDissociateBond({
record_id: recordId,
signer
})
return {
message: dissociateBondMessage,
path: 'vulcanize.nameservice.v1beta1.MsgDissociateBond',
}
}
function createMsgDissociateRecords(
bondId: string,
signer: string
) {
return {
type: 'nameservice/DissociateRecords',
value: {
bond_id: bondId,
signer
},
}
}
const protoCreateMsgDissociateRecords = (
bondId: string,
signer: string
) => {
const dissociateRecordsMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgDissociateRecords({
bond_id: bondId,
signer
})
return {
message: dissociateRecordsMessage,
path: 'vulcanize.nameservice.v1beta1.MsgDissociateRecords',
}
}
function createMsgReAssociateRecords(
newBondId: string,
oldBondId: string,
signer: string
) {
return {
type: 'nameservice/ReassociateRecords',
value: {
new_bond_id: newBondId,
old_bond_id: oldBondId,
signer
},
}
}
const protoCreateMsgReAssociateRecords = (
newBondId: string,
oldBondId: string,
signer: string
) => {
const reAssociateRecordsMessage = new nameserviceTx.vulcanize.nameservice.v1beta1.MsgReAssociateRecords({
new_bond_id: newBondId,
old_bond_id: oldBondId,
signer
})
return {
message: reAssociateRecordsMessage,
path: 'vulcanize.nameservice.v1beta1.MsgReAssociateRecords',
}
}

View File

@ -33,7 +33,7 @@ describe('Querying', () => {
expect(registry.chainID).toBe(chainId); expect(registry.chainID).toBe(chainId);
}); });
xtest('Get status.', async () => { test('Get status.', async () => {
const status = await registry.getStatus(); const status = await registry.getStatus();
expect(status).toBeDefined(); expect(status).toBeDefined();
expect(status.version).toBeDefined(); expect(status.version).toBeDefined();

View File

@ -26,7 +26,7 @@ export const getBaseConfig = async (path: string) => {
export const provisionBondId = async (registry: Registry, privateKey: string, fee: Fee) => { export const provisionBondId = async (registry: Registry, privateKey: string, fee: Fee) => {
let bonds = await registry.queryBonds(); let bonds = await registry.queryBonds();
if (!bonds.length) { if (!bonds.length) {
await registry.createBond({ denom: 'uwire', amount: '1000000000' }, privateKey, fee); await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, privateKey, fee);
bonds = await registry.queryBonds(); bonds = await registry.queryBonds();
} }