diff --git a/src/auction.test.ts b/src/auction.test.ts index 08d24b4..d8c5f64 100644 --- a/src/auction.test.ts +++ b/src/auction.test.ts @@ -12,29 +12,24 @@ jest.setTimeout(30 * 60 * 1000); const { chainId, rpcEndpoint, gqlEndpoint, privateKey, fee } = getConfig(); const duration = 60; - -const commitsDuration = Duration.fromPartial({ - seconds: Long.fromNumber(duration), - nanos: 0 -}); -const revealsDuration = Duration.fromPartial({ - seconds: Long.fromNumber(duration), - nanos: 0 -}); +const commitsDuration = Duration.fromPartial({ seconds: Long.fromNumber(60) }); +const revealsDuration = Duration.fromPartial({ seconds: Long.fromNumber(60) }); const commitFee = coin('1000', DENOM); const revealFee = coin('1000', DENOM); const creatorInitialBalance = 1000000000000; const bidderInitialBalance = 20000000; +const lowestBidAmount = 10000000; -const createAuctionTests = () => { +const auctionTests = () => { let registry: Registry; let auctionId: string; - let auctionCreatorAccount: { address: string, privateKey: string, bid?: any }; + let auctionCreatorAccount: { address: string, privateKey: string }; let bidderAccounts: { address: string, privateKey: string, bid?: any }[] = []; + const numBidders = 3; let bidAmounts: Coin[] = []; beforeAll(async () => { @@ -44,31 +39,36 @@ const createAuctionTests = () => { const mnenonic1 = Account.generateMnemonic(); const auctionCreator = await Account.generateFromMnemonic(mnenonic1); await auctionCreator.init(); + await registry.sendCoins({ denom: DENOM, amount: creatorInitialBalance.toString(), destinationAddress: auctionCreator.address }, privateKey, fee); auctionCreatorAccount = { address: auctionCreator.address, privateKey: auctionCreator.privateKey.toString('hex') }; }); test('Setup bidder accounts', async () => { - for (let i = 0; i < 3; i++) { + for (let i = 0; i < numBidders; i++) { const mnenonic = Account.generateMnemonic(); const account = await Account.generateFromMnemonic(mnenonic); await account.init(); + await registry.sendCoins({ denom: DENOM, amount: bidderInitialBalance.toString(), destinationAddress: account.address }, privateKey, fee); bidderAccounts.push({ address: account.address, privateKey: account.privateKey.toString('hex') }); } }); - test('Create vickrey auction', async () => { + test('Create a vickrey auction', async () => { const minimumBid = coin('1000000', DENOM); - const auction = await registry.createAuction({ - commitsDuration, - revealsDuration, - commitFee, - revealFee, - minimumBid - }, - auctionCreatorAccount.privateKey, fee); + const auction = await registry.createAuction( + { + commitsDuration, + revealsDuration, + commitFee, + revealFee, + minimumBid + }, + auctionCreatorAccount.privateKey, + fee + ); expect(auction.auction?.id).toBeDefined(); auctionId = auction.auction?.id || ''; @@ -76,8 +76,8 @@ const createAuctionTests = () => { }); test('Commit bids.', async () => { - for (let i = 0; i < 3; i++) { - bidAmounts.push(coin((10000000 + (i * 500)).toString(), DENOM)); + for (let i = 0; i < numBidders; i++) { + bidAmounts.push(coin((lowestBidAmount + (i * 500)).toString(), DENOM)); bidderAccounts[i].bid = await createBid(chainId, auctionId, bidderAccounts[i].address, `${bidAmounts[i].amount}${bidAmounts[i].denom}`); await registry.commitBid({ auctionId, commitHash: bidderAccounts[i].bid.commitHash }, bidderAccounts[i].privateKey, fee); } @@ -101,7 +101,7 @@ const createAuctionTests = () => { const [auction] = await registry.getAuctionsByIds([auctionId]); expect(auction.status).toEqual('reveal'); - for (let i = 0; i < 3; i++) { + for (let i = 0; i < numBidders; i++) { await registry.revealBid({ auctionId, reveal: bidderAccounts[i].bid.revealString }, bidderAccounts[i].privateKey, fee); } }); @@ -129,33 +129,35 @@ const createAuctionTests = () => { expect(auction.status).toEqual('completed'); const highestBidder = bidderAccounts[bidderAccounts.length - 1]; - const secondHighestBidder = (bidderAccounts[bidderAccounts.length - 2]); + const secondHighestBidder = bidderAccounts[bidderAccounts.length - 2]; + + expect(auction.winnerAddresses).toHaveLength(1); expect(auction.winnerAddresses[0]).toEqual(highestBidder.address); expect(highestBidder.bid.reveal.bidAmount).toEqual(`${auction.winnerBids[0].quantity}${auction.winnerBids[0].type}`); expect(secondHighestBidder.bid.reveal.bidAmount).toEqual(`${auction.winnerPrice.quantity}${auction.winnerPrice.type}`); - const winningPriceAmount = parseInt(auction.winnerPrice.quantity, 10); - const expectedBalance = (bidderInitialBalance - winningPriceAmount); + const winningPriceAmount = parseInt(auction.winnerPrice.quantity); const [winnerAccountObj] = await registry.getAccounts([highestBidder.address]); expect(winnerAccountObj).toBeDefined(); - expect(winnerAccountObj.address).toBe(highestBidder.address); + // Balance should be less than bidder's initial balance - winning price as tx fees also gets deducted const [{ type, quantity }] = winnerAccountObj.balance; - expect(type).toBe(DENOM); - expect(parseInt(quantity)).toBeLessThan(expectedBalance); + expect(parseInt(quantity)).toBeLessThan(bidderInitialBalance - winningPriceAmount); }); }; -const createProviderAuctionTests = () => { +const providerAuctionTests = () => { let registry: Registry; let auctionId: string; let auctionCreatorAccount: { address: string, privateKey: string, bid?: any }; let bidderAccounts: { address: string, privateKey: string, bid?: any }[] = []; + const numBidders = 4; + const numProviders = 3; let bidAmounts: Coin[] = []; beforeAll(async () => { @@ -165,32 +167,36 @@ const createProviderAuctionTests = () => { const mnenonic1 = Account.generateMnemonic(); const auctionCreator = await Account.generateFromMnemonic(mnenonic1); await auctionCreator.init(); + await registry.sendCoins({ denom: DENOM, amount: creatorInitialBalance.toString(), destinationAddress: auctionCreator.address }, privateKey, fee); auctionCreatorAccount = { address: auctionCreator.address, privateKey: auctionCreator.privateKey.toString('hex') }; }); test('Setup bidder accounts', async () => { - for (let i = 0; i < 4; i++) { + for (let i = 0; i < numBidders; i++) { const mnenonic = Account.generateMnemonic(); const account = await Account.generateFromMnemonic(mnenonic); await account.init(); + await registry.sendCoins({ denom: DENOM, amount: bidderInitialBalance.toString(), destinationAddress: account.address }, privateKey, fee); bidderAccounts.push({ address: account.address, privateKey: account.privateKey.toString('hex') }); } }); - test('Create provider auction', async () => { - const maxPrice = coin('100000000', DENOM); + test('Create a provider auction', async () => { + const maxPrice = coin((10 * lowestBidAmount).toString(), DENOM); - const auction = await registry.createProviderAuction({ - commitsDuration, - revealsDuration, - commitFee, - revealFee, - maxPrice, - numProviders: 3 - }, - auctionCreatorAccount.privateKey, fee); + const auction = await registry.createProviderAuction( + { + commitsDuration, + revealsDuration, + commitFee, + revealFee, + maxPrice, + numProviders + }, + auctionCreatorAccount.privateKey, fee + ); expect(auction.auction?.id).toBeDefined(); auctionId = auction.auction?.id || ''; @@ -198,15 +204,15 @@ const createProviderAuctionTests = () => { }); test('Commit bids.', async () => { - for (let i = 0; i < 4; i++) { - bidAmounts.push(coin((100000 + (i * 500)).toString(), DENOM)); + for (let i = 0; i < numBidders; i++) { + bidAmounts.push(coin((lowestBidAmount + (i * 500)).toString(), DENOM)); bidderAccounts[i].bid = await createBid(chainId, auctionId, bidderAccounts[i].address, `${bidAmounts[i].amount}${bidAmounts[i].denom}`); await registry.commitBid({ auctionId, commitHash: bidderAccounts[i].bid.commitHash }, bidderAccounts[i].privateKey, fee); } const [auction] = await registry.getAuctionsByIds([auctionId]); expect(auction.status).toEqual('commit'); - expect(auction.bids.length).toEqual(3); + expect(auction.bids.length).toEqual(numBidders); auction.bids.forEach((bid: any) => { expect(bid.status).toEqual('commit'); }); @@ -223,7 +229,7 @@ const createProviderAuctionTests = () => { const [auction] = await registry.getAuctionsByIds([auctionId]); expect(auction.status).toEqual('reveal'); - for (let i = 0; i < 4; i++) { + for (let i = 0; i < numBidders; i++) { await registry.revealBid({ auctionId, reveal: bidderAccounts[i].bid.revealString }, bidderAccounts[i].privateKey, fee); } }); @@ -250,51 +256,49 @@ const createProviderAuctionTests = () => { const [auction] = await registry.getAuctionsByIds([auctionId]); expect(auction.status).toEqual('completed'); - const bidWinners = bidderAccounts.slice(0, 3); + const bidWinners = bidderAccounts.slice(0, numProviders); + const bidLosers = bidderAccounts.slice(numProviders, numBidders); // Check balances of auction winners for (let i = 0; i < bidWinners.length; i++) { - const winner = bidWinners[i]; + const expectedWinner = bidWinners[i]; - expect(auction.winnerAddresses[i]).toEqual(winner.address); - expect(winner.bid.reveal.bidAmount).toEqual(`${auction.winnerBids[i].quantity}${auction.winnerBids[i].type}`); + expect(auction.winnerAddresses[i]).toEqual(expectedWinner.address); + expect(expectedWinner.bid.reveal.bidAmount).toEqual(`${auction.winnerBids[i].quantity}${auction.winnerBids[i].type}`); - const [winnerAccountObj] = await registry.getAccounts([winner.address]); + const [winnerAccountObj] = await registry.getAccounts([expectedWinner.address]); expect(winnerAccountObj).toBeDefined(); - expect(winnerAccountObj.address).toBe(winner.address); const [{ type, quantity }] = winnerAccountObj.balance; - const winningBidAmount = parseInt(auction.winnerPrice.quantity, 10); - const expectedBalance = bidderInitialBalance + winningBidAmount; + const actualBalance = parseInt(quantity); + const winningBidAmount = parseInt(auction.winnerPrice.quantity); - // The actual balance would be less than expected balance as fees would also get deducted + // Balance should be more than bidder's initial balance but + // less than initial balance + winning price as tx fees also gets deducted expect(type).toBe(DENOM); - expect(expectedBalance).toBeLessThan(parseInt(quantity)); + expect(actualBalance).toBeGreaterThan(bidderInitialBalance); + expect(actualBalance).toBeLessThan(bidderInitialBalance + winningBidAmount); } // Check balances of non-winners - for (let i = 3; i < bidderAccounts.length; i++) { - const bidder = bidderAccounts[i]; - + for (const bidder of bidLosers) { const [bidderAccountObj] = await registry.getAccounts([bidder.address]); expect(bidderAccountObj).toBeDefined(); - expect(bidderAccountObj.address).toBe(bidder.address); const [{ type, quantity }] = bidderAccountObj.balance; - // The balance would be less than initial balance as fees would get deducted + // Balance should be less than initial balance as fees would get deducted expect(type).toBe(DENOM); expect(parseInt(quantity)).toBeLessThan(bidderInitialBalance); } const [creatorAccountObj] = await registry.getAccounts([auctionCreatorAccount.address]); expect(creatorAccountObj).toBeDefined(); - expect(creatorAccountObj.address).toBe(auctionCreatorAccount.address); const [{ type, quantity }] = creatorAccountObj.balance; - const totalWinningAmount = parseInt(auction.winnerPrice.quantity, 10) * bidWinners.length; - const expectedCreatorBalance = creatorInitialBalance + totalWinningAmount; + const totalWinningAmount = parseInt(auction.winnerPrice.quantity) * bidWinners.length; + const expectedCreatorBalance = creatorInitialBalance - totalWinningAmount; // The balance would be less than expected balance expect(type).toBe(DENOM); @@ -302,5 +306,5 @@ const createProviderAuctionTests = () => { }); }; -describe('Vickrey Auction', () => createAuctionTests()); -describe('Provider Auction', () => createProviderAuctionTests()); +describe('Vickrey Auction', () => auctionTests()); +describe('Provider Auction', () => providerAuctionTests()); diff --git a/src/index.ts b/src/index.ts index b076726..622b9fd 100644 --- a/src/index.ts +++ b/src/index.ts @@ -33,8 +33,8 @@ import { Coin } from './proto/cosmos/base/v1beta1/coin'; import { MsgCancelBondResponse, MsgCreateBondResponse, MsgRefillBondResponse, MsgWithdrawBondResponse } from './proto/cerc/bond/v1/tx'; import { MsgOnboardParticipantResponse } from './proto/cerc/onboarding/v1/tx'; import { MsgSendResponse } from './proto/cosmos/bank/v1beta1/tx'; -import { DEFAULT_GAS_ESTIMATION_MULTIPLIER } from './constants'; -import { MsgCreateAuction, MsgCreateAuctionResponse } from './proto/cerc/auction/v1/tx'; +import { AUCTION_KIND_PROVIDER, AUCTION_KIND_VICKREY, DEFAULT_GAS_ESTIMATION_MULTIPLIER } from './constants'; +import { MsgCreateAuctionResponse } from './proto/cerc/auction/v1/tx'; /** * Create an auction bid. @@ -503,22 +503,24 @@ export class Registry { ); } - async createAuction ({ - commitsDuration, - revealsDuration, - commitFee, - revealFee, - minimumBid - }: MsgCreateVickreyAuction, - privateKey: string, - fee: StdFee | number = DEFAULT_GAS_ESTIMATION_MULTIPLIER): Promise { + async createAuction ( + { + commitsDuration, + revealsDuration, + commitFee, + revealFee, + minimumBid + }: MsgCreateVickreyAuction, + privateKey: string, + fee: StdFee | number = DEFAULT_GAS_ESTIMATION_MULTIPLIER + ): Promise { const account = new Account(Buffer.from(privateKey, 'hex')); await account.init(); const laconicClient = await this.getLaconicClient(account); return laconicClient.createAuction( account.address, - 'vickrey', + AUCTION_KIND_VICKREY, commitsDuration, revealsDuration, commitFee, @@ -530,23 +532,25 @@ export class Registry { ); } - async createProviderAuction ({ - commitsDuration, - revealsDuration, - commitFee, - revealFee, - maxPrice, - numProviders - }: MsgCreateProviderAuction, - privateKey: string, - fee: StdFee | number = DEFAULT_GAS_ESTIMATION_MULTIPLIER): Promise { + async createProviderAuction ( + { + commitsDuration, + revealsDuration, + commitFee, + revealFee, + maxPrice, + numProviders + }: MsgCreateProviderAuction, + privateKey: string, + fee: StdFee | number = DEFAULT_GAS_ESTIMATION_MULTIPLIER + ): Promise { const account = new Account(Buffer.from(privateKey, 'hex')); await account.init(); const laconicClient = await this.getLaconicClient(account); return laconicClient.createAuction( account.address, - 'provider', + AUCTION_KIND_PROVIDER, commitsDuration, revealsDuration, commitFee, diff --git a/src/laconic-client.ts b/src/laconic-client.ts index 669acf6..9146cb7 100644 --- a/src/laconic-client.ts +++ b/src/laconic-client.ts @@ -431,13 +431,13 @@ export class LaconicClient extends SigningStargateClient { const createAuctionMsg: MsgCreateAuctionEncodeObject = { typeUrl: typeUrlMsgCreateAuction, value: { + signer, + kind, commitsDuration, revealsDuration, commitFee, revealFee, minimumBid, - signer, - kind, maxPrice, numProviders }