forked from cerc-io/laconic-sdk
Add tests for bond refill, withdraw and cancel
This commit is contained in:
parent
7fe5bcda83
commit
df5619932d
219
src/bond.ts
219
src/bond.ts
@ -37,6 +37,25 @@ const MSG_REFILL_BOND_TYPES = {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MSG_WITHDRAW_BOND_TYPES = {
|
||||||
|
MsgValue: [
|
||||||
|
{ name: 'id', type: 'string' },
|
||||||
|
{ name: 'signer', type: 'string' },
|
||||||
|
{ name: 'coins', type: 'TypeCoins[]' },
|
||||||
|
],
|
||||||
|
TypeCoins: [
|
||||||
|
{ name: 'denom', type: 'string' },
|
||||||
|
{ name: 'amount', type: 'string' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const MSG_CANCEL_BOND_TYPES = {
|
||||||
|
MsgValue: [
|
||||||
|
{ name: 'id', type: 'string' },
|
||||||
|
{ name: 'signer', type: 'string' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
export interface MessageMsgCreateBond {
|
export interface MessageMsgCreateBond {
|
||||||
amount: string
|
amount: string
|
||||||
denom: string
|
denom: string
|
||||||
@ -48,6 +67,16 @@ export interface MessageMsgRefillBond {
|
|||||||
denom: string
|
denom: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MessageMsgWithdrawBond {
|
||||||
|
id: string
|
||||||
|
amount: string
|
||||||
|
denom: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageMsgCancelBond {
|
||||||
|
id: string
|
||||||
|
}
|
||||||
|
|
||||||
export function createTxMsgCreateBond(
|
export function createTxMsgCreateBond(
|
||||||
chain: Chain,
|
chain: Chain,
|
||||||
sender: Sender,
|
sender: Sender,
|
||||||
@ -168,6 +197,124 @@ export function createTxMsgRefillBond(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createTxMsgWithdrawBond(
|
||||||
|
chain: Chain,
|
||||||
|
sender: Sender,
|
||||||
|
fee: Fee,
|
||||||
|
memo: string,
|
||||||
|
params: MessageMsgWithdrawBond,
|
||||||
|
) {
|
||||||
|
// EIP712
|
||||||
|
const feeObject = generateFee(
|
||||||
|
fee.amount,
|
||||||
|
fee.denom,
|
||||||
|
fee.gas,
|
||||||
|
sender.accountAddress,
|
||||||
|
)
|
||||||
|
const types = generateTypes(MSG_WITHDRAW_BOND_TYPES)
|
||||||
|
|
||||||
|
const msg = createMsgWithdrawBond(
|
||||||
|
params.id,
|
||||||
|
sender.accountAddress,
|
||||||
|
params.amount,
|
||||||
|
params.denom
|
||||||
|
)
|
||||||
|
|
||||||
|
const messages = generateMessage(
|
||||||
|
sender.accountNumber.toString(),
|
||||||
|
sender.sequence.toString(),
|
||||||
|
chain.cosmosChainId,
|
||||||
|
memo,
|
||||||
|
feeObject,
|
||||||
|
msg,
|
||||||
|
)
|
||||||
|
const eipToSign = createEIP712(types, chain.chainId, messages)
|
||||||
|
|
||||||
|
// Cosmos
|
||||||
|
const msgCosmos = protoCreateMsgWithdrawBond(
|
||||||
|
params.id,
|
||||||
|
sender.accountAddress,
|
||||||
|
params.amount,
|
||||||
|
params.denom
|
||||||
|
)
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTxMsgCancelBond(
|
||||||
|
chain: Chain,
|
||||||
|
sender: Sender,
|
||||||
|
fee: Fee,
|
||||||
|
memo: string,
|
||||||
|
params: MessageMsgCancelBond,
|
||||||
|
) {
|
||||||
|
// EIP712
|
||||||
|
const feeObject = generateFee(
|
||||||
|
fee.amount,
|
||||||
|
fee.denom,
|
||||||
|
fee.gas,
|
||||||
|
sender.accountAddress,
|
||||||
|
)
|
||||||
|
const types = generateTypes(MSG_CANCEL_BOND_TYPES)
|
||||||
|
|
||||||
|
const msg = createMsgCancelBond(
|
||||||
|
params.id,
|
||||||
|
sender.accountAddress
|
||||||
|
)
|
||||||
|
|
||||||
|
const messages = generateMessage(
|
||||||
|
sender.accountNumber.toString(),
|
||||||
|
sender.sequence.toString(),
|
||||||
|
chain.cosmosChainId,
|
||||||
|
memo,
|
||||||
|
feeObject,
|
||||||
|
msg,
|
||||||
|
)
|
||||||
|
const eipToSign = createEIP712(types, chain.chainId, messages)
|
||||||
|
|
||||||
|
// Cosmos
|
||||||
|
const msgCosmos = protoCreateMsgCancelBond(
|
||||||
|
params.id,
|
||||||
|
sender.accountAddress
|
||||||
|
)
|
||||||
|
|
||||||
|
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 createMsgCreateBond(
|
function createMsgCreateBond(
|
||||||
signer: string,
|
signer: string,
|
||||||
amount: string,
|
amount: string,
|
||||||
@ -251,3 +398,75 @@ const protoCreateMsgRefillBond = (
|
|||||||
path: 'vulcanize.bond.v1beta1.MsgRefillBond',
|
path: 'vulcanize.bond.v1beta1.MsgRefillBond',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createMsgWithdrawBond(
|
||||||
|
id: string,
|
||||||
|
signer: string,
|
||||||
|
amount: string,
|
||||||
|
denom: string,
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: 'bond/MsgWithdrawBond',
|
||||||
|
value: {
|
||||||
|
id,
|
||||||
|
coins: [
|
||||||
|
{
|
||||||
|
amount,
|
||||||
|
denom,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
signer
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const protoCreateMsgWithdrawBond = (
|
||||||
|
id: string,
|
||||||
|
signer: string,
|
||||||
|
amount: string,
|
||||||
|
denom: string,
|
||||||
|
) => {
|
||||||
|
const value = new coin.cosmos.base.v1beta1.Coin({
|
||||||
|
denom,
|
||||||
|
amount,
|
||||||
|
})
|
||||||
|
|
||||||
|
const withdrawBondMessage = new bondTx.vulcanize.bond.v1beta1.MsgWithdrawBond({
|
||||||
|
id,
|
||||||
|
signer,
|
||||||
|
coins: [value]
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: withdrawBondMessage,
|
||||||
|
path: 'vulcanize.bond.v1beta1.MsgWithdrawBond',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMsgCancelBond(
|
||||||
|
id: string,
|
||||||
|
signer: string
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: 'bond/MsgCancelBond',
|
||||||
|
value: {
|
||||||
|
id,
|
||||||
|
signer
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const protoCreateMsgCancelBond = (
|
||||||
|
id: string,
|
||||||
|
signer: string
|
||||||
|
) => {
|
||||||
|
const cancelBondMessage = new bondTx.vulcanize.bond.v1beta1.MsgCancelBond({
|
||||||
|
id,
|
||||||
|
signer
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: cancelBondMessage,
|
||||||
|
path: 'vulcanize.bond.v1beta1.MsgCancelBond',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Registry } from './index';
|
import { Registry } from './index';
|
||||||
import { getConfig, wait } from './testing/helper';
|
import { getConfig, wait } from './testing/helper';
|
||||||
|
|
||||||
|
const TX_WAIT_TIME = 5000; // in milliseconds.
|
||||||
|
|
||||||
const { mockServer, chibaClonk: { chainId, restEndpoint, gqlEndpoint, privateKey, accountAddress, fee } } = getConfig();
|
const { mockServer, chibaClonk: { chainId, restEndpoint, gqlEndpoint, privateKey, accountAddress, fee } } = getConfig();
|
||||||
|
|
||||||
jest.setTimeout(90 * 1000);
|
jest.setTimeout(90 * 1000);
|
||||||
@ -18,8 +20,8 @@ const bondTests = () => {
|
|||||||
test('Create bond.', async () => {
|
test('Create bond.', async () => {
|
||||||
bondId1 = await registry.getNextBondId(accountAddress);
|
bondId1 = await registry.getNextBondId(accountAddress);
|
||||||
expect(bondId1).toBeDefined();
|
expect(bondId1).toBeDefined();
|
||||||
await registry.createBond({ denom: 'aphoton', amount: '100' }, accountAddress, privateKey, fee);
|
await registry.createBond({ denom: 'aphoton', amount: '1000000000' }, accountAddress, privateKey, fee);
|
||||||
await wait(5000)
|
await wait(TX_WAIT_TIME)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Get bond by ID.', async () => {
|
test('Get bond by ID.', async () => {
|
||||||
@ -27,7 +29,7 @@ const bondTests = () => {
|
|||||||
expect(bond).toBeDefined();
|
expect(bond).toBeDefined();
|
||||||
expect(bond.id).toBe(bondId1);
|
expect(bond.id).toBe(bondId1);
|
||||||
expect(bond.balance).toHaveLength(1);
|
expect(bond.balance).toHaveLength(1);
|
||||||
expect(bond.balance[0]).toEqual({ type: 'aphoton', quantity: '100' });
|
expect(bond.balance[0]).toEqual({ type: 'aphoton', quantity: '1000000000' });
|
||||||
bondOwner = bond.owner;
|
bondOwner = bond.owner;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -44,6 +46,38 @@ const bondTests = () => {
|
|||||||
const bond = bonds.filter((bond: any) => bond.id === bondId1);
|
const bond = bonds.filter((bond: any) => bond.id === bondId1);
|
||||||
expect(bond).toBeDefined();
|
expect(bond).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Refill bond.', async () => {
|
||||||
|
await registry.refillBond({ id: bondId1, denom: 'aphoton', amount: '500' }, accountAddress, privateKey, fee);
|
||||||
|
await wait(TX_WAIT_TIME);
|
||||||
|
|
||||||
|
const [bond] = await registry.getBondsByIds([bondId1]);
|
||||||
|
expect(bond).toBeDefined();
|
||||||
|
expect(bond.id).toBe(bondId1);
|
||||||
|
expect(bond.balance).toHaveLength(1);
|
||||||
|
expect(bond.balance[0]).toEqual({ type: 'aphoton', quantity: '1000000500' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Withdraw bond.', async () => {
|
||||||
|
await registry.withdrawBond({ id: bondId1, denom: 'aphoton', amount: '500' }, accountAddress, privateKey, fee);
|
||||||
|
await wait(TX_WAIT_TIME);
|
||||||
|
|
||||||
|
const [bond] = await registry.getBondsByIds([bondId1]);
|
||||||
|
expect(bond).toBeDefined();
|
||||||
|
expect(bond.id).toBe(bondId1);
|
||||||
|
expect(bond.balance).toHaveLength(1);
|
||||||
|
expect(bond.balance[0]).toEqual({ type: 'aphoton', quantity: '1000000000' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Cancel bond.', async () => {
|
||||||
|
await registry.cancelBond({ id: bondId1 }, accountAddress, privateKey, fee);
|
||||||
|
await wait(TX_WAIT_TIME);
|
||||||
|
|
||||||
|
const [bond] = await registry.getBondsByIds([bondId1]);
|
||||||
|
expect(bond.id).toBe("");
|
||||||
|
expect(bond.owner).toBe("");
|
||||||
|
expect(bond.balance).toHaveLength(0);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mockServer) {
|
if (mockServer) {
|
||||||
|
81
src/index.ts
81
src/index.ts
@ -8,7 +8,7 @@ import {
|
|||||||
Fee,
|
Fee,
|
||||||
} from '@tharsis/transactions'
|
} from '@tharsis/transactions'
|
||||||
|
|
||||||
import { createTxMsgCreateBond, MessageMsgCreateBond } from "./bond";
|
import { createTxMsgCancelBond, createTxMsgCreateBond, createTxMsgRefillBond, createTxMsgWithdrawBond, MessageMsgCancelBond, MessageMsgCreateBond, MessageMsgRefillBond, MessageMsgWithdrawBond } from "./bond";
|
||||||
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";
|
||||||
@ -21,7 +21,6 @@ export const DEFAULT_CHAIN_ID = 'ethermint_9000-1';
|
|||||||
export const parseTxResponse = (result: any) => {
|
export const parseTxResponse = (result: any) => {
|
||||||
const { txhash: hash, height, ...txResponse } = result;
|
const { txhash: hash, height, ...txResponse } = result;
|
||||||
txResponse.data = txResponse.data && Buffer.from(txResponse.data, 'base64').toString('utf8');
|
txResponse.data = txResponse.data && Buffer.from(txResponse.data, 'base64').toString('utf8');
|
||||||
txResponse.log = JSON.parse(txResponse.raw_log);
|
|
||||||
|
|
||||||
txResponse.events.forEach((event:any) => {
|
txResponse.events.forEach((event:any) => {
|
||||||
event.attributes = event.attributes.map(({ key, value }: { key: string, value: string }) => ({
|
event.attributes = event.attributes.map(({ key, value }: { key: string, value: string }) => ({
|
||||||
@ -138,6 +137,84 @@ export class Registry {
|
|||||||
return parseTxResponse(result);
|
return parseTxResponse(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refill bond.
|
||||||
|
*/
|
||||||
|
async refillBond(params: MessageMsgRefillBond, 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 = createTxMsgRefillBond(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Withdraw (from) bond.
|
||||||
|
*/
|
||||||
|
async withdrawBond(params: MessageMsgWithdrawBond, 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 = createTxMsgWithdrawBond(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel bond.
|
||||||
|
*/
|
||||||
|
async cancelBond(params: MessageMsgCancelBond, 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 = createTxMsgCancelBond(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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a generic Tx to the chain.
|
* Submit a generic Tx to the chain.
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const DEFAULT_PRIVATE_KEY = '794ce0bf3c75571416001c3415e69059aeba54038bcac8ce5b9792259e6d193b';
|
const DEFAULT_PRIVATE_KEY = '3d8e23810daecb66ec4ca97805f6bbfc102015c3f22cdda1a783b1d074c43bdd';
|
||||||
const DEFAULT_ADDRESS = 'ethm10atmndy7sm46829rc3yr7cxqucgrz5e9jg58xp'
|
const DEFAULT_ADDRESS = 'ethm1lrdrh056ce23h9d9d5rx34tp0uwj0u9zumynx3'
|
||||||
|
|
||||||
export const wait = (time: number) => new Promise(resolve => setTimeout(resolve, time))
|
export const wait = (time: number) => new Promise(resolve => setTimeout(resolve, time))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user