-
Notifications
You must be signed in to change notification settings - Fork 35
/
dftx.indexer.ts
127 lines (115 loc) · 4.5 KB
/
dftx.indexer.ts
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import { OP_DEFI_TX, OPCode } from '@defichain/jellyfish-transaction'
import { Indexer, RawBlock } from './_abstract'
import { toOPCodes } from '@defichain/jellyfish-transaction/dist/script/_buffer'
import { SmartBuffer } from 'smart-buffer'
import { AppointOracleIndexer } from './dftx/appoint.oracle'
import { RemoveOracleIndexer } from './dftx/remove.oracle'
import { UpdateOracleIndexer } from './dftx/update.oracle'
import { SetOracleDataIndexer } from './dftx/set.oracle.data'
import { SetOracleDataIntervalIndexer } from './dftx/set.oracle.data.interval'
import { CreateMasternodeIndexer } from './dftx/create.masternode'
import { ResignMasternodeIndexer } from './dftx/resign.masternode'
import { UpdateMasternodeIndexer } from './dftx/update.masternode'
import { Injectable, Logger } from '@nestjs/common'
import { DfTxIndexer, DfTxTransaction } from './dftx/_abstract'
import { PoolSwapIndexer } from './dftx/pool.swap'
import { CompositeSwapIndexer } from './dftx/composite.swap'
import { ActivePriceIndexer } from './dftx/active.price'
import { PlaceAuctionBidIndexer } from './dftx/place.auction.bid'
import { PoolSwapAggregatedIndexer } from './dftx/pool.swap.aggregated'
@Injectable()
export class MainDfTxIndexer extends Indexer {
private readonly logger = new Logger(MainDfTxIndexer.name)
private readonly indexers: Array<DfTxIndexer<any>>
constructor (
appointOracle: AppointOracleIndexer,
removeOracle: RemoveOracleIndexer,
updateOracle: UpdateOracleIndexer,
setOracleData: SetOracleDataIndexer,
setOracleDataInterval: SetOracleDataIntervalIndexer,
createMasternode: CreateMasternodeIndexer,
resignMasternode: ResignMasternodeIndexer,
updateMasternode: UpdateMasternodeIndexer,
poolSwapIndexer: PoolSwapIndexer,
compositeSwapIndexer: CompositeSwapIndexer,
poolSwapIntervalIndexer: PoolSwapAggregatedIndexer,
activePriceIndexer: ActivePriceIndexer,
placeAuctionBidIndexer: PlaceAuctionBidIndexer
) {
super()
this.indexers = [
appointOracle,
updateOracle,
removeOracle,
setOracleData,
setOracleDataInterval,
createMasternode,
resignMasternode,
updateMasternode,
poolSwapIndexer,
compositeSwapIndexer,
poolSwapIntervalIndexer,
activePriceIndexer,
placeAuctionBidIndexer
]
}
async index (block: RawBlock): Promise<void> {
for (const indexer of this.indexers) {
await indexer.indexBlockStart(block)
}
const transactions = this.getDfTxTransactions(block)
for (const transaction of transactions) {
const filtered = this.indexers.filter(value => transaction.dftx.type === value.OP_CODE)
for (const indexer of filtered) {
await indexer.indexTransaction(block, transaction)
}
}
for (const indexer of this.indexers) {
await indexer.indexBlockEnd(block)
}
}
async invalidate (block: RawBlock): Promise<void> {
// When invalidating reverse the order of block indexing
for (const indexer of this.indexers) {
await indexer.invalidateBlockEnd(block)
}
// Invalidate backwards
const transactions = this.getDfTxTransactions(block).reverse()
for (const transaction of transactions) {
const filtered = this.indexers.filter(value => transaction.dftx.type === value.OP_CODE).reverse()
for (const indexer of filtered) {
await indexer.invalidateTransaction(block, transaction)
}
}
for (const indexer of this.indexers) {
await indexer.invalidateBlockStart(block)
}
}
private getDfTxTransactions (block: RawBlock): Array<DfTxTransaction<any>> {
const transactions: Array<DfTxTransaction<any>> = []
for (let i = 0; i < block.tx.length; i++) {
const txn = block.tx[i]
for (const vout of txn.vout) {
if (!vout.scriptPubKey.asm.startsWith('OP_RETURN 44665478')) {
continue
}
try {
const stack: OPCode[] = toOPCodes(SmartBuffer.fromBuffer(Buffer.from(vout.scriptPubKey.hex, 'hex')))
if (stack[1].type !== 'OP_DEFI_TX') {
continue
}
transactions.push({
txn: txn,
txnNo: i,
dftx: (stack[1] as OP_DEFI_TX).tx
})
} catch (err) {
// TODO(fuxingloh): we can improve on this design by having separated indexing pipeline where
// a failed pipeline won't affect another indexer pipeline.
this.logger.error(`Failed to parse a DfTx Transaction with txid: ${txn.txid}`, err)
}
}
}
return transactions
}
}