blob: ae9c232bb03eaf0509fe715af615f2e999ca0564 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
import * as _ from 'lodash';
import * as Web3 from 'web3';
import {BigNumber} from 'bignumber.js';
import {BlockParamLiteral, InternalZeroExError, ZeroExError} from '../types';
import {Web3Wrapper} from '../web3_wrapper';
import {intervalUtils} from '../utils/interval_utils';
const DEFAULT_BLOCK_POLLING_INTERVAL_MS = 500;
/**
* Store for a current latest block number
*/
export class BlockStore {
private web3Wrapper?: Web3Wrapper;
private latestBlockNumber?: number;
private intervalId?: NodeJS.Timer;
private blockPollingIntervalMs: number;
private numConfirmations: number;
constructor(numConfirmations: number, web3Wrapper?: Web3Wrapper, blockPollingIntervalMs?: number) {
this.numConfirmations = numConfirmations;
this.web3Wrapper = web3Wrapper;
this.blockPollingIntervalMs = blockPollingIntervalMs || DEFAULT_BLOCK_POLLING_INTERVAL_MS;
}
public getBlockNumber(): Web3.BlockParam {
let blockNumber;
if (this.numConfirmations === 0) {
blockNumber = BlockParamLiteral.Pending;
} else if (this.numConfirmations === 1) {
// HACK: We special-case `numConfirmations === 1` so that we can use this block store without actually
// setting `latestBlockNumber` when block number is latest (in order validation) whhich allows us to omit
// an async call in a constructor of `ExchangeTransferSimulator`
blockNumber = BlockParamLiteral.Latest;
} else {
if (_.isUndefined(this.latestBlockNumber)) {
throw new Error(InternalZeroExError.LatestBlockNumberNotSet);
}
// Latest block already has 1 confirmation
blockNumber = this.latestBlockNumber - this.numConfirmations + 1;
}
return blockNumber;
}
public async startAsync(): Promise<void> {
if (this.numConfirmations === 0 || this.numConfirmations === 1) {
return; // no-op
}
await this.updateLatestBlockAsync();
this.intervalId = intervalUtils.setAsyncExcludingInterval(
this.updateLatestBlockAsync.bind(this), this.blockPollingIntervalMs,
);
}
public stop(): void {
if (!_.isUndefined(this.intervalId)) {
intervalUtils.clearAsyncExcludingInterval(this.intervalId);
}
}
private async updateLatestBlockAsync(): Promise<void> {
if (_.isUndefined(this.web3Wrapper)) {
throw new Error(InternalZeroExError.Web3WrapperRequiredToStartBlockStore);
}
const block = await this.web3Wrapper.getBlockAsync(BlockParamLiteral.Latest);
if (_.isNull(block.number)) {
throw new Error(ZeroExError.FailedToFetchLatestBlock);
}
this.latestBlockNumber = block.number;
}
}
|