Implement scraping and parsing exchange cancel events
This commit is contained in:
committed by
Fred Carlsen
parent
7d9afce13b
commit
5262d3b1f2
@@ -1,4 +1,4 @@
|
||||
import { ExchangeEventArgs, ExchangeFillEventArgs } from '@0xproject/contract-wrappers';
|
||||
import { ExchangeCancelEventArgs, ExchangeEventArgs, ExchangeFillEventArgs } from '@0xproject/contract-wrappers';
|
||||
import { assetDataUtils } from '@0xproject/order-utils';
|
||||
import { AssetProxyId, ERC721AssetData } from '@0xproject/types';
|
||||
import { BigNumber } from '@0xproject/utils';
|
||||
@@ -7,12 +7,12 @@ import * as R from 'ramda';
|
||||
|
||||
import { artifacts } from '../../artifacts';
|
||||
import { EventsResponse } from '../../data_sources/etherscan';
|
||||
import { ExchangeCancelEvent } from '../../entities/ExchangeCancelEvent';
|
||||
import { ExchangeFillEvent } from '../../entities/ExchangeFillEvent';
|
||||
|
||||
import { convertResponseToLogEntry, decodeLogEntry } from './event_utils';
|
||||
|
||||
// TODO(albrow): Union with other exchange event entity types
|
||||
export type ExchangeEventEntity = ExchangeFillEvent;
|
||||
export type ExchangeEventEntity = ExchangeFillEvent | ExchangeCancelEvent;
|
||||
|
||||
const exchangeContractAbi = artifacts.Exchange.compilerOutput.abi;
|
||||
|
||||
@@ -22,7 +22,7 @@ export function parseExchangeEvents(rawEventsResponse: EventsResponse): Exchange
|
||||
eventResponse => decodeLogEntry<ExchangeEventArgs>(exchangeContractAbi, eventResponse),
|
||||
logEntries,
|
||||
);
|
||||
const filteredLogEntries = R.filter(logEntry => R.contains(logEntry.event, ['Fill']), decodedLogEntries);
|
||||
const filteredLogEntries = R.filter(logEntry => R.contains(logEntry.event, ['Fill', 'Cancel']), decodedLogEntries);
|
||||
return R.map(_convertToEntity, filteredLogEntries);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ export function _convertToEntity(eventLog: LogWithDecodedArgs<ExchangeEventArgs>
|
||||
switch (eventLog.event) {
|
||||
case 'Fill':
|
||||
return _convertToExchangeFillEvent(eventLog as LogWithDecodedArgs<ExchangeFillEventArgs>);
|
||||
case 'Cancel':
|
||||
return _convertToExchangeCancelEvent(eventLog as LogWithDecodedArgs<ExchangeCancelEventArgs>);
|
||||
default:
|
||||
throw new Error('unexpected eventLog.event type: ' + eventLog.event);
|
||||
}
|
||||
@@ -67,6 +69,37 @@ export function _convertToExchangeFillEvent(eventLog: LogWithDecodedArgs<Exchang
|
||||
return exchangeFillEvent;
|
||||
}
|
||||
|
||||
export function _convertToExchangeCancelEvent(
|
||||
eventLog: LogWithDecodedArgs<ExchangeCancelEventArgs>,
|
||||
): ExchangeCancelEvent {
|
||||
const makerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.makerAssetData);
|
||||
const makerAssetType = makerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
|
||||
const takerAssetData = assetDataUtils.decodeAssetDataOrThrow(eventLog.args.takerAssetData);
|
||||
const takerAssetType = takerAssetData.assetProxyId === AssetProxyId.ERC20 ? 'erc20' : 'erc721';
|
||||
const exchangeCancelEvent = new ExchangeCancelEvent();
|
||||
exchangeCancelEvent.logIndex = eventLog.logIndex as number;
|
||||
exchangeCancelEvent.address = eventLog.address as string;
|
||||
exchangeCancelEvent.rawData = eventLog.data as string;
|
||||
exchangeCancelEvent.blockNumber = eventLog.blockNumber as number;
|
||||
exchangeCancelEvent.makerAddress = eventLog.args.makerAddress.toString();
|
||||
exchangeCancelEvent.takerAddress =
|
||||
eventLog.args.takerAddress == null ? null : eventLog.args.takerAddress.toString();
|
||||
exchangeCancelEvent.feeRecepientAddress = eventLog.args.feeRecipientAddress;
|
||||
exchangeCancelEvent.senderAddress = eventLog.args.senderAddress;
|
||||
exchangeCancelEvent.orderHash = eventLog.args.orderHash;
|
||||
exchangeCancelEvent.rawMakerAssetData = eventLog.args.makerAssetData;
|
||||
exchangeCancelEvent.makerAssetType = makerAssetType;
|
||||
exchangeCancelEvent.makerAssetProxyId = makerAssetData.assetProxyId;
|
||||
exchangeCancelEvent.makerTokenAddress = makerAssetData.tokenAddress;
|
||||
exchangeCancelEvent.makerTokenId = bigNumbertoStringOrNull((makerAssetData as ERC721AssetData).tokenId);
|
||||
exchangeCancelEvent.rawTakerAssetData = eventLog.args.takerAssetData;
|
||||
exchangeCancelEvent.takerAssetType = takerAssetType;
|
||||
exchangeCancelEvent.takerAssetProxyId = takerAssetData.assetProxyId;
|
||||
exchangeCancelEvent.takerTokenAddress = takerAssetData.tokenAddress;
|
||||
exchangeCancelEvent.takerTokenId = bigNumbertoStringOrNull((takerAssetData as ERC721AssetData).tokenId);
|
||||
return exchangeCancelEvent;
|
||||
}
|
||||
|
||||
function bigNumbertoStringOrNull(n: BigNumber): string | null {
|
||||
if (n == null) {
|
||||
return null;
|
||||
|
||||
32
packages/pipeline/src/entities/ExchangeCancelEvent.ts
Normal file
32
packages/pipeline/src/entities/ExchangeCancelEvent.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { BaseEntity, Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
import { AssetType } from '../types';
|
||||
|
||||
@Entity()
|
||||
export class ExchangeCancelEvent extends BaseEntity {
|
||||
@PrimaryColumn() public logIndex!: number;
|
||||
|
||||
@Column() public address!: string;
|
||||
@Column() public rawData!: string;
|
||||
@Column() public blockNumber!: number;
|
||||
|
||||
@Column() public makerAddress!: string;
|
||||
@Column({ nullable: true, type: String })
|
||||
public takerAddress!: string;
|
||||
@Column() public feeRecepientAddress!: string;
|
||||
@Column() public senderAddress!: string;
|
||||
@Column() public orderHash!: string;
|
||||
@Column() public rawMakerAssetData!: string;
|
||||
@Column() public makerAssetType!: AssetType;
|
||||
@Column() public makerAssetProxyId!: string;
|
||||
@Column() public makerTokenAddress!: string;
|
||||
@Column({ nullable: true, type: String })
|
||||
public makerTokenId!: string | null;
|
||||
@Column() public rawTakerAssetData!: string;
|
||||
@Column() public takerAssetType!: AssetType;
|
||||
@Column() public takerAssetProxyId!: string;
|
||||
@Column() public takerTokenAddress!: string;
|
||||
@Column({ nullable: true, type: String })
|
||||
public takerTokenId!: string | null;
|
||||
// TODO(albrow): Include topics?
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { BaseEntity, Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
export type ExchangeFillEventAssetType = 'erc20' | 'erc721';
|
||||
import { AssetType } from '../types';
|
||||
|
||||
@Entity()
|
||||
export class ExchangeFillEvent extends BaseEntity {
|
||||
@@ -20,13 +20,13 @@ export class ExchangeFillEvent extends BaseEntity {
|
||||
@Column() public takerFeePaid!: string;
|
||||
@Column() public orderHash!: string;
|
||||
@Column() public rawMakerAssetData!: string;
|
||||
@Column() public makerAssetType!: ExchangeFillEventAssetType;
|
||||
@Column() public makerAssetType!: AssetType;
|
||||
@Column() public makerAssetProxyId!: string;
|
||||
@Column() public makerTokenAddress!: string;
|
||||
@Column({ nullable: true, type: String })
|
||||
public makerTokenId!: string | null;
|
||||
@Column() public rawTakerAssetData!: string;
|
||||
@Column() public takerAssetType!: ExchangeFillEventAssetType;
|
||||
@Column() public takerAssetType!: AssetType;
|
||||
@Column() public takerAssetProxyId!: string;
|
||||
@Column() public takerTokenAddress!: string;
|
||||
@Column({ nullable: true, type: String })
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'reflect-metadata';
|
||||
import { createConnection } from 'typeorm';
|
||||
|
||||
import { Etherscan } from './data_sources/etherscan';
|
||||
import { ExchangeCancelEvent } from './entities/ExchangeCancelEvent';
|
||||
import { ExchangeFillEvent } from './entities/ExchangeFillEvent';
|
||||
import { config } from './ormconfig';
|
||||
|
||||
@@ -12,12 +13,16 @@ const EXCHANGE_ADDRESS = '0x4f833a24e1f95d70f028921e27040ca56e09ab0b';
|
||||
|
||||
(async () => {
|
||||
const connection = await createConnection(config);
|
||||
const repository = connection.getRepository(ExchangeFillEvent);
|
||||
console.log(`found ${await repository.count()} existing fill events`);
|
||||
const fillRepository = connection.getRepository(ExchangeFillEvent);
|
||||
const cancelRepository = connection.getRepository(ExchangeCancelEvent);
|
||||
console.log(`found ${await fillRepository.count()} existing fill events`);
|
||||
console.log(`found ${await cancelRepository.count()} existing cancel events`);
|
||||
const rawEvents = await etherscan.getContractEventsAsync(EXCHANGE_ADDRESS);
|
||||
const events = parseExchangeEvents(rawEvents);
|
||||
console.log(`got ${events.length} parsed events`);
|
||||
for (const event of events) {
|
||||
await event.save();
|
||||
}
|
||||
console.log(`now ${await repository.count()} total fill events`);
|
||||
console.log(`now ${await fillRepository.count()} total fill events`);
|
||||
console.log(`now ${await cancelRepository.count()} total cancel events`);
|
||||
})();
|
||||
|
||||
1
packages/pipeline/src/types.ts
Normal file
1
packages/pipeline/src/types.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type AssetType = 'erc20' | 'erc721';
|
||||
Reference in New Issue
Block a user