Skip to content

Commit

Permalink
feat: split tx service to multi files
Browse files Browse the repository at this point in the history
  • Loading branch information
classicalliu committed Jul 30, 2019
1 parent f78e1f4 commit 1dcf5e1
Show file tree
Hide file tree
Showing 7 changed files with 694 additions and 8 deletions.
8 changes: 0 additions & 8 deletions packages/neuron-wallet/src/services/transactions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { getConnection, In, ObjectLiteral } from 'typeorm'
import { ReplaySubject } from 'rxjs'
import {
OutPoint,
Transaction,
Expand Down Expand Up @@ -73,8 +72,6 @@ export enum SearchType {
/* eslint no-await-in-loop: "off" */
/* eslint no-restricted-syntax: "off" */
export default class TransactionsService {
public static txSentSubject = new ReplaySubject<{ transaction: TransactionWithoutHash; txHash: string }>(100)

public static filterSearchType = (value: string) => {
if (value === '') {
return SearchType.Empty
Expand Down Expand Up @@ -680,8 +677,3 @@ export default class TransactionsService {
return getConnection().manager.save(transactionEntity)
}
}

// listen to send tx event
TransactionsService.txSentSubject.subscribe(msg => {
TransactionsService.saveSentTx(msg.transaction, msg.txHash)
})
72 changes: 72 additions & 0 deletions packages/neuron-wallet/src/services/tx/failed-transaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { getConnection, In } from 'typeorm'
import { TransactionStatus } from '../../types/cell-types'
import OutputEntity from '../../database/chain/entities/output'
import TransactionEntity from '../../database/chain/entities/transaction'
import { OutputStatus } from './params'
import TransactionsService from './transaction-service'

export default class FailedTransaction {
public static pendings = async (): Promise<TransactionEntity[]> => {
const pendingTransactions = await getConnection()
.getRepository(TransactionEntity)
.createQueryBuilder('tx')
.where({
status: TransactionStatus.Pending,
})
.getMany()

return pendingTransactions
}

// update tx status to TransactionStatus.Failed
// update outputs status to OutputStatus.Failed
// update previous outputs (inputs) to OutputStatus.Live
public static updateFailedTxs = async (hashes: string[]) => {
const txs = await getConnection()
.getRepository(TransactionEntity)
.createQueryBuilder('tx')
.leftJoinAndSelect('tx.inputs', 'input')
.leftJoinAndSelect('tx.outputs', 'output')
.where({
hash: In(hashes),
status: TransactionStatus.Pending,
})
.getMany()

const txToUpdate = txs.map(tx => {
const transaction = tx
transaction.status = TransactionStatus.Failed
return transaction
})
const allOutputs = txs
.map(tx => tx.outputs)
.reduce((acc, val) => acc.concat(val), [])
.map(o => {
const output = o
output.status = OutputStatus.Failed
return output
})
const allInputs = txs.map(tx => tx.inputs).reduce((acc, val) => acc.concat(val), [])
const previousOutputs = await Promise.all(
allInputs.map(async input => {
const output = await getConnection()
.getRepository(OutputEntity)
.createQueryBuilder('output')
.where({
outPointTxHash: input.outPointTxHash,
outPointIndex: input.outPointIndex,
})
.getOne()
if (output) {
output.status = OutputStatus.Live
}
return output
})
)
const previous = previousOutputs.filter(output => output) as OutputEntity[]
await getConnection().manager.save([...txToUpdate, ...allOutputs, ...previous])
const blake160s = txs.map(tx => TransactionsService.blake160sOfTx(tx.toInterface()))
const uniqueBlake160s = [...new Set(blake160s.reduce((acc, val) => acc.concat(val), []))]
return uniqueBlake160s
}
}
72 changes: 72 additions & 0 deletions packages/neuron-wallet/src/services/tx/generate-transaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { TransactionWithoutHash, Cell, ScriptHashType } from '../../types/cell-types'
import CellsService, { MIN_CELL_CAPACITY } from '../cells'
import LockUtils from '../../models/lock-utils'
import { CapacityTooSmall } from '../../exceptions'
import { TargetOutput } from './params'

export default class GenerateTransaction {
// lockHashes for each inputs
public static generateTx = async (
lockHashes: string[],
targetOutputs: TargetOutput[],
changeAddress: string,
fee: string = '0'
): Promise<TransactionWithoutHash> => {
const { codeHash, outPoint } = await LockUtils.systemScript()

const needCapacities: bigint = targetOutputs
.map(o => BigInt(o.capacity))
.reduce((result, c) => result + c, BigInt(0))

const minCellCapacity = BigInt(MIN_CELL_CAPACITY)

const outputs: Cell[] = targetOutputs.map(o => {
const { capacity, address } = o

if (BigInt(capacity) < minCellCapacity) {
throw new CapacityTooSmall()
}

const blake160: string = LockUtils.addressToBlake160(address)

const output: Cell = {
capacity,
data: '0x',
lock: {
codeHash,
args: [blake160],
hashType: ScriptHashType.Data,
},
}

return output
})

const { inputs, capacities } = await CellsService.gatherInputs(needCapacities.toString(), lockHashes, fee)

// change
if (BigInt(capacities) > needCapacities + BigInt(fee)) {
const changeBlake160: string = LockUtils.addressToBlake160(changeAddress)

const output: Cell = {
capacity: `${BigInt(capacities) - needCapacities - BigInt(fee)}`,
data: '0x',
lock: {
codeHash,
args: [changeBlake160],
hashType: ScriptHashType.Data,
},
}

outputs.push(output)
}

return {
version: '0',
deps: [outPoint],
inputs,
outputs,
witnesses: [],
}
}
}
4 changes: 4 additions & 0 deletions packages/neuron-wallet/src/services/tx/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './transaction-service'
export * from './save-transaction'
export * from './generate-transaction'
export * from './failed-transaction'
17 changes: 17 additions & 0 deletions packages/neuron-wallet/src/services/tx/params.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export interface TargetOutput {
address: string
capacity: string
}

export enum TxSaveType {
Sent = 'sent',
Fetch = 'fetch',
}

export enum OutputStatus {
Sent = 'sent',
Live = 'live',
Pending = 'pending',
Dead = 'dead',
Failed = 'failed',
}
Loading

0 comments on commit 1dcf5e1

Please sign in to comment.