Update bond-record association methods to use cosmjs (#3)

Part of https://www.notion.so/Create-laconic-registry-SDK-d3a636d4aba44f7cbba3bd99b7146811

- Update methods to
  - associate and dissociate a bond from a record
  - dissociate all records from a bond
  - reassociate all record from a bond to another bond
- Update bond tests with changes

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
Reviewed-on: #3
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
This commit is contained in:
Prathamesh Musale 2024-03-11 11:27:27 +00:00 committed by nabarun
parent 227cd3d318
commit 8d3c35b22e
11 changed files with 211 additions and 109 deletions

View File

@ -1,10 +1,9 @@
import { Registry, Account, createBid } from './index'; import { Registry, Account, createBid } from './index';
import { getConfig, getLaconic2Config } from './testing/helper'; import { getConfig } from './testing/helper';
import { DENOM } from './constants'; import { DENOM } from './constants';
jest.setTimeout(30 * 60 * 1000); jest.setTimeout(30 * 60 * 1000);
const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig();
const { fee: laconic2Fee } = getLaconic2Config();
const auctionTests = (numBidders = 3) => { const auctionTests = (numBidders = 3) => {
let registry: Registry; let registry: Registry;
@ -25,14 +24,14 @@ const auctionTests = (numBidders = 3) => {
const mnenonic = Account.generateMnemonic(); const mnenonic = Account.generateMnemonic();
const account = await Account.generateFromMnemonic(mnenonic); const account = await Account.generateFromMnemonic(mnenonic);
await account.init(); await account.init();
await registry.sendCoins({ denom: DENOM, amount: '20000000', destinationAddress: account.address }, privateKey, laconic2Fee); await registry.sendCoins({ denom: DENOM, amount: '20000000', destinationAddress: account.address }, privateKey, fee);
accounts.push({ address: account.address, privateKey: account.privateKey.toString('hex') }); accounts.push({ address: account.address, privateKey: account.privateKey.toString('hex') });
} }
}); });
test('Reserve authority.', async () => { test('Reserve authority.', async () => {
authorityName = `laconic-${Date.now()}`; authorityName = `laconic-${Date.now()}`;
await registry.reserveAuthority({ name: authorityName }, accounts[0].privateKey, laconic2Fee); await registry.reserveAuthority({ name: authorityName }, accounts[0].privateKey, fee);
}); });
test('Authority should be under auction.', async () => { test('Authority should be under auction.', async () => {
@ -50,7 +49,7 @@ const auctionTests = (numBidders = 3) => {
test('Commit bids.', async () => { test('Commit bids.', async () => {
for (let i = 0; i < numBidders; i++) { for (let i = 0; i < numBidders; i++) {
accounts[i].bid = await createBid(chainId, auctionId, accounts[i].address, `${10000000 + (i * 500)}${DENOM}`); accounts[i].bid = await createBid(chainId, auctionId, accounts[i].address, `${10000000 + (i * 500)}${DENOM}`);
await registry.commitBid({ auctionId, commitHash: accounts[i].bid.commitHash }, accounts[i].privateKey, laconic2Fee); await registry.commitBid({ auctionId, commitHash: accounts[i].bid.commitHash }, accounts[i].privateKey, fee);
} }
}); });
@ -74,7 +73,7 @@ const auctionTests = (numBidders = 3) => {
expect(auction.status).toEqual('reveal'); expect(auction.status).toEqual('reveal');
for (let i = 0; i < numBidders; i++) { for (let i = 0; i < numBidders; i++) {
await registry.revealBid({ auctionId, reveal: accounts[i].bid.revealString }, accounts[i].privateKey, laconic2Fee); await registry.revealBid({ auctionId, reveal: accounts[i].bid.revealString }, accounts[i].privateKey, fee);
} }
}); });

View File

@ -1,14 +1,13 @@
import path from 'path'; import path from 'path';
import { Registry } from './index'; import { Registry } from './index';
import { ensureUpdatedConfig, getConfig, getLaconic2Config } from './testing/helper'; import { ensureUpdatedConfig, getConfig } from './testing/helper';
import { DENOM } from './constants'; import { DENOM } from './constants';
const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
const BOND_AMOUNT = '10000'; const BOND_AMOUNT = '10000';
const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig();
const { fee: laconic2Fee } = getLaconic2Config();
jest.setTimeout(90 * 1000); jest.setTimeout(90 * 1000);
@ -17,7 +16,7 @@ const bondTests = () => {
const publishNewWatcherVersion = async (bondId: string) => { const publishNewWatcherVersion = async (bondId: string) => {
let watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); let watcher = await ensureUpdatedConfig(WATCHER_YML_PATH);
await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, laconic2Fee); await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, fee);
return watcher; return watcher;
}; };
@ -28,7 +27,7 @@ const bondTests = () => {
test('Create bond.', async () => { test('Create bond.', async () => {
let bondId = await registry.getNextBondId(privateKey); let bondId = await registry.getNextBondId(privateKey);
expect(bondId).toBeDefined(); expect(bondId).toBeDefined();
await registry.createBond({ denom: DENOM, amount: BOND_AMOUNT }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: BOND_AMOUNT }, privateKey, fee);
}); });
describe('With bond created', () => { describe('With bond created', () => {
@ -37,7 +36,7 @@ const bondTests = () => {
beforeAll(async () => { beforeAll(async () => {
let bondId1 = await registry.getNextBondId(privateKey); let bondId1 = await registry.getNextBondId(privateKey);
expect(bondId1).toBeDefined(); expect(bondId1).toBeDefined();
await registry.createBond({ denom: DENOM, amount: BOND_AMOUNT }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: BOND_AMOUNT }, privateKey, fee);
[bond1] = await registry.getBondsByIds([bondId1]); [bond1] = await registry.getBondsByIds([bondId1]);
expect(bond1).toBeDefined(); expect(bond1).toBeDefined();
@ -69,7 +68,7 @@ const bondTests = () => {
test('Refill bond.', async () => { test('Refill bond.', async () => {
const refillAmount = '500'; const refillAmount = '500';
const total = (parseInt(BOND_AMOUNT) + parseInt(refillAmount)).toString(); const total = (parseInt(BOND_AMOUNT) + parseInt(refillAmount)).toString();
await registry.refillBond({ id: bond1.id, denom: DENOM, amount: refillAmount }, privateKey, laconic2Fee); await registry.refillBond({ id: bond1.id, denom: DENOM, amount: refillAmount }, privateKey, fee);
const [bond] = await registry.getBondsByIds([bond1.id]); const [bond] = await registry.getBondsByIds([bond1.id]);
expect(bond).toBeDefined(); expect(bond).toBeDefined();
expect(bond.id).toBe(bond1.id); expect(bond.id).toBe(bond1.id);
@ -78,7 +77,7 @@ const bondTests = () => {
}); });
test('Withdraw bond.', async () => { test('Withdraw bond.', async () => {
await registry.withdrawBond({ id: bond1.id, denom: DENOM, amount: '500' }, privateKey, laconic2Fee); await registry.withdrawBond({ id: bond1.id, denom: DENOM, amount: '500' }, privateKey, fee);
const [bond] = await registry.getBondsByIds([bond1.id]); const [bond] = await registry.getBondsByIds([bond1.id]);
expect(bond).toBeDefined(); expect(bond).toBeDefined();
expect(bond.id).toBe(bond1.id); expect(bond.id).toBe(bond1.id);
@ -87,7 +86,7 @@ const bondTests = () => {
}); });
test('Cancel bond.', async () => { test('Cancel bond.', async () => {
await registry.cancelBond({ id: bond1.id }, privateKey, laconic2Fee); await registry.cancelBond({ id: bond1.id }, privateKey, fee);
const [bond] = await registry.getBondsByIds([bond1.id]); const [bond] = await registry.getBondsByIds([bond1.id]);
expect(bond.id).toBe(''); expect(bond.id).toBe('');
expect(bond.owner).toBe(''); expect(bond.owner).toBe('');
@ -95,13 +94,12 @@ const bondTests = () => {
}); });
}); });
// TODO: Implement set record test('Associate/Dissociate bond.', async () => {
xtest('Associate/Dissociate bond.', async () => {
let bondId1: string; let bondId1: string;
bondId1 = await registry.getNextBondId(privateKey); bondId1 = await registry.getNextBondId(privateKey);
expect(bondId1).toBeDefined(); expect(bondId1).toBeDefined();
await registry.createBond({ denom: DENOM, amount: BOND_AMOUNT }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, fee);
// Create a new record. // Create a new record.
let watcher = await publishNewWatcherVersion(bondId1); let watcher = await publishNewWatcherVersion(bondId1);
@ -120,14 +118,13 @@ const bondTests = () => {
expect(record1.bondId).toBe(bondId1); expect(record1.bondId).toBe(bondId1);
}); });
// TODO: Implement set record test('Reassociate/Dissociate records.', async () => {
xtest('Reassociate/Dissociate records.', async () => {
let bondId1: string; let bondId1: string;
let bondId2: string; let bondId2: string;
bondId1 = await registry.getNextBondId(privateKey); bondId1 = await registry.getNextBondId(privateKey);
expect(bondId1).toBeDefined(); expect(bondId1).toBeDefined();
await registry.createBond({ denom: DENOM, amount: BOND_AMOUNT }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, fee);
// Create a new record version. // Create a new record version.
let watcher = await publishNewWatcherVersion(bondId1); let watcher = await publishNewWatcherVersion(bondId1);
@ -144,7 +141,7 @@ const bondTests = () => {
// Create another bond. // Create another bond.
bondId2 = await registry.getNextBondId(privateKey); bondId2 = await registry.getNextBondId(privateKey);
expect(bondId2).toBeDefined(); expect(bondId2).toBeDefined();
await registry.createBond({ denom: DENOM, amount: BOND_AMOUNT }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, fee);
const [bond] = await registry.getBondsByIds([bondId2]); const [bond] = await registry.getBondsByIds([bondId2]);
expect(bond.id).toBe(bondId2); expect(bond.id).toBe(bondId2);

View File

@ -1,10 +1,9 @@
import { Account } from './account'; import { Account } from './account';
import { DENOM } from './constants'; import { DENOM } from './constants';
import { Registry } from './index'; import { Registry } from './index';
import { getConfig, getLaconic2Config } from './testing/helper'; import { getConfig } from './testing/helper';
const { chainId, restEndpoint, gqlEndpoint, privateKey } = getConfig(); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig();
const { fee } = getLaconic2Config();
jest.setTimeout(90 * 1000); jest.setTimeout(90 * 1000);

View File

@ -319,57 +319,71 @@ export class Registry {
/** /**
* Associate record with bond. * Associate record with bond.
*/ */
async associateBond (params: MessageMsgAssociateBond, privateKey: string, fee: Fee) { async associateBond ({ bondId, recordId }: MessageMsgAssociateBond, privateKey: string, fee: StdFee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex')); 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 = createTxMsgAssociateBond(this._chain, sender, fee, '', params); const response: DeliverTxResponse = await laconicClient.associateBond(
result = await this._submitTx(msg, privateKey, sender); account.address,
recordId,
bondId,
fee
);
return parseTxResponse(result); return laconicClient.registry.decode(response.msgResponses[0]);
} }
/** /**
* Dissociate record from bond. * Dissociate record from bond.
*/ */
async dissociateBond (params: MessageMsgDissociateBond, privateKey: string, fee: Fee) { async dissociateBond ({ recordId }: MessageMsgDissociateBond, privateKey: string, fee: StdFee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex')); 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 = createTxMsgDissociateBond(this._chain, sender, fee, '', params); const response: DeliverTxResponse = await laconicClient.dissociateBond(
result = await this._submitTx(msg, privateKey, sender); account.address,
recordId,
fee
);
return parseTxResponse(result); return laconicClient.registry.decode(response.msgResponses[0]);
} }
/** /**
* Dissociate all records from bond. * Dissociate all records from bond.
*/ */
async dissociateRecords (params: MessageMsgDissociateRecords, privateKey: string, fee: Fee) { async dissociateRecords ({ bondId }: MessageMsgDissociateRecords, privateKey: string, fee: StdFee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex')); 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 = createTxMsgDissociateRecords(this._chain, sender, fee, '', params); const response: DeliverTxResponse = await laconicClient.dissociateRecords(
result = await this._submitTx(msg, privateKey, sender); account.address,
bondId,
fee
);
return parseTxResponse(result); return laconicClient.registry.decode(response.msgResponses[0]);
} }
/** /**
* Reassociate records (switch bond). * Reassociate records (switch bond).
*/ */
async reassociateRecords (params: MessageMsgReAssociateRecords, privateKey: string, fee: Fee) { async reassociateRecords ({ newBondId, oldBondId }: MessageMsgReAssociateRecords, privateKey: string, fee: StdFee) {
let result;
const account = new Account(Buffer.from(privateKey, 'hex')); 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 = createTxMsgReAssociateRecords(this._chain, sender, fee, '', params); const response: DeliverTxResponse = await laconicClient.reassociateRecords(
result = await this._submitTx(msg, privateKey, sender); account.address,
oldBondId,
newBondId,
fee
);
return parseTxResponse(result); return laconicClient.registry.decode(response.msgResponses[0]);
} }
/** /**

View File

@ -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 { MsgCancelBondEncodeObject, MsgCreateBondEncodeObject, MsgRefillBondEncodeObject, MsgWithdrawBondEncodeObject, bondTypes, typeUrlMsgCancelBond, typeUrlMsgCreateBond, typeUrlMsgRefillBond, typeUrlMsgWithdrawBond } from './types/cerc/bond/message';
import { Coin } from './proto2/cosmos/base/v1beta1/coin'; import { Coin } from './proto2/cosmos/base/v1beta1/coin';
import { MsgDeleteNameAuthorityEncodeObject, MsgReserveAuthorityEncodeObject, MsgSetAuthorityBondEncodeObject, MsgSetNameEncodeObject, MsgSetRecordEncodeObject, registryTypes, typeUrlMsgDeleteNameAuthority, typeUrlMsgReserveAuthority, typeUrlMsgSetAuthorityBond, typeUrlMsgSetName, typeUrlMsgSetRecord } from './types/cerc/registry/message'; import { MsgAssociateBondEncodeObject, MsgDeleteNameAuthorityEncodeObject, MsgDissociateBondEncodeObject, MsgDissociateRecordsEncodeObject, MsgReassociateRecordsEncodeObject, MsgReserveAuthorityEncodeObject, MsgSetAuthorityBondEncodeObject, MsgSetNameEncodeObject, MsgSetRecordEncodeObject, registryTypes, typeUrlMsgAssociateBond, typeUrlMsgDeleteNameAuthority, typeUrlMsgDissociateBond, typeUrlMsgDissociateRecords, typeUrlMsgReassociateRecords, typeUrlMsgReserveAuthority, typeUrlMsgSetAuthorityBond, typeUrlMsgSetName, typeUrlMsgSetRecord } from './types/cerc/registry/message';
import { MsgCommitBidEncodeObject, MsgRevealBidEncodeObject, auctionTypes, typeUrlMsgCommitBid, typeUrlMsgRevealBid } from './types/cerc/auction/message'; import { MsgCommitBidEncodeObject, MsgRevealBidEncodeObject, auctionTypes, typeUrlMsgCommitBid, typeUrlMsgRevealBid } from './types/cerc/auction/message';
import { Payload } from './proto2/cerc/registry/v1/tx'; import { Payload } from './proto2/cerc/registry/v1/tx';
import { Record, Signature } from './proto2/cerc/registry/v1/registry'; import { Record, Signature } from './proto2/cerc/registry/v1/registry';
@ -132,6 +132,78 @@ export class LaconicClient extends SigningStargateClient {
return this.signAndBroadcast(signer, [createMsg], fee, memo); return this.signAndBroadcast(signer, [createMsg], fee, memo);
} }
public async associateBond (
signer: string,
recordId: string,
bondId: string,
fee: StdFee | 'auto' | number,
memo = ''
): Promise<DeliverTxResponse> {
const createMsg: MsgAssociateBondEncodeObject = {
typeUrl: typeUrlMsgAssociateBond,
value: {
recordId,
bondId,
signer
}
};
return this.signAndBroadcast(signer, [createMsg], fee, memo);
}
public async dissociateBond (
signer: string,
recordId: string,
fee: StdFee | 'auto' | number,
memo = ''
): Promise<DeliverTxResponse> {
const createMsg: MsgDissociateBondEncodeObject = {
typeUrl: typeUrlMsgDissociateBond,
value: {
recordId,
signer
}
};
return this.signAndBroadcast(signer, [createMsg], fee, memo);
}
public async dissociateRecords (
signer: string,
bondId: string,
fee: StdFee | 'auto' | number,
memo = ''
): Promise<DeliverTxResponse> {
const createMsg: MsgDissociateRecordsEncodeObject = {
typeUrl: typeUrlMsgDissociateRecords,
value: {
signer,
bondId
}
};
return this.signAndBroadcast(signer, [createMsg], fee, memo);
}
public async reassociateRecords (
signer: string,
oldBondId: string,
newBondId: string,
fee: StdFee | 'auto' | number,
memo = ''
): Promise<DeliverTxResponse> {
const createMsg: MsgReassociateRecordsEncodeObject = {
typeUrl: typeUrlMsgReassociateRecords,
value: {
signer,
oldBondId,
newBondId
}
};
return this.signAndBroadcast(signer, [createMsg], fee, memo);
}
public async reserveAuthority ( public async reserveAuthority (
signer: string, signer: string,
name: string, name: string,

View File

@ -1,7 +1,7 @@
import path from 'path'; import path from 'path';
import { Registry } from './index'; import { Registry } from './index';
import { ensureUpdatedConfig, getConfig, getLaconic2Config } from './testing/helper'; import { ensureUpdatedConfig, getConfig } from './testing/helper';
import { DENOM } from './constants'; import { DENOM } from './constants';
const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
@ -9,7 +9,6 @@ const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
jest.setTimeout(120 * 1000); jest.setTimeout(120 * 1000);
const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig();
const { fee: laconic2Fee } = getLaconic2Config();
const nameserviceExpiryTests = () => { const nameserviceExpiryTests = () => {
let registry: Registry; let registry: Registry;
@ -26,7 +25,7 @@ const nameserviceExpiryTests = () => {
// Create bond. // Create bond.
bondId = await registry.getNextBondId(privateKey); bondId = await registry.getNextBondId(privateKey);
await registry.createBond({ denom: DENOM, amount: '3000000' }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '3000000' }, privateKey, fee);
}); });
test('Set record and check bond balance', async () => { test('Set record and check bond balance', async () => {
@ -39,7 +38,7 @@ const nameserviceExpiryTests = () => {
record: watcher.record record: watcher.record
}, },
privateKey, privateKey,
laconic2Fee fee
); );
console.log('SetRecordResult: ' + result.id); console.log('SetRecordResult: ' + result.id);
const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }, true); const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }, true);
@ -53,8 +52,8 @@ const nameserviceExpiryTests = () => {
test('Reserve authority and set bond', async () => { test('Reserve authority and set bond', async () => {
authorityName = `laconic-${Date.now()}`; authorityName = `laconic-${Date.now()}`;
await registry.reserveAuthority({ name: authorityName }, privateKey, laconic2Fee); await registry.reserveAuthority({ name: authorityName }, privateKey, fee);
await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, laconic2Fee); await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, fee);
const [authority] = await registry.lookupAuthorities([authorityName]); const [authority] = await registry.lookupAuthorities([authorityName]);
expect(authority.status).toBe('active'); expect(authority.status).toBe('active');
authorityExpiryTime = new Date(authority.expiryTime); authorityExpiryTime = new Date(authority.expiryTime);

View File

@ -3,11 +3,10 @@ import path from 'path';
import { Account } from './account'; import { Account } from './account';
import { Registry } from './index'; import { Registry } from './index';
import { ensureUpdatedConfig, getConfig, getLaconic2Config } from './testing/helper'; import { ensureUpdatedConfig, getConfig } from './testing/helper';
import { DENOM } from './constants'; import { DENOM } from './constants';
const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
const { fee: laconic2Fee } = getLaconic2Config();
jest.setTimeout(5 * 60 * 1000); jest.setTimeout(5 * 60 * 1000);
@ -25,7 +24,7 @@ const namingTests = () => {
// Create bond. // Create bond.
bondId = await registry.getNextBondId(privateKey); bondId = await registry.getNextBondId(privateKey);
await registry.createBond({ denom: DENOM, amount: '2000000' }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '2000000' }, privateKey, fee);
// Create watcher. // Create watcher.
watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); watcher = await ensureUpdatedConfig(WATCHER_YML_PATH);
@ -36,7 +35,7 @@ const namingTests = () => {
record: watcher.record record: watcher.record
}, },
privateKey, privateKey,
laconic2Fee fee
); );
watcherId = result.id; watcherId = result.id;
@ -45,7 +44,7 @@ const namingTests = () => {
describe('Authority tests', () => { describe('Authority tests', () => {
test('Reserve authority.', async () => { test('Reserve authority.', async () => {
const authorityName = `laconic-${Date.now()}`; const authorityName = `laconic-${Date.now()}`;
await registry.reserveAuthority({ name: authorityName }, privateKey, laconic2Fee); await registry.reserveAuthority({ name: authorityName }, privateKey, fee);
}); });
describe('With authority reserved', () => { describe('With authority reserved', () => {
@ -56,7 +55,7 @@ const namingTests = () => {
authorityName = `laconic-${Date.now()}`; authorityName = `laconic-${Date.now()}`;
lrn = `lrn://${authorityName}/app/test`; lrn = `lrn://${authorityName}/app/test`;
await registry.reserveAuthority({ name: authorityName }, privateKey, laconic2Fee); await registry.reserveAuthority({ name: authorityName }, privateKey, fee);
}); });
test('Lookup authority.', async () => { test('Lookup authority.', async () => {
@ -78,13 +77,13 @@ const namingTests = () => {
// TODO: Implement parse error response // TODO: Implement parse error response
xtest('Reserve already reserved authority', async () => { xtest('Reserve already reserved authority', async () => {
await expect(registry.reserveAuthority({ name: authorityName }, privateKey, laconic2Fee)) await expect(registry.reserveAuthority({ name: authorityName }, privateKey, fee))
.rejects.toThrow('Name already reserved.'); .rejects.toThrow('Name already reserved.');
}); });
test('Reserve sub-authority.', async () => { test('Reserve sub-authority.', async () => {
const subAuthority = `echo.${authorityName}`; const subAuthority = `echo.${authorityName}`;
await registry.reserveAuthority({ name: subAuthority }, privateKey, laconic2Fee); await registry.reserveAuthority({ name: subAuthority }, privateKey, fee);
const [record] = await registry.lookupAuthorities([subAuthority]); const [record] = await registry.lookupAuthorities([subAuthority]);
expect(record).toBeDefined(); expect(record).toBeDefined();
@ -98,15 +97,15 @@ const namingTests = () => {
const mnenonic1 = Account.generateMnemonic(); const mnenonic1 = Account.generateMnemonic();
const otherAccount1 = await Account.generateFromMnemonic(mnenonic1); const otherAccount1 = await Account.generateFromMnemonic(mnenonic1);
await otherAccount1.init(); await otherAccount1.init();
await registry.sendCoins({ denom: DENOM, amount: '10000', destinationAddress: otherAccount1.address }, privateKey, laconic2Fee); await registry.sendCoins({ denom: DENOM, amount: '10000', destinationAddress: otherAccount1.address }, privateKey, fee);
const mnenonic2 = Account.generateMnemonic(); const mnenonic2 = Account.generateMnemonic();
const otherAccount2 = await Account.generateFromMnemonic(mnenonic2); const otherAccount2 = await Account.generateFromMnemonic(mnenonic2);
await otherAccount2.init(); await otherAccount2.init();
await registry.sendCoins({ denom: DENOM, amount: '10000', destinationAddress: otherAccount2.address }, otherAccount1.getPrivateKey(), laconic2Fee); await registry.sendCoins({ denom: DENOM, amount: '10000', destinationAddress: otherAccount2.address }, otherAccount1.getPrivateKey(), fee);
const subAuthority = `halo.${authorityName}`; const subAuthority = `halo.${authorityName}`;
await registry.reserveAuthority({ name: subAuthority, owner: otherAccount1.address }, privateKey, laconic2Fee); await registry.reserveAuthority({ name: subAuthority, owner: otherAccount1.address }, privateKey, fee);
const [record] = await registry.lookupAuthorities([subAuthority]); const [record] = await registry.lookupAuthorities([subAuthority]);
expect(record).toBeDefined(); expect(record).toBeDefined();
@ -119,12 +118,12 @@ const namingTests = () => {
// TODO: Parse error response from set name // TODO: Parse error response from set name
xtest('Set name for unbonded authority', async () => { xtest('Set name for unbonded authority', async () => {
assert(watcherId); assert(watcherId);
await expect(registry.setName({ lrn, cid: watcherId }, privateKey, laconic2Fee)) await expect(registry.setName({ lrn, cid: watcherId }, privateKey, fee))
.rejects.toThrow('Authority bond not found.'); .rejects.toThrow('Authority bond not found.');
}); });
test('Set authority bond', async () => { test('Set authority bond', async () => {
await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, laconic2Fee); await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, fee);
}); });
}); });
}); });
@ -137,14 +136,14 @@ const namingTests = () => {
beforeAll(async () => { beforeAll(async () => {
authorityName = `laconic-${Date.now()}`; authorityName = `laconic-${Date.now()}`;
await registry.reserveAuthority({ name: authorityName }, privateKey, laconic2Fee); await registry.reserveAuthority({ name: authorityName }, privateKey, fee);
await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, laconic2Fee); await registry.setAuthorityBond({ name: authorityName, bondId }, privateKey, fee);
// Create another account. // Create another account.
const mnenonic = Account.generateMnemonic(); const mnenonic = Account.generateMnemonic();
otherAccount = await Account.generateFromMnemonic(mnenonic); otherAccount = await Account.generateFromMnemonic(mnenonic);
await otherAccount.init(); await otherAccount.init();
await registry.sendCoins({ denom: DENOM, amount: '1000000000', destinationAddress: otherAccount.address }, privateKey, laconic2Fee); await registry.sendCoins({ denom: DENOM, amount: '1000000000', destinationAddress: otherAccount.address }, privateKey, fee);
otherAuthorityName = `other-${Date.now()}`; otherAuthorityName = `other-${Date.now()}`;
otherPrivateKey = otherAccount.privateKey.toString('hex'); otherPrivateKey = otherAccount.privateKey.toString('hex');
@ -153,14 +152,14 @@ const namingTests = () => {
test('Set name', async () => { test('Set name', async () => {
const lrn = `lrn://${authorityName}/app/test1`; const lrn = `lrn://${authorityName}/app/test1`;
await registry.setName({ lrn, cid: watcherId }, privateKey, laconic2Fee); await registry.setName({ lrn, cid: watcherId }, privateKey, fee);
// Query records should return it (some lrn points to it). // Query records should return it (some lrn points to it).
const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version }); const [record] = await registry.queryRecords({ type: 'WebsiteRegistrationRecord', version: watcher.record.version });
expect(record).toBeDefined(); expect(record).toBeDefined();
expect(record.names).toHaveLength(1); expect(record.names).toHaveLength(1);
await registry.deleteName({ lrn }, privateKey, laconic2Fee); await registry.deleteName({ lrn }, privateKey, fee);
}); });
describe('With name set', () => { describe('With name set', () => {
@ -168,11 +167,11 @@ const namingTests = () => {
beforeAll(async () => { beforeAll(async () => {
lrn = `lrn://${authorityName}/app/test2`; lrn = `lrn://${authorityName}/app/test2`;
await registry.setName({ lrn, cid: watcherId }, privateKey, laconic2Fee); await registry.setName({ lrn, cid: watcherId }, privateKey, fee);
}); });
afterAll(async () => { afterAll(async () => {
await registry.deleteName({ lrn }, privateKey, laconic2Fee); await registry.deleteName({ lrn }, privateKey, fee);
}); });
test('Lookup name', async () => { test('Lookup name', async () => {
@ -206,11 +205,11 @@ const namingTests = () => {
record: updatedWatcher.record record: updatedWatcher.record
}, },
privateKey, privateKey,
laconic2Fee fee
); );
const updatedWatcherId = result.id; const updatedWatcherId = result.id;
await registry.setName({ lrn, cid: updatedWatcherId }, privateKey, laconic2Fee); await registry.setName({ lrn, cid: updatedWatcherId }, privateKey, fee);
const records = await registry.lookupNames([lrn], true); const records = await registry.lookupNames([lrn], true);
expect(records).toHaveLength(1); expect(records).toHaveLength(1);
@ -231,7 +230,7 @@ const namingTests = () => {
}); });
test('Delete name', async () => { test('Delete name', async () => {
await registry.deleteName({ lrn }, privateKey, laconic2Fee); await registry.deleteName({ lrn }, privateKey, fee);
let records = await registry.lookupNames([lrn], true); let records = await registry.lookupNames([lrn], true);
expect(records).toBeDefined(); expect(records).toBeDefined();
@ -255,8 +254,8 @@ const namingTests = () => {
}); });
test('Delete already deleted name', async () => { test('Delete already deleted name', async () => {
await registry.deleteName({ lrn }, privateKey, laconic2Fee); await registry.deleteName({ lrn }, privateKey, fee);
await registry.deleteName({ lrn }, privateKey, laconic2Fee); await registry.deleteName({ lrn }, privateKey, fee);
const records = await registry.lookupNames([lrn], true); const records = await registry.lookupNames([lrn], true);
expect(records).toBeDefined(); expect(records).toBeDefined();
@ -272,30 +271,30 @@ const namingTests = () => {
// TODO: Parse error response form set name // TODO: Parse error response form set name
xtest('Set name without reserving authority', async () => { xtest('Set name without reserving authority', async () => {
await expect(registry.setName({ lrn: 'lrn://not-reserved/app/test', cid: watcherId }, privateKey, laconic2Fee)) await expect(registry.setName({ lrn: 'lrn://not-reserved/app/test', cid: watcherId }, privateKey, fee))
.rejects.toThrow('Name authority not found.'); .rejects.toThrow('Name authority not found.');
}); });
// TODO: Parse error response form set name // TODO: Parse error response form set name
xtest('Set name for non-owned authority', async () => { xtest('Set name for non-owned authority', async () => {
await registry.sendCoins({ denom: DENOM, amount: '1000000000', destinationAddress: otherAccount.address }, privateKey, laconic2Fee); await registry.sendCoins({ denom: DENOM, amount: '1000000000', destinationAddress: otherAccount.address }, privateKey, fee);
// Other account reserves an authority. // Other account reserves an authority.
await registry.reserveAuthority({ name: otherAuthorityName }, otherPrivateKey, laconic2Fee); await registry.reserveAuthority({ name: otherAuthorityName }, otherPrivateKey, fee);
// Try setting name under other authority. // Try setting name under other authority.
await expect(registry.setName({ lrn: `lrn://${otherAuthorityName}/app/test`, cid: watcherId }, privateKey, laconic2Fee)).rejects.toThrow('Access denied.'); await expect(registry.setName({ lrn: `lrn://${otherAuthorityName}/app/test`, cid: watcherId }, privateKey, fee)).rejects.toThrow('Access denied.');
}); });
// TODO: Parse error response form set name // TODO: Parse error response form set name
xtest('Delete name for non-owned authority.', async () => { xtest('Delete name for non-owned authority.', async () => {
const otherBondId = await registry.getNextBondId(otherPrivateKey); const otherBondId = await registry.getNextBondId(otherPrivateKey);
await registry.createBond({ denom: DENOM, amount: '1000000' }, otherPrivateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '1000000' }, otherPrivateKey, fee);
await registry.setAuthorityBond({ name: otherAuthorityName, bondId: otherBondId }, otherPrivateKey, laconic2Fee); await registry.setAuthorityBond({ name: otherAuthorityName, bondId: otherBondId }, otherPrivateKey, fee);
await registry.setName({ lrn: `lrn://${otherAuthorityName}/app/test`, cid: watcherId }, otherPrivateKey, laconic2Fee); await registry.setName({ lrn: `lrn://${otherAuthorityName}/app/test`, cid: watcherId }, otherPrivateKey, fee);
// Try deleting name under other authority. // Try deleting name under other authority.
await expect(registry.deleteName({ lrn: `lrn://${otherAuthorityName}/app/test` }, privateKey, laconic2Fee)).rejects.toThrow('Access denied.'); await expect(registry.deleteName({ lrn: `lrn://${otherAuthorityName}/app/test` }, privateKey, fee)).rejects.toThrow('Access denied.');
}); });
// TODO: Check later for empty records // TODO: Check later for empty records

View File

@ -1,7 +1,7 @@
import path from 'path'; import path from 'path';
import { Registry } from './index'; import { Registry } from './index';
import { getConfig, ensureUpdatedConfig, getLaconic2Config } from './testing/helper'; import { getConfig, ensureUpdatedConfig } from './testing/helper';
import { DENOM } from './constants'; import { DENOM } from './constants';
const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml'); const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
@ -9,7 +9,6 @@ const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
jest.setTimeout(40 * 1000); jest.setTimeout(40 * 1000);
const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig();
const { fee: laconic2Fee } = getLaconic2Config();
describe('Querying', () => { describe('Querying', () => {
let watcher: any; let watcher: any;
@ -20,11 +19,11 @@ describe('Querying', () => {
registry = new Registry(gqlEndpoint, restEndpoint, chainId); registry = new Registry(gqlEndpoint, restEndpoint, chainId);
bondId = await registry.getNextBondId(privateKey); bondId = await registry.getNextBondId(privateKey);
await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, fee);
const publishNewWatcherVersion = async () => { const publishNewWatcherVersion = async () => {
watcher = await ensureUpdatedConfig(WATCHER_YML_PATH); watcher = await ensureUpdatedConfig(WATCHER_YML_PATH);
await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, laconic2Fee); await registry.setRecord({ privateKey, record: watcher.record, bondId }, privateKey, fee);
return watcher.record.version; return watcher.record.version;
}; };

View File

@ -28,17 +28,6 @@ export const getConfig = () => {
privateKey: process.env.PRIVATE_KEY, privateKey: process.env.PRIVATE_KEY,
restEndpoint: process.env.LACONICD_REST_ENDPOINT || 'http://localhost:1317', restEndpoint: process.env.LACONICD_REST_ENDPOINT || 'http://localhost:1317',
gqlEndpoint: process.env.LACONICD_GQL_ENDPOINT || 'http://localhost:9473/api', gqlEndpoint: process.env.LACONICD_GQL_ENDPOINT || 'http://localhost:9473/api',
fee: {
amount: '40',
denom: 'aphoton',
gas: '400000'
}
};
};
// TODO: Merge both config
export const getLaconic2Config = () => {
return {
fee: { fee: {
amount: [{ denom: 'photon', amount: '40' }], amount: [{ denom: 'photon', amount: '40' }],
gas: '400000' gas: '400000'

View File

@ -1,6 +1,6 @@
import { EncodeObject, GeneratedType } from '@cosmjs/proto-signing'; import { EncodeObject, GeneratedType } from '@cosmjs/proto-signing';
import { MsgReserveAuthority, MsgReserveAuthorityResponse, MsgSetAuthorityBond, MsgSetAuthorityBondResponse, MsgSetRecord, MsgSetRecordResponse, MsgSetName, MsgSetNameResponse, MsgDeleteNameAuthority, MsgDeleteNameAuthorityResponse } from '../../../proto2/cerc/registry/v1/tx'; import { MsgReserveAuthority, MsgReserveAuthorityResponse, MsgSetAuthorityBond, MsgSetAuthorityBondResponse, MsgSetRecord, MsgSetRecordResponse, MsgSetName, MsgSetNameResponse, MsgDeleteNameAuthority, MsgDeleteNameAuthorityResponse, MsgAssociateBond, MsgAssociateBondResponse, MsgDissociateBond, MsgDissociateBondResponse, MsgDissociateRecords, MsgReassociateRecords, MsgDissociateRecordsResponse, MsgReassociateRecordsResponse } from '../../../proto2/cerc/registry/v1/tx';
export const typeUrlMsgReserveAuthority = '/cerc.registry.v1.MsgReserveAuthority'; export const typeUrlMsgReserveAuthority = '/cerc.registry.v1.MsgReserveAuthority';
export const typeUrlMsgSetRecord = '/cerc.registry.v1.MsgSetRecord'; export const typeUrlMsgSetRecord = '/cerc.registry.v1.MsgSetRecord';
@ -12,6 +12,14 @@ export const typeUrlMsgSetName = '/cerc.registry.v1.MsgSetName';
export const typeUrlMsgSetNameResponse = '/cerc.registry.v1.MsgSetNameResponse'; export const typeUrlMsgSetNameResponse = '/cerc.registry.v1.MsgSetNameResponse';
export const typeUrlMsgDeleteNameAuthority = '/cerc.registry.v1.MsgDeleteNameAuthority'; export const typeUrlMsgDeleteNameAuthority = '/cerc.registry.v1.MsgDeleteNameAuthority';
export const typeUrlMsgDeleteNameAuthorityResponse = '/cerc.registry.v1.MsgDeleteNameAuthorityResponse'; export const typeUrlMsgDeleteNameAuthorityResponse = '/cerc.registry.v1.MsgDeleteNameAuthorityResponse';
export const typeUrlMsgAssociateBond = '/cerc.registry.v1.MsgAssociateBond';
export const typeUrlMsgDissociateBond = '/cerc.registry.v1.MsgDissociateBond';
export const typeUrlMsgAssociateBondResponse = '/cerc.registry.v1.MsgAssociateBondResponse';
export const typeUrlMsgDissociateBondResponse = '/cerc.registry.v1.MsgDissociateBondResponse';
export const typeUrlMsgDissociateRecords = '/cerc.registry.v1.MsgDissociateRecords';
export const typeUrlMsgReassociateRecords = '/cerc.registry.v1.MsgReassociateRecords';
export const typeUrlMsgDissociateRecordsResponse = '/cerc.registry.v1.MsgDissociateRecordsResponse';
export const typeUrlMsgReassociateRecordsResponse = '/cerc.registry.v1.MsgReassociateRecordsResponse';
export const registryTypes: ReadonlyArray<[string, GeneratedType]> = [ export const registryTypes: ReadonlyArray<[string, GeneratedType]> = [
[typeUrlMsgReserveAuthority, MsgReserveAuthority], [typeUrlMsgReserveAuthority, MsgReserveAuthority],
@ -23,7 +31,15 @@ export const registryTypes: ReadonlyArray<[string, GeneratedType]> = [
[typeUrlMsgSetName, MsgSetName], [typeUrlMsgSetName, MsgSetName],
[typeUrlMsgSetNameResponse, MsgSetNameResponse], [typeUrlMsgSetNameResponse, MsgSetNameResponse],
[typeUrlMsgDeleteNameAuthority, MsgDeleteNameAuthority], [typeUrlMsgDeleteNameAuthority, MsgDeleteNameAuthority],
[typeUrlMsgDeleteNameAuthorityResponse, MsgDeleteNameAuthorityResponse] [typeUrlMsgDeleteNameAuthorityResponse, MsgDeleteNameAuthorityResponse],
[typeUrlMsgAssociateBond, MsgAssociateBond],
[typeUrlMsgAssociateBondResponse, MsgAssociateBondResponse],
[typeUrlMsgDissociateBond, MsgDissociateBond],
[typeUrlMsgDissociateBondResponse, MsgDissociateBondResponse],
[typeUrlMsgDissociateRecords, MsgDissociateRecords],
[typeUrlMsgReassociateRecords, MsgReassociateRecords],
[typeUrlMsgDissociateRecordsResponse, MsgDissociateRecordsResponse],
[typeUrlMsgReassociateRecordsResponse, MsgReassociateRecordsResponse]
]; ];
export interface MsgReserveAuthorityEncodeObject extends EncodeObject { export interface MsgReserveAuthorityEncodeObject extends EncodeObject {
@ -50,3 +66,23 @@ export interface MsgDeleteNameAuthorityEncodeObject extends EncodeObject {
readonly typeUrl: '/cerc.registry.v1.MsgDeleteNameAuthority'; readonly typeUrl: '/cerc.registry.v1.MsgDeleteNameAuthority';
readonly value: Partial<MsgDeleteNameAuthority>; readonly value: Partial<MsgDeleteNameAuthority>;
} }
export interface MsgAssociateBondEncodeObject extends EncodeObject {
readonly typeUrl: '/cerc.registry.v1.MsgAssociateBond';
readonly value: Partial<MsgAssociateBond>;
}
export interface MsgDissociateBondEncodeObject extends EncodeObject {
readonly typeUrl: '/cerc.registry.v1.MsgDissociateBond';
readonly value: Partial<MsgDissociateBond>;
}
export interface MsgDissociateRecordsEncodeObject extends EncodeObject {
readonly typeUrl: '/cerc.registry.v1.MsgDissociateRecords';
readonly value: Partial<MsgDissociateRecords>;
}
export interface MsgReassociateRecordsEncodeObject extends EncodeObject {
readonly typeUrl: '/cerc.registry.v1.MsgReassociateRecords';
readonly value: Partial<MsgReassociateRecords>;
}

View File

@ -1,7 +1,7 @@
import path from 'path'; import path from 'path';
import { Registry } from './index'; import { Registry } from './index';
import { getBaseConfig, getConfig, getLaconic2Config } from './testing/helper'; import { getBaseConfig, getConfig } from './testing/helper';
import { Util } from './util'; import { Util } from './util';
import { DENOM } from './constants'; import { DENOM } from './constants';
@ -10,7 +10,6 @@ const WATCHER_YML_PATH = path.join(__dirname, './testing/data/watcher.yml');
jest.setTimeout(90 * 1000); jest.setTimeout(90 * 1000);
const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); const { chainId, restEndpoint, gqlEndpoint, privateKey, fee } = getConfig();
const { fee: laconic2Fee } = getLaconic2Config();
const utilTests = () => { const utilTests = () => {
let registry: Registry; let registry: Registry;
@ -24,7 +23,7 @@ const utilTests = () => {
// Create bond. // Create bond.
bondId = await registry.getNextBondId(privateKey); bondId = await registry.getNextBondId(privateKey);
await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, laconic2Fee); await registry.createBond({ denom: DENOM, amount: '1000000000' }, privateKey, fee);
// Create watcher. // Create watcher.
watcher = await getBaseConfig(WATCHER_YML_PATH); watcher = await getBaseConfig(WATCHER_YML_PATH);
@ -35,7 +34,7 @@ const utilTests = () => {
record: watcher.record record: watcher.record
}, },
privateKey, privateKey,
laconic2Fee fee
); );
watcherId = result.id; watcherId = result.id;