forked from cerc-io/registry-sdk
Add auction tests for commitBid and revealBid
This commit is contained in:
parent
d51f9618e0
commit
838edaa9a6
@ -1,6 +1,6 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
|
||||||
import { Registry, Account } from './index';
|
import { Registry, Account, createBid } from './index';
|
||||||
import { getConfig } from './testing/helper';
|
import { getConfig } from './testing/helper';
|
||||||
|
|
||||||
jest.setTimeout(30 * 60 * 1000);
|
jest.setTimeout(30 * 60 * 1000);
|
||||||
@ -10,7 +10,7 @@ const { chainId, restEndpoint, gqlEndpoint, privateKey, accountAddress, fee } =
|
|||||||
const auctionTests = (numBidders = 3) => {
|
const auctionTests = (numBidders = 3) => {
|
||||||
let registry: Registry;
|
let registry: Registry;
|
||||||
|
|
||||||
const accounts: { address: string, privateKey: string }[] = [];
|
const accounts: { address: string, privateKey: string, bid?: any }[] = [];
|
||||||
|
|
||||||
let auctionId: string;
|
let auctionId: string;
|
||||||
let authorityName: string;
|
let authorityName: string;
|
||||||
@ -28,11 +28,11 @@ const auctionTests = (numBidders = 3) => {
|
|||||||
await account.init();
|
await account.init();
|
||||||
const bidderAddress = account.formattedCosmosAddress;
|
const bidderAddress = account.formattedCosmosAddress;
|
||||||
assert(bidderAddress)
|
assert(bidderAddress)
|
||||||
await registry.sendCoins({ denom: 'uwire', amount: '1000000000', destinationAddress: bidderAddress }, accountAddress, privateKey, fee);
|
await registry.sendCoins({ denom: 'aphoton', amount: '1000000000', destinationAddress: bidderAddress }, accountAddress, privateKey, fee);
|
||||||
accounts.push({ address: bidderAddress, privateKey: account.privateKey.toString('hex') });
|
accounts.push({ address: bidderAddress, privateKey: account.privateKey.toString('hex') });
|
||||||
}
|
}
|
||||||
|
|
||||||
accounts.unshift({ address: accountAddress, privateKey });
|
accounts[0] = { address: accountAddress, privateKey };
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Reserve authority.', async () => {
|
test('Reserve authority.', async () => {
|
||||||
@ -51,6 +51,68 @@ const auctionTests = (numBidders = 3) => {
|
|||||||
|
|
||||||
auctionId = record.auction.id;
|
auctionId = record.auction.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Commit bids.', async () => {
|
||||||
|
for (let i = 0; i < numBidders; i++) {
|
||||||
|
accounts[i].bid = await createBid(chainId, auctionId, accounts[i].address, `${10000000 + (i * 500)}aphoton`);
|
||||||
|
await registry.commitBid({ auctionId, commitHash: accounts[i].bid.commitHash }, accounts[i].address, accounts[i].privateKey, fee);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Check bids are committed', async () => {
|
||||||
|
const [record] = await registry.lookupAuthorities([authorityName], true);
|
||||||
|
expect(record.auction.id).toBeDefined();
|
||||||
|
expect(record.auction.status).toEqual('commit');
|
||||||
|
expect(record.auction.bids).toHaveLength(accounts.length);
|
||||||
|
|
||||||
|
record.auction.bids.forEach((bid: any) => {
|
||||||
|
expect(bid.status).toEqual('commit');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Wait for reveal phase.', (done) => {
|
||||||
|
setTimeout(done, 60 * 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Reveal bids.', async () => {
|
||||||
|
const [auction] = await registry.getAuctionsByIds([auctionId]);
|
||||||
|
expect(auction.status).toEqual('reveal');
|
||||||
|
|
||||||
|
for (let i = 0; i < numBidders; i++) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await registry.revealBid({ auctionId, reveal: accounts[i].bid.revealString }, accounts[i].address, accounts[i].privateKey, fee);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Check bids are revealed', async () => {
|
||||||
|
const [auction] = await registry.getAuctionsByIds([auctionId]);
|
||||||
|
expect(auction.status).toEqual('reveal');
|
||||||
|
|
||||||
|
auction.bids.forEach((bid: any) => {
|
||||||
|
expect(bid.status).toEqual('reveal');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Wait for auction completion.', (done) => {
|
||||||
|
setTimeout(done, 60 * 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Check auction winner, authority owner and status.', async () => {
|
||||||
|
const [auction] = await registry.getAuctionsByIds([auctionId]);
|
||||||
|
expect(auction.status).toEqual('completed');
|
||||||
|
|
||||||
|
const highestBidder = accounts[accounts.length - 1];
|
||||||
|
const secondHighestBidder = (accounts.length > 1 ? accounts[accounts.length - 2] : highestBidder);
|
||||||
|
|
||||||
|
expect(auction.winnerAddress).toEqual(highestBidder.address);
|
||||||
|
expect(highestBidder.bid.reveal.bidAmount).toEqual(`${auction.winnerBid.quantity}${auction.winnerBid.type}`);
|
||||||
|
expect(secondHighestBidder.bid.reveal.bidAmount).toEqual(`${auction.winnerPrice.quantity}${auction.winnerPrice.type}`);
|
||||||
|
|
||||||
|
const [record] = await registry.lookupAuthorities([authorityName], true);
|
||||||
|
expect(record.ownerAddress).toEqual(highestBidder.address);
|
||||||
|
expect(record.height).toBeDefined();
|
||||||
|
expect(record.status).toEqual('active');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const withNumBidders = (numBidders: number) => () => auctionTests(numBidders);
|
const withNumBidders = (numBidders: number) => () => auctionTests(numBidders);
|
||||||
@ -70,6 +132,6 @@ if (!process.env.AUCTIONS_ENABLED) {
|
|||||||
yarn test:auctions
|
yarn test:auctions
|
||||||
*/
|
*/
|
||||||
describe('Auction (1 bidder)', withNumBidders(1));
|
describe('Auction (1 bidder)', withNumBidders(1));
|
||||||
describe('Auction (2 bidders)', withNumBidders(2));
|
xdescribe('Auction (2 bidders)', withNumBidders(2));
|
||||||
describe('Auction (4 bidders)', withNumBidders(4));
|
xdescribe('Auction (4 bidders)', withNumBidders(4));
|
||||||
}
|
}
|
||||||
|
105
src/index.ts
105
src/index.ts
@ -9,12 +9,40 @@ import {
|
|||||||
MessageSendParams
|
MessageSendParams
|
||||||
} from '@tharsis/transactions'
|
} from '@tharsis/transactions'
|
||||||
|
|
||||||
import { createTxMsgCancelBond, createTxMsgCreateBond, createTxMsgRefillBond, createTxMsgWithdrawBond, MessageMsgCancelBond, MessageMsgCreateBond, MessageMsgRefillBond, MessageMsgWithdrawBond } from "./messages/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";
|
||||||
import { createTxMsgDeleteName, createTxMsgReserveAuthority, createTxMsgSetAuthorityBond, createTxMsgSetName, createTxMsgSetRecord, MessageMsgDeleteName, MessageMsgReserveAuthority, MessageMsgSetAuthorityBond, MessageMsgSetName, MessageMsgSetRecord, NAMESERVICE_ERRORS } from './messages/nameservice';
|
|
||||||
import { Payload, Record } from './types';
|
import { Payload, Record } from './types';
|
||||||
|
import { Util } from './util';
|
||||||
|
import {
|
||||||
|
createTxMsgCancelBond,
|
||||||
|
createTxMsgCreateBond,
|
||||||
|
createTxMsgRefillBond,
|
||||||
|
createTxMsgWithdrawBond,
|
||||||
|
MessageMsgCancelBond,
|
||||||
|
MessageMsgCreateBond,
|
||||||
|
MessageMsgRefillBond,
|
||||||
|
MessageMsgWithdrawBond
|
||||||
|
} from "./messages/bond";
|
||||||
|
import {
|
||||||
|
createTxMsgDeleteName,
|
||||||
|
createTxMsgReserveAuthority,
|
||||||
|
createTxMsgSetAuthorityBond,
|
||||||
|
createTxMsgSetName,
|
||||||
|
createTxMsgSetRecord,
|
||||||
|
MessageMsgDeleteName,
|
||||||
|
MessageMsgReserveAuthority,
|
||||||
|
MessageMsgSetAuthorityBond,
|
||||||
|
MessageMsgSetName,
|
||||||
|
MessageMsgSetRecord,
|
||||||
|
NAMESERVICE_ERRORS
|
||||||
|
} from './messages/nameservice';
|
||||||
|
import {
|
||||||
|
createTxMsgCommitBid,
|
||||||
|
createTxMsgRevealBid,
|
||||||
|
MessageMsgCommitBid,
|
||||||
|
MessageMsgRevealBid
|
||||||
|
} from './messages/auction';
|
||||||
|
|
||||||
const DEFAULT_WRITE_ERROR = 'Unable to write to chiba-clonk.';
|
const DEFAULT_WRITE_ERROR = 'Unable to write to chiba-clonk.';
|
||||||
|
|
||||||
@ -35,6 +63,32 @@ export const parseTxResponse = (result: any) => {
|
|||||||
return { hash, height, ...txResponse };
|
return { hash, height, ...txResponse };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an auction bid.
|
||||||
|
*/
|
||||||
|
export const createBid = async (chainId: string, auctionId: string, bidderAddress: string, bidAmount: string, noise?: string) => {
|
||||||
|
if (!noise) {
|
||||||
|
noise = Account.generateMnemonic();
|
||||||
|
}
|
||||||
|
|
||||||
|
const reveal = {
|
||||||
|
chainId,
|
||||||
|
auctionId,
|
||||||
|
bidderAddress,
|
||||||
|
bidAmount,
|
||||||
|
noise
|
||||||
|
};
|
||||||
|
|
||||||
|
const commitHash = await Util.getContentId(reveal);
|
||||||
|
const revealString = Buffer.from(JSON.stringify(reveal)).toString('hex');
|
||||||
|
|
||||||
|
return {
|
||||||
|
commitHash,
|
||||||
|
reveal,
|
||||||
|
revealString
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const isKeyValid = (key: string) => key && key.match(/^[0-9a-fA-F]{64}$/);
|
export const isKeyValid = (key: string) => key && key.match(/^[0-9a-fA-F]{64}$/);
|
||||||
|
|
||||||
export class Registry {
|
export class Registry {
|
||||||
@ -277,6 +331,53 @@ export class Registry {
|
|||||||
return parseTxResponse(result);
|
return parseTxResponse(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit auction bid.
|
||||||
|
*/
|
||||||
|
async commitBid(params: MessageMsgCommitBid, senderAddress: string, privateKey: string, fee: Fee) {
|
||||||
|
let result;
|
||||||
|
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 = createTxMsgCommitBid(this._chain, sender, fee, '', params)
|
||||||
|
result = await this._submitTx(msg, privateKey, sender);
|
||||||
|
|
||||||
|
return parseTxResponse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reveal auction bid.
|
||||||
|
*/
|
||||||
|
async revealBid(params: MessageMsgRevealBid, senderAddress: string, privateKey: string, fee: Fee) {
|
||||||
|
let result;
|
||||||
|
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 = createTxMsgRevealBid(this._chain, sender, fee, '', params)
|
||||||
|
result = await this._submitTx(msg, privateKey, sender);
|
||||||
|
|
||||||
|
return parseTxResponse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get records by ids.
|
||||||
|
*/
|
||||||
|
async getAuctionsByIds(ids: string[]) {
|
||||||
|
return this._client.getAuctionsByIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup authorities by names.
|
* Lookup authorities by names.
|
||||||
*/
|
*/
|
||||||
|
149
src/messages/auction.ts
Normal file
149
src/messages/auction.ts
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
import {
|
||||||
|
generateTypes,
|
||||||
|
} from '@tharsis/eip712'
|
||||||
|
import {
|
||||||
|
Chain,
|
||||||
|
Sender,
|
||||||
|
Fee,
|
||||||
|
} from '@tharsis/transactions'
|
||||||
|
|
||||||
|
import * as auctionTx from '../proto/vulcanize/auction/v1beta1/tx'
|
||||||
|
import { createTx } from './util'
|
||||||
|
|
||||||
|
const MSG_COMMIT_BID_TYPES = {
|
||||||
|
MsgValue: [
|
||||||
|
{ name: 'auction_id', type: 'string' },
|
||||||
|
{ name: 'commit_hash', type: 'string' },
|
||||||
|
{ name: 'signer', type: 'string' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageMsgCommitBid {
|
||||||
|
auctionId: string,
|
||||||
|
commitHash: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
const MSG_REVEAL_BID_TYPES = {
|
||||||
|
MsgValue: [
|
||||||
|
{ name: 'auction_id', type: 'string' },
|
||||||
|
{ name: 'reveal', type: 'string' },
|
||||||
|
{ name: 'signer', type: 'string' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessageMsgRevealBid {
|
||||||
|
auctionId: string,
|
||||||
|
reveal: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTxMsgCommitBid(
|
||||||
|
chain: Chain,
|
||||||
|
sender: Sender,
|
||||||
|
fee: Fee,
|
||||||
|
memo: string,
|
||||||
|
params: MessageMsgCommitBid,
|
||||||
|
) {
|
||||||
|
const types = generateTypes(MSG_COMMIT_BID_TYPES)
|
||||||
|
|
||||||
|
const msg = createMsgCommitBid(
|
||||||
|
params.auctionId,
|
||||||
|
params.commitHash,
|
||||||
|
sender.accountAddress,
|
||||||
|
)
|
||||||
|
|
||||||
|
const msgCosmos = protoCreateMsgCommitBid(
|
||||||
|
params.auctionId,
|
||||||
|
params.commitHash,
|
||||||
|
sender.accountAddress,
|
||||||
|
)
|
||||||
|
|
||||||
|
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createTxMsgRevealBid(
|
||||||
|
chain: Chain,
|
||||||
|
sender: Sender,
|
||||||
|
fee: Fee,
|
||||||
|
memo: string,
|
||||||
|
params: MessageMsgRevealBid,
|
||||||
|
) {
|
||||||
|
const types = generateTypes(MSG_REVEAL_BID_TYPES)
|
||||||
|
|
||||||
|
const msg = createMsgRevealBid(
|
||||||
|
params.auctionId,
|
||||||
|
params.reveal,
|
||||||
|
sender.accountAddress,
|
||||||
|
)
|
||||||
|
|
||||||
|
const msgCosmos = protoCreateMsgRevealBid(
|
||||||
|
params.auctionId,
|
||||||
|
params.reveal,
|
||||||
|
sender.accountAddress,
|
||||||
|
)
|
||||||
|
|
||||||
|
return createTx(chain, sender, fee, memo, types, msg, msgCosmos)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMsgCommitBid(
|
||||||
|
auctionId: string,
|
||||||
|
commitHash: string,
|
||||||
|
signer: string
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: 'auction/MsgCommitBid',
|
||||||
|
value: {
|
||||||
|
auction_id: auctionId,
|
||||||
|
commit_hash: commitHash,
|
||||||
|
signer,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const protoCreateMsgCommitBid = (
|
||||||
|
auctionId: string,
|
||||||
|
commitHash: string,
|
||||||
|
signer: string
|
||||||
|
) => {
|
||||||
|
const commitBidMessage = new auctionTx.vulcanize.auction.v1beta1.MsgCommitBid({
|
||||||
|
auction_id: auctionId,
|
||||||
|
commit_hash: commitHash,
|
||||||
|
signer,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: commitBidMessage,
|
||||||
|
path: 'vulcanize.auction.v1beta1.MsgCommitBid',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMsgRevealBid(
|
||||||
|
auctionId: string,
|
||||||
|
reveal: string,
|
||||||
|
signer: string
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: 'auction/MsgRevealBid',
|
||||||
|
value: {
|
||||||
|
auction_id: auctionId,
|
||||||
|
reveal,
|
||||||
|
signer,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const protoCreateMsgRevealBid = (
|
||||||
|
auctionId: string,
|
||||||
|
reveal: string,
|
||||||
|
signer: string
|
||||||
|
) => {
|
||||||
|
const revealBidMessage = new auctionTx.vulcanize.auction.v1beta1.MsgRevealBid({
|
||||||
|
auction_id: auctionId,
|
||||||
|
reveal,
|
||||||
|
signer,
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: revealBidMessage,
|
||||||
|
path: 'vulcanize.auction.v1beta1.MsgRevealBid',
|
||||||
|
}
|
||||||
|
}
|
@ -203,6 +203,26 @@ export class RegistryClient {
|
|||||||
return result['lookupAuthorities'];
|
return result['lookupAuthorities'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get auctions by ids.
|
||||||
|
*/
|
||||||
|
async getAuctionsByIds(ids: string[]) {
|
||||||
|
assert(ids);
|
||||||
|
assert(ids.length);
|
||||||
|
|
||||||
|
const query = `query ($ids: [String!]) {
|
||||||
|
getAuctionsByIds(ids: $ids) {
|
||||||
|
${auctionFields}
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const variables = {
|
||||||
|
ids
|
||||||
|
};
|
||||||
|
|
||||||
|
return RegistryClient.getResult(this._graph(query)(variables), 'getAuctionsByIds');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup names.
|
* Lookup names.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user