UNPKG

0xweb

Version:

Contract package manager and other web3 tools

117 lines (98 loc) 3.89 kB
import alot from 'alot'; import { Web3Client } from '@dequanto/clients/Web3Client'; import { $bigint } from '@dequanto/utils/$bigint'; import { GasWatcherLogger } from './GasWatcherLogger'; import { GasWatcherStore, IGasWatcherStore } from './GasWatcherStore'; import { GasWatcherTx, IGasWatcherCondition } from './GasWatcherTx'; import { IAccount } from '@dequanto/models/TAccount'; import type { TxWriter } from '../TxWriter'; export class GasWatcherService { private pending: GasWatcherTx[] = []; private logger = new GasWatcherLogger(); private timer; static async load (client: Web3Client, store: IGasWatcherStore = new GasWatcherStore(client.platform)) { let service = new GasWatcherService(client, store); await service.loadTxs(); return service; } protected constructor (public client: Web3Client, public store: IGasWatcherStore) { } start () { this.tick(); //setInterval(() => this.tick(), ms); } async tick () { let start = Date.now(); let [block, priceInfo] = await Promise.all([ this.client.getBlockNumber(), this.client.getGasPrice() ]); let price = priceInfo.price; this.logger.logPrice(price, block); await this.store.savePrice({ date: new Date(), price }); await alot(this.pending) .forEachAsync(async entry => { await entry.tick(price); }) .toArrayAsync(); // let end = Date.now(); // console.log(`Gas tick completed in ${$date.formatTimespan(end - start)}`); let ms = 30_000; if (this.pending.length > 0) { let expectPrice = alot(this.pending).max(x => x.condition.price) ; if (expectPrice < price && price - expectPrice < 10) { ms = 15_000; } } // if (expectPrice < price) { // ms *= Number(price) / Number(expectPrice) * .5; // } setTimeout(() => { this.tick(); }, ms) } async add (writer: TxWriter, condition: IGasWatcherCondition) { let writerJson = writer.toJSON(); let exists = this.pending.some(pending => { let currentData = writer.builder.data; let pendingData = pending.txWriter.builder.data; let currentTo = currentData.to; let pendingTo = pendingData.to; if (currentTo !== pendingTo) { return false; } let currentFrom = (writer.account as IAccount).address; let pendingFrom = (pending.txWriter.account as IAccount).address; if (currentFrom !== pendingFrom) { return false; } if (currentData.data !== pendingData.data) { return false; } // similar return true; }); if (exists) { return; } let gasWatcherWriter = await GasWatcherTx.fromJSON(condition, writerJson, this.logger); this.pending.push(gasWatcherWriter); let id = gasWatcherWriter.txWriter.id; let gwei = $bigint.toGweiFromWei(gasWatcherWriter.condition.price); this.logger.logTx(id, `Transaction was added to listed for ${ gwei } gas gwei`) // Ensure completed txs are removed this.pending = this.pending.filter(x => x.txWriter.receipt == null); await this.saveTxs(); } private async loadTxs () { let jsons = await this.store.loadTxs(); let pending = await alot(jsons) .mapAsync(x => GasWatcherTx.fromJSON(x.condition, x.writer, this.logger)) .toArrayAsync(); this.pending = pending; } private async saveTxs () { let jsons = this.pending.map(x => x.toJSON()); await this.store.saveTxs(jsons); } }