Created
April 22, 2021 12:39
-
-
Save itoonx/4dbdea972231fbb0bf304cd883158e27 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* @Author: itoonx | |
* @Date: 2018-05-01 22:55:25 | |
* @Last Modified by: itoonx | |
* @Last Modified time: 2018-08-30 08:14:49 | |
*/ | |
const fs = require('fs') | |
const path = require('path') | |
const chalk = require('chalk') | |
const crypto = require('crypto') | |
const { web3, engine } = require('../../config/web3provider') | |
const WalletModel = require('../../api/wallet/wallet.model') | |
const TransactionModel = require('../../api/transaction/transaction.model') | |
const tokensConfig = JSON.parse(fs.readFileSync(path.join(__dirname, '../../../../shared/ethereum/abi/tokensConfig.json'))) | |
var listOfCurrencyBaseOnEther = ['ETH'] | |
tokensConfig.map((item) => { | |
listOfCurrencyBaseOnEther.push(item.symbol) | |
}) | |
/** | |
* @param {object} block - Ethereum block file from web socket | |
*/ | |
const parseAddressFromBlock = (block) => { | |
block.transactions.map( async (tx, index) => { | |
if (tx.to) { | |
try { | |
const blockNumber = Number.parseInt(tx.blockNumber.toString('hex'), 16) | |
const blockHash = tx.blockHash | |
const nonce = tx.nonce | |
const txHash = tx.hash | |
const senderAddress = tx.from | |
const recieverAddress = tx.to | |
const value = tx.value | |
const wallet = await WalletModel.findOne({ address: recieverAddress }) | |
if (wallet) { | |
let ctx = new TransactionModel({ | |
user_id: wallet.user_id, | |
currency_type: 'ETH', | |
block_hash: blockHash, | |
block_number: blockNumber, | |
tx_type: 'Deposit', | |
txhash: txHash, | |
from_address: senderAddress, | |
to_address: recieverAddress, | |
amount: Number.parseFloat(value.toString('hex'), 16) / 1e18, // Convert wei to ether by 18 decimal point | |
current_confirmation: 1, | |
sequence_hash: crypto.createHash('sha256').update(txHash, value + nonce).digest('base64'), | |
status: 'WaitingForConfirm' | |
}) | |
console.log(`ETH: Found Transaction in block #${txHash}`) | |
await ctx.save() | |
/** | |
* Add deposit pending here.... | |
* Fire data via socket.io | |
*/ | |
} | |
} catch (err) { | |
throw new Error(err) | |
} | |
} | |
}) | |
} | |
async function checkConfirmationAndUpdateBalance (block_number) { | |
let getBlockToConfirm = block_number - process.env.ETHEREUM_REQUIRED_CONFIRMATION | |
let context = { | |
status: 'WaitingForConfirm', | |
tx_type: 'Deposit', | |
currency_type: { $in: listOfCurrencyBaseOnEther }, | |
block_number: { $lt: block_number }, | |
} | |
let deposits = await TransactionModel.find(context) | |
// console.log('deposits', deposits) | |
for (let dptx of deposits) { | |
let dp = await TransactionModel.findById(dptx._id) | |
console.log('dp', dp) | |
// // ถ้า Block ปัจจุบัน - 16 แล้วยังไม่มากเท่า Block Number ของ TXID ที่เก็บเอาไว้ ให้อัพเดทจำนวน Confirm เฉยๆ | |
if (dptx.block_number > getBlockToConfirm) { | |
/** | |
* Update Confirmation | |
* - +=1 current_confirmation | |
* Fire data via socket.io | |
*/ | |
dp.current_confirmation += 1 | |
let save = await dp.save() | |
// ถ้ายอด Confirm เกิน 16 แล้วถือว่า Confirm | |
} else if (dptx.block_number <= getBlockToConfirm) { | |
/** | |
* Move balance pending to available | |
*/ | |
// let amount = dptx.amount | |
dp.current_confirmation += 1 | |
dp.status = 'Confirmed' | |
let save = await dp.save() | |
} | |
} | |
} | |
const watcherERC20TokenTransfer = async () => { | |
tokensConfig.forEach(tknConfig => { | |
if (tknConfig.enable === true && process.env.ETHEREUM_SERVER === tknConfig.network) { | |
console.log(`ERC20: ${tknConfig.tokenName} - Transfer Event Listening`) | |
// filter ethereum network for look up the event in token contract | |
web3.eth.filter({ | |
fromBlock: 'latest', // lastest block only | |
address: tknConfig.contractAddress, | |
topics:[ | |
web3.sha3(tknConfig.transferEvent) // Transfer Event | |
] | |
}).watch((err, incomingTx) => { | |
if (err) return err | |
let txHash = incomingTx.transactionHash | |
let blockNumber = incomingTx.blockNumber | |
let blockHash = incomingTx.blockHash | |
web3.eth.getTransactionReceipt(txHash, async (err, receipt) => { | |
if (err) return err | |
// if the transaction status = success | |
if (receipt) { | |
// console.log('receipt', receipt) | |
if (receipt.status != null || receipt.status != 'undefined') { | |
if (receipt.status === '0x1') { | |
const from_addr_with_0x = `0x${incomingTx.topics[1].slice(26)}` | |
const to_addr_with_0x = `0x${incomingTx.topics[2].slice(26)}` | |
const tokenAmount = Number.parseFloat( web3.toDecimal(incomingTx.data) / 10 ** tknConfig.decimals ) | |
// console.log(`ERC20: - From ${from_addr_with_0x} | To ${to_addr_with_0x} | Amount ${tokenAmount} ${tknConfig.symbol}`) | |
// console.log('globals.blockNumber', globals.blockNumber) | |
const wallet = await WalletModel.findOne({ address: to_addr_with_0x }) | |
if (wallet) { | |
let ctx = new TransactionModel({ | |
user_id: wallet.user_id, | |
currency_type: tknConfig.symbol, | |
block_hash: blockHash, | |
block_number: blockNumber, | |
tx_type: 'Deposit', | |
txhash: txHash, | |
from_address: from_addr_with_0x, | |
to_address: to_addr_with_0x, | |
amount: tokenAmount, | |
current_confirmation: 0, | |
sequence_hash: crypto.createHash('sha256').update(txHash, tokenAmount).digest('base64'), | |
status: 'WaitingForConfirm' | |
}) | |
console.log(`${tknConfig.symbol}: Found Transaction #${txHash} | Amount ${tokenAmount}`) | |
await ctx.save() | |
/** | |
* Add deposit pending here.... | |
* Fire data via socket.io | |
*/ | |
} | |
} | |
} | |
} | |
}) | |
}) | |
} | |
}) | |
} | |
const watchEthereumBlock = () => { | |
engine.on('block', async (block) => { | |
const blockNumber = Number.parseInt(block.number.toString('hex'), 16) | |
const blockHash = `0x${block.hash.toString('hex')}` | |
console.log(chalk.yellow('ETH: BLOCK CHANGED:', '#'+blockNumber, blockHash)) | |
parseAddressFromBlock(block) | |
checkConfirmationAndUpdateBalance(blockNumber) | |
}) | |
} | |
setTimeout(() => { | |
watchEthereumBlock() | |
watcherERC20TokenTransfer() | |
}, 100) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment