Skip to content

Commit

Permalink
Use token array instead of map (#739)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nlordell authored May 6, 2020
1 parent ce6516f commit 630705e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 11 deletions.
19 changes: 9 additions & 10 deletions src/streamed/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand All @@ -106,7 +106,7 @@ export interface AuctionStateJson {
export class AuctionState {
private lastBlock = -1;

private readonly tokens: Map<TokenId, Address> = new Map();
private readonly tokens: Address[] = [];
private readonly accounts: Map<Address, Account> = new Map();
private lastSolution?: Event<BatchExchange, "SolutionSubmission">;

Expand All @@ -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(
Expand Down Expand Up @@ -361,15 +361,14 @@ export class AuctionState {
* it was listed out of order.
*/
private applyTokenListing({ id, token }: Event<BatchExchange, "TokenListing">): 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)
}

/**
Expand Down Expand Up @@ -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
}
}

Expand Down
27 changes: 26 additions & 1 deletion test/models/streamed/state.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
})
Expand Down

0 comments on commit 630705e

Please sign in to comment.