From 630705edfe833f21b19e23db2b43eaf1b4870b67 Mon Sep 17 00:00:00 2001 From: Nicholas Rodrigues Lordello Date: Wed, 6 May 2020 17:15:04 +0200 Subject: [PATCH] Use token array instead of map (#739) This PR refactors the auction state to use a token array instead of a map so that it is trivial to check if a token listing was missed. ### Test Plan New unit tests added --- src/streamed/state.ts | 19 +++++++++---------- test/models/streamed/state.spec.ts | 27 ++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/streamed/state.ts b/src/streamed/state.ts index 071797bf0..69d79bf30 100644 --- a/src/streamed/state.ts +++ b/src/streamed/state.ts @@ -82,7 +82,7 @@ const UNLIMITED_ORDER_AMOUNT = BigInt(2 ** 128) - BigInt(1) * JSON representation of the account state. */ export interface AuctionStateJson { - tokens: { [key: string]: string }; + tokens: string[]; accounts: { [key: string]: { balances: { [key: string]: string }; @@ -106,7 +106,7 @@ export interface AuctionStateJson { export class AuctionState { private lastBlock = -1; - private readonly tokens: Map = new Map(); + private readonly tokens: Address[] = []; private readonly accounts: Map = new Map(); private lastSolution?: Event; @@ -131,7 +131,7 @@ export class AuctionState { } return { - tokens: map2obj(this.tokens, addr => addr), + tokens: this.tokens.slice(0), accounts: map2obj(this.accounts, account => ({ balances: map2obj(account.balances, balance => balance.toString()), pendingWithdrawals: map2obj( @@ -361,15 +361,14 @@ export class AuctionState { * it was listed out of order. */ private applyTokenListing({ id, token }: Event): void { - const tokenId = parseInt(id) if (this.options.strict) { assert( - this.tokens.get(tokenId) === undefined, - `token ${tokenId} has already been listed`, + this.tokens.length === parseInt(id), + `token ${token} with ID ${id} added as token ${this.tokens.length}`, ) } - this.tokens.set(parseInt(id), token) + this.tokens.push(token) } /** @@ -482,9 +481,9 @@ export class AuctionState { ) return token } else { - const tokenAddr = this.tokens.get(token) - assert(tokenAddr, `missing token ${token}`) - return tokenAddr as Address + const tokenAddr = this.tokens[token] + assert(tokenAddr !== undefined, `missing token ${token}`) + return tokenAddr } } diff --git a/test/models/streamed/state.spec.ts b/test/models/streamed/state.spec.ts index ca2b6cc2a..c2def530f 100644 --- a/test/models/streamed/state.spec.ts +++ b/test/models/streamed/state.spec.ts @@ -61,7 +61,32 @@ describe("Account State", () => { const state = auctionState() expect(() => state.applyEvents([ event(2, "TokenListing", { id: "0", token: addr(1) }), - event(1, "TokenListing", { id: "0", token: addr(1) }), + event(1, "TokenListing", { id: "1", token: addr(1) }), + ])).to.throw() + }) + }) + + describe("TokenListing", () => { + it("Adds a new token", () => { + const state = auctionState() + state.applyEvents([ + event(1, "TokenListing", { id: "0", token: addr(0) }), + ]) + expect(state.toJSON().tokens[0]).to.equal(addr(0)) + }) + + it("Throws if the same token is listed twice", () => { + const state = auctionState() + expect(() => state.applyEvents([ + event(1, "TokenListing", { id: "0", token: addr(0) }), + event(2, "TokenListing", { id: "0", token: addr(0) }), + ])).to.throw() + }) + + it("Throws if a token is skipped", () => { + const state = auctionState() + expect(() => state.applyEvents([ + event(1, "TokenListing", { id: "1", token: addr(0) }), ])).to.throw() }) })