upgrade eslint, reformat code

This commit is contained in:
CounterFire2023 2024-01-17 19:19:02 +08:00
parent 36621a9206
commit 4b45ccfce3
26 changed files with 578 additions and 992 deletions

View File

@ -54,21 +54,20 @@
},
"devDependencies": {
"@types/dotenv": "^8.2.0",
"@types/node": "^14.14.20",
"@types/node": "^16.18.68",
"@types/node-fetch": "2.x",
"@types/node-schedule": "^2.1.0",
"@types/nodemailer": "^6.4.7",
"@types/redis": "^2.8.28",
"@typescript-eslint/eslint-plugin": "^4.25.0",
"@typescript-eslint/parser": "^4.25.0",
"eslint": "^7.27.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"prettier": "^2.3.0",
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"prettier": "^3.2.4",
"ts-node": "^10.9.1",
"ts-node-dev": "^2.0.0",
"tsconfig-paths": "^3.9.0",
"tslint": "^6.1.1",
"typescript": "^4.1.3"
"typescript": "^5.3.3"
}
}

View File

@ -1,4 +1,4 @@
import fetch, {Response} from "node-fetch"
import fetch, { Response } from 'node-fetch'
import { retry } from 'utils/promise.util'
// AbortController was added in node v14.17.0 globally
const AbortController = globalThis.AbortController
@ -6,13 +6,13 @@ const AbortController = globalThis.AbortController
const request = async (url: string, options: any) => {
const controller = new AbortController()
const timeout = setTimeout(() => controller.abort(), 30000)
let res: Response;
let res: Response
try {
res = await fetch(url, { ...options, signal: controller.signal })
clearTimeout(timeout)
} catch (err) {
clearTimeout(timeout)
throw err;
throw err
}
return res
}
@ -20,22 +20,21 @@ const request = async (url: string, options: any) => {
const requestChain = async (rpc: string, method: string, params: any) => {
const data = {
id: Date.now(),
jsonrpc: "2.0",
jsonrpc: '2.0',
method,
params
params,
}
return request(rpc, {
method: "POST",
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify(data)
})
.then((res) => res.json())
body: JSON.stringify(data),
}).then(res => res.json())
}
export const ethBlockNumber = async (rpc: string) => {
return requestChain(rpc, "eth_blockNumber", [])
return requestChain(rpc, 'eth_blockNumber', [])
}
export const retryEthBlockNumber = async (rpc: string) => {
@ -47,61 +46,58 @@ export const retryEthBlockNumber = async (rpc: string) => {
}
export const ethGetBlockByNumber = async (rpc: string, blockNumber: string) => {
return requestChain(rpc, "eth_getBlockByNumber", [blockNumber, true])
return requestChain(rpc, 'eth_getBlockByNumber', [blockNumber, true])
}
export const ethGetLogs = async (rpc: string, params: any) => {
return requestChain(rpc, "eth_getLogs", params)
return requestChain(rpc, 'eth_getLogs', params)
}
export const _batchEthBlocks = async (rpc: string, blockNumber: number, amount: number) => {
let batch = []
for (let i = 0; i < amount; i++) {
batch.push({
jsonrpc: "2.0",
method: "eth_getBlockByNumber",
params: ["0x" + (blockNumber + i).toString(16), true],
id: blockNumber + i
jsonrpc: '2.0',
method: 'eth_getBlockByNumber',
params: ['0x' + (blockNumber + i).toString(16), true],
id: blockNumber + i,
})
}
return request(rpc, {
method: "POST",
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify(batch)
})
.then((res) => res.json())
body: JSON.stringify(batch),
}).then(res => res.json())
}
export const batchEthBlocks = async (rpc: string, blockNumbers: number[]) => {
let batch = []
for (let blockNum of blockNumbers) {
batch.push({
jsonrpc: "2.0",
method: "eth_getBlockByNumber",
params: ["0x" + blockNum.toString(16), true],
id: blockNum
jsonrpc: '2.0',
method: 'eth_getBlockByNumber',
params: ['0x' + blockNum.toString(16), true],
id: blockNum,
})
}
return request(rpc, {
method: "POST",
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify(batch)
})
.then((res) => res.json())
body: JSON.stringify(batch),
}).then(res => res.json())
}
export const batchEthLogs = async (rpc: string, params: any) => {
return request(rpc, {
method: "POST",
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
'Content-Type': 'application/json; charset=utf-8',
},
body: JSON.stringify(params)
})
.then((res) => res.json())
body: JSON.stringify(params),
}).then(res => res.json())
}

View File

@ -5,7 +5,6 @@ import { CheckIn } from 'models/CheckIn'
import { NftHolder } from 'models/NftHolder'
import { getMonthBegin, getNDayAgo } from 'utils/date.util'
class TaskController extends BaseController {
@role('anon')
@router('post /task/check_in')
@ -18,23 +17,23 @@ class TaskController extends BaseController {
if (!limit) {
if (typeof days === 'number') {
let begin = getNDayAgo(days, true)
query.blockTime = {$gt: begin.getTime() / 1000 | 0}
query.blockTime = { $gt: (begin.getTime() / 1000) | 0 }
} else if (typeof days === 'string') {
if (days === '1month') {
let date = getMonthBegin(new Date())
query.blockTime = {$gt: date.getTime() / 1000 | 0}
query.blockTime = { $gt: (date.getTime() / 1000) | 0 }
} else {
query.dateTag = days
}
} else if (Array.isArray(days)) {
query.dateTag = {$in: days}
query.dateTag = { $in: days }
}
}
let records
if (limit) {
records = await CheckIn.find(query).sort({_id: -1}).limit(limit)
records = await CheckIn.find(query).sort({ _id: -1 }).limit(limit)
} else {
records = await CheckIn.find(query).sort({_id: -1})
records = await CheckIn.find(query).sort({ _id: -1 })
}
let result = []
for (let record of records) {
@ -50,7 +49,7 @@ class TaskController extends BaseController {
if (!address) {
throw new ZError(10, 'params mismatch')
}
const record = await CheckIn.findOne({from: address.toLowerCase()}).sort({count: -1})
const record = await CheckIn.findOne({ from: address.toLowerCase() }).sort({ count: -1 })
return record.toJson()
}
@ -64,7 +63,7 @@ class TaskController extends BaseController {
address = address.toLowerCase()
user = user.toLowerCase()
let records = await NftHolder.find({address, chain, user, burn: true }).sort({blockNumber: -1})
let records = await NftHolder.find({ address, chain, user, burn: true }).sort({ blockNumber: -1 })
let result = []
for (let record of records) {
result.push({
@ -74,7 +73,7 @@ class TaskController extends BaseController {
tokenId: record.tokenId,
})
}
return result;
return result
}
}
export default TaskController

View File

@ -14,13 +14,12 @@ import { IEventCfg } from 'interface/IEventCfg'
let svrs: any[] = []
let lock = false
async function initEventSvrs() {
const cfgMap: Map<IChain, IEventCfg[]> = new Map();
const cfgMap: Map<IChain, IEventCfg[]> = new Map()
for (let cfg of events) {
cfg.address = cfg.address.toLowerCase()
cfg.abi = require(`../config/event_abis/${cfg.abi}.json`)
const chainCfg = AllChains.find((chain) => chain.id === cfg.chain)
const chainCfg = AllChains.find(chain => chain.id === cfg.chain)
if (!chainCfg) {
logger.error('chainCfg not found: ' + cfg.chain)
process.exit(1)
@ -42,12 +41,12 @@ async function parseAllEvents() {
return
}
lock = true
logger.info('begin sync events: ' + svrs.map((svr) => svr.chainCfg.id).join(',') )
logger.info('begin sync events: ' + svrs.map(svr => svr.chainCfg.id).join(','))
for (let svr of svrs) {
try {
await svr.execute()
} catch (err) {
logger.info('sync events error:: chain: ' + svr.chainCfg.id )
logger.info('sync events error:: chain: ' + svr.chainCfg.id)
logger.info(err)
}
}
@ -63,5 +62,4 @@ async function parseAllEvents() {
parseAllEvents()
}, 10000)
parseAllEvents()
})();
})()

View File

@ -1,9 +1,9 @@
export interface IEventCfg {
address: string,
event: string,
abi: any,
fromBlock: number,
eventProcesser?: string,
chain: number,
topic?: string,
address: string
event: string
abi: any
fromBlock: number
eventProcesser?: string
chain: number
topic?: string
}

View File

@ -10,7 +10,7 @@ export enum FilterEnum {
like = 'like',
nlike = 'nlike',
isNull = 'isNull',
isNotNull = 'isNotNull'
isNotNull = 'isNotNull',
}
export enum FilterValueTypeEnum {
@ -19,20 +19,20 @@ export enum FilterValueTypeEnum {
boolean = 'boolean',
utf8_data = 'utf8_data',
hex_data = 'hex_data',
address = 'address'
address = 'address',
}
export interface IFilter {
key: string,
type: string,
value: string,
key: string
type: string
value: string
op: FilterEnum
}
export interface IScriptionCfg {
chain: number,
rpc?: string,
fromBlock: number,
filters?: IFilter[],
filter: (event: any) => boolean,
process: (event: any) => Promise<void>,
chain: number
rpc?: string
fromBlock: number
filters?: IFilter[]
filter: (event: any) => boolean
process: (event: any) => Promise<void>
}

View File

@ -14,11 +14,11 @@ export class BlockDataClass extends BaseModule {
@prop()
public chainId: number
@prop({ type: mongoose.Schema.Types.Mixed})
@prop({ type: mongoose.Schema.Types.Mixed })
public data: any
public static async saveBlock(event: any) {
return BlockData.insertOrUpdate({ hash: event.hash }, {data: event})
return BlockData.insertOrUpdate({ hash: event.hash }, { data: event })
}
}

View File

@ -7,8 +7,8 @@ import { logger } from '@typegoose/typegoose/lib/logSettings'
@dbconn()
@index({ from: 1 }, { unique: false })
@index({ hash: 1 }, { unique: true })
@index({ from: 1, dateTag: 1}, { unique: true })
@index({ from: 1, blockTime: 1}, { unique: false })
@index({ from: 1, dateTag: 1 }, { unique: true })
@index({ from: 1, blockTime: 1 }, { unique: false })
@modelOptions({
schemaOptions: { collection: 'check_in_event', timestamps: true },
})
@ -28,7 +28,7 @@ export class CheckInClass extends BaseModule {
@prop()
public dateTag: string
// 连签天数
@prop({default: 0})
@prop({ default: 0 })
public count: number
@prop()
public value: string
@ -36,7 +36,7 @@ export class CheckInClass extends BaseModule {
public input: string
public static async saveEvent(event: any) {
const preDay = formatDate(yesterday());
const preDay = formatDate(yesterday())
const preDayEvent = await CheckIn.findOne({ from: event.from, dateTag: preDay })
if (preDayEvent) {
event.count = preDayEvent.count + 1
@ -49,12 +49,12 @@ export class CheckInClass extends BaseModule {
}
public toJson() {
return {
address: this.from,
day: this.dateTag,
time: this.blockTime,
count: this.count
}
return {
address: this.from,
day: this.dateTag,
time: this.blockTime,
count: this.count,
}
}
}

View File

@ -5,7 +5,7 @@ import { TokenHolder } from './TokenHolder'
@dbconn()
@index({ address: 1 }, { unique: false })
@index({ chain: 1, hash: 1, logIndex: 1}, { unique: true })
@index({ chain: 1, hash: 1, logIndex: 1 }, { unique: true })
@modelOptions({
schemaOptions: { collection: 'ft_transfer_event', timestamps: true },
})
@ -60,7 +60,7 @@ export class FtTransferEventClass extends BaseModule {
$inc: { version: 1 },
}
let record = await FtTransferEvent.insertOrUpdate({ hash, logIndex, chain: event.chain }, data)
let record = await FtTransferEvent.insertOrUpdate({ hash, logIndex, chain: event.chain }, data)
await TokenHolder.saveData(record)
}
}

View File

@ -4,7 +4,7 @@ import { BaseModule } from './Base'
import { NftHolder } from './NftHolder'
@dbconn()
@index({ chain: 1, hash: 1, logIndex: 1}, { unique: true })
@index({ chain: 1, hash: 1, logIndex: 1 }, { unique: true })
@modelOptions({
schemaOptions: { collection: 'general_event', timestamps: true },
options: { allowMixed: Severity.ALLOW },
@ -28,7 +28,7 @@ export class GeneralEventClass extends BaseModule {
@prop()
public removed: boolean
@prop({ type: mongoose.Schema.Types.Mixed})
@prop({ type: mongoose.Schema.Types.Mixed })
public decodedData: any
@prop()
@ -36,7 +36,6 @@ export class GeneralEventClass extends BaseModule {
@prop({ default: 0 })
public version: number
public static async saveEvent(event: any) {
const logIndex = parseInt(event.logIndex || '0')
const hash = event.hash || event.transactionHash
@ -50,7 +49,7 @@ export class GeneralEventClass extends BaseModule {
$inc: { version: 1 },
}
let record = await GeneralEvent.insertOrUpdate({ hash, logIndex, chain: event.chain }, data)
let record = await GeneralEvent.insertOrUpdate({ hash, logIndex, chain: event.chain }, data)
return record
}
}

View File

@ -21,14 +21,14 @@ export class NftHolderClass extends BaseModule {
public blockNumber: number
@prop()
public user: string
@prop({default: false})
@prop({ default: false })
public burn: boolean
public static async parseEvent(event: typeof GeneralEvent) {
const address = event.address.toLowerCase();
const chain = event.chain;
const tokenId = event.decodedData.tokenId;
const blockNumer = event.blockNumber;
const address = event.address.toLowerCase()
const chain = event.chain
const tokenId = event.decodedData.tokenId
const blockNumer = event.blockNumber
const burn = event.decodedData.to === ZERO_ADDRESS
let user = (burn ? event.decodedData.from : event.decodedData.to).toLowerCase()
user = user.toLowerCase()
@ -42,7 +42,7 @@ export class NftHolderClass extends BaseModule {
record.blockNumber = blockNumer
}
}
await record.save();
await record.save()
}
}

View File

@ -4,13 +4,12 @@ import { BaseModule } from './Base'
import logger from 'logger/logger'
import { GeneralEvent } from './GeneralEvent'
const STAKE_EVENT = 'Staked'
const REDEEM_EVENT = 'Redeem'
@dbconn()
@index({ chain: 1, nft: 1, tokenId: 1, start: 1 }, { unique: true })
@index({ chain:1, user: 1, nft: 1}, {unique: false})
@index({ chain: 1, nft: 1, tokenId: 1, start: 1 }, { unique: true })
@index({ chain: 1, user: 1, nft: 1 }, { unique: false })
@modelOptions({
schemaOptions: { collection: 'nft_stake_info', timestamps: true },
})
@ -42,7 +41,6 @@ export class NftStakeClass extends BaseModule {
@prop({ default: 0 })
public version: number
/**
*
{
@ -84,21 +82,22 @@ export class NftStakeClass extends BaseModule {
blockNumber,
status: 1,
start,
stakeTime
stakeTime,
})
await record.save()
} else {
logger.info(`redeem nft: ${nft}, tokenId: ${tokenId}, user: ${user}, blockNumber: ${blockNumber}`)
await NftStake.insertOrUpdate(
{ chain, nft, tokenId, start},
{ chain, nft, tokenId, start },
{
status: 2,
address,
user,
redeemTime: Date.now() / 1000 | 0,
redeemTime: (Date.now() / 1000) | 0,
blockNumber,
$inc: { version: 1 },
})
},
)
}
}
}

View File

@ -6,7 +6,7 @@ import { NftHolder } from './NftHolder'
@dbconn()
@index({ chain: 1, address: 1, tokenId: 1 }, { unique: false })
@index({ chain: 1, address: 1, from: 1, to: 1 }, { unique: false })
@index({ chain: 1, hash: 1, logIndex: 1}, { unique: true })
@index({ chain: 1, hash: 1, logIndex: 1 }, { unique: true })
@modelOptions({
schemaOptions: { collection: 'nft_transfer_event', timestamps: true },
})
@ -58,7 +58,7 @@ export class NftTransferEventClass extends BaseModule {
$inc: { version: 1 },
}
await NftTransferEvent.insertOrUpdate({ hash, logIndex, chain: event.chain }, data)
await NftTransferEvent.insertOrUpdate({ hash, logIndex, chain: event.chain }, data)
}
}

View File

@ -10,7 +10,6 @@ import { ZERO_ADDRESS } from 'common/Constants'
schemaOptions: { collection: 'token_holder', timestamps: true },
})
export class TokenHolderClass extends BaseModule {
@prop({ required: true })
public chain: string
@ -26,11 +25,10 @@ export class TokenHolderClass extends BaseModule {
@prop()
public blockNumber: number
public static async parseEvent(event: typeof GeneralEvent) {
const address = event.address.toLowerCase();
const chain = event.chain;
const blockNumber = event.blockNumber;
const address = event.address.toLowerCase()
const chain = event.chain
const blockNumber = event.blockNumber
let { from, to, value } = event.decodedData
from = from.toLowerCase()
to = to.toLowerCase()
@ -40,7 +38,7 @@ export class TokenHolderClass extends BaseModule {
record.amount = BigInt(record.amount) - BigInt(value)
record.blockNumber = blockNumber
}
await record.save();
await record.save()
}
if (to !== ZERO_ADDRESS) {
let record = await TokenHolder.findOne({ address, chain, user: to })
@ -50,7 +48,7 @@ export class TokenHolderClass extends BaseModule {
record.amount = BigInt(record.amount) + BigInt(value)
record.blockNumber = blockNumber
}
await record.save();
await record.save()
}
}
}

View File

@ -17,7 +17,7 @@ let eventProcessers = {
FtTransferEvent: FtTransferEvent,
}
const events = require('config/events.json')
const events = require('../config/events.json')
async function initEventSvrs() {
for (let event of events) {

View File

@ -20,7 +20,7 @@ let eventProcessers = {
}
async function initEventSvrs() {
const cfgMap: Map<IChain, IScriptionCfg[]> = new Map();
const cfgMap: Map<IChain, IScriptionCfg[]> = new Map()
for (let cfg of scriptions) {
if (!cfg.filter && cfg.filters) {
cfg.filter = buildScriptionFilters(cfg)
@ -33,7 +33,7 @@ async function initEventSvrs() {
}
await processer.saveEvent(event)
}
const chainCfg = AllChains.find((chain) => chain.id === cfg.chain)
const chainCfg = AllChains.find(chain => chain.id === cfg.chain)
if (!chainCfg) {
logger.error('chainCfg not found: ' + cfg.chain)
process.exit(1)
@ -55,12 +55,12 @@ async function parseAllEvents() {
return
}
lock = true
logger.info('begin sync block: ' + svrs.map((svr) => svr.chainCfg.id).join(','))
logger.info('begin sync block: ' + svrs.map(svr => svr.chainCfg.id).join(','))
for (let svr of svrs) {
try {
await svr.execute()
} catch (err) {
logger.info('sync block with error:: chain: ' + svr.chainCfg.id )
logger.info('sync block with error:: chain: ' + svr.chainCfg.id)
logger.info(err)
}
}
@ -76,5 +76,4 @@ async function parseAllEvents() {
parseAllEvents()
}, 20000)
parseAllEvents()
})();
})()

View File

@ -1,11 +1,10 @@
import { IChain } from "chain/allchain";
import { retryEthBlockNumber } from "chain/chain.api";
import { IScriptionCfg } from "interface/IScriptionCfg";
import logger from "logger/logger";
import { RedisClient } from "redis/RedisClient";
import { getPastBlocksIter } from "utils/block.util";
import { formatDate } from "utils/date.util";
import { IChain } from 'chain/allchain'
import { retryEthBlockNumber } from 'chain/chain.api'
import { IScriptionCfg } from 'interface/IScriptionCfg'
import logger from 'logger/logger'
import { RedisClient } from 'redis/RedisClient'
import { getPastBlocksIter } from 'utils/block.util'
import { formatDate } from 'utils/date.util'
export class BlockSyncSvr {
chainCfg: IChain
@ -13,9 +12,9 @@ export class BlockSyncSvr {
fromBlock: number = Number.MAX_SAFE_INTEGER
batchCount: number = 0
redisKey = ''
rpc = '';
rpc = ''
constructor(_chainCfg: IChain, _scriptionCfgs: IScriptionCfg[]) {
this.chainCfg =_chainCfg
this.chainCfg = _chainCfg
this.scriptionCfgs = _scriptionCfgs
this.rpc = _chainCfg.rpc.split('|')[0]
for (let cfg of _scriptionCfgs) {
@ -28,22 +27,22 @@ export class BlockSyncSvr {
}
async execute() {
let currentBlock = await retryEthBlockNumber(this.rpc)
let blockStr = await new RedisClient().get(this.redisKey)
if (blockStr) {
this.fromBlock = Math.max(parseInt(blockStr), this.fromBlock)
}
this.batchCount = parseInt(currentBlock.result, 16) - this.fromBlock
if (this.batchCount <= 0) {
return
}
let blocks = getPastBlocksIter({
chainId: this.chainCfg.id,
rpc: this.rpc,
fromBlock: this.fromBlock,
amount: this.batchCount
})
await this.processBlockDatas(blocks)
let currentBlock = await retryEthBlockNumber(this.rpc)
let blockStr = await new RedisClient().get(this.redisKey)
if (blockStr) {
this.fromBlock = Math.max(parseInt(blockStr), this.fromBlock)
}
this.batchCount = parseInt(currentBlock.result, 16) - this.fromBlock
if (this.batchCount <= 0) {
return
}
let blocks = getPastBlocksIter({
chainId: this.chainCfg.id,
rpc: this.rpc,
fromBlock: this.fromBlock,
amount: this.batchCount,
})
await this.processBlockDatas(blocks)
}
async processBlockDatas(iterator: any) {
@ -57,15 +56,15 @@ export class BlockSyncSvr {
continue
}
for (let i = 0; i < block.transactions.length; i++) {
const tx = block.transactions[i];
const tx = block.transactions[i]
if (block.timestamp) {
tx.blockTime = parseInt(block.timestamp, 16);
tx.dateTag = formatDate(new Date(tx.blockTime * 1000));
tx.blockTime = parseInt(block.timestamp, 16)
tx.dateTag = formatDate(new Date(tx.blockTime * 1000))
}
for (let j = 0; j < this.scriptionCfgs.length; j++) {
const cfg = this.scriptionCfgs[j];
const cfg = this.scriptionCfgs[j]
if (cfg.filter && cfg.filter(tx) ) {
if (cfg.filter && cfg.filter(tx)) {
try {
await cfg.process(tx)
} catch (err) {

View File

@ -1,20 +1,20 @@
import { IChain } from "chain/allchain";
import { batchEthLogs, ethGetLogs, retryEthBlockNumber } from "chain/chain.api";
import logger from "logger/logger";
import { GeneralEvent } from "models/GeneralEvent";
import { IChain } from 'chain/allchain'
import { batchEthLogs, ethGetLogs, retryEthBlockNumber } from 'chain/chain.api'
import logger from 'logger/logger'
import { GeneralEvent } from 'models/GeneralEvent'
import { RedisClient } from "redis/RedisClient";
import { decodeEvent, getTopics } from "utils/event.util";
import { RedisClient } from 'redis/RedisClient'
import { decodeEvent, getTopics } from 'utils/event.util'
import { NftHolder } from 'models/NftHolder'
import { TokenHolder } from 'models/TokenHolder'
import { NftStake } from 'models/NftStake'
import { IEventCfg } from "interface/IEventCfg";
import { IEventCfg } from 'interface/IEventCfg'
let eventProcessers = {
NftHolder: NftHolder,
TokenHolder: TokenHolder,
NftStake: NftStake
NftStake: NftStake,
}
export class EventBatchSvr {
@ -23,9 +23,9 @@ export class EventBatchSvr {
processer: Map<string, IEventCfg> = new Map()
fromBlock: number = Number.MAX_SAFE_INTEGER
redisKey = ''
rpc = '';
rpc = ''
constructor(_chainCfg: IChain, _eventCfgs: IEventCfg[]) {
this.chainCfg =_chainCfg
this.chainCfg = _chainCfg
this.eventCfgs = _eventCfgs
this.rpc = _chainCfg.rpc.split('|')[0]
for (let cfg of this.eventCfgs) {
@ -33,82 +33,81 @@ export class EventBatchSvr {
if (!cfg.topic) {
cfg.topic = getTopics(cfg)
}
this.processer.set((cfg.address+cfg.topic).toLowerCase(), cfg)
this.processer.set((cfg.address + cfg.topic).toLowerCase(), cfg)
}
this.eventCfgs.sort((a, b) => a.topic.localeCompare(b.topic))
this.redisKey = `event_${this.chainCfg.id}`
}
async execute() {
let currentBlock = await retryEthBlockNumber(this.rpc)
let toBlock = parseInt(currentBlock.result, 16)
let blockStr = await new RedisClient().get(this.redisKey)
if (blockStr) {
this.fromBlock = Math.max(parseInt(blockStr), this.fromBlock)
}
logger.info(`sync events with chain: ${this.chainCfg.id}, from: ${this.fromBlock}, to: ${toBlock}`)
let params = []
let uninParams = []
let topicsSet = new Set()
for (let cfg of this.eventCfgs) {
await this.fixBlockNumber(cfg);
if (cfg.fromBlock != this.fromBlock) {
let _param = this.buildQueryParams(cfg, toBlock)
params.push(_param)
let currentBlock = await retryEthBlockNumber(this.rpc)
let toBlock = parseInt(currentBlock.result, 16)
let blockStr = await new RedisClient().get(this.redisKey)
if (blockStr) {
this.fromBlock = Math.max(parseInt(blockStr), this.fromBlock)
}
logger.info(`sync events with chain: ${this.chainCfg.id}, from: ${this.fromBlock}, to: ${toBlock}`)
let params = []
let uninParams = []
let topicsSet = new Set()
for (let cfg of this.eventCfgs) {
await this.fixBlockNumber(cfg)
if (cfg.fromBlock != this.fromBlock) {
let _param = this.buildQueryParams(cfg, toBlock)
params.push(_param)
} else {
let _param = uninParams[uninParams.length - 1]
if (!_param || !topicsSet.has(cfg.topic)) {
_param = this.buildQueryParams(cfg, toBlock)
uninParams.push(_param)
topicsSet = new Set()
topicsSet.add(cfg.topic)
} else {
let _param = uninParams[uninParams.length - 1]
if (!_param || !topicsSet.has(cfg.topic)) {
_param = this.buildQueryParams(cfg, toBlock)
uninParams.push(_param)
topicsSet = new Set()
if (!topicsSet.has(cfg.topic)) {
_param.params[0].topics.push(cfg.topic)
topicsSet.add(cfg.topic)
} else {
if (!topicsSet.has(cfg.topic)) {
_param.params[0].topics.push(cfg.topic)
topicsSet.add(cfg.topic)
}
_param.params[0].address.push(cfg.address)
}
_param.params[0].address.push(cfg.address)
}
}
let nextBlock = this.fromBlock
if (uninParams.length > 1) {
logger.debug(`unin params: ${uninParams.length}`)
let results = await batchEthLogs(this.rpc, uninParams)
for (let i = 0; i < results.length; i++) {
if (results[i].error) {
throw results[i].error
}
let events = results[i].result
await this.processEvents(events)
}
let nextBlock = this.fromBlock
if (uninParams.length > 1) {
logger.debug(`unin params: ${uninParams.length}`)
let results = await batchEthLogs(this.rpc, uninParams)
for (let i = 0; i < results.length; i++) {
if (results[i].error) {
throw results[i].error
}
} else if (uninParams.length == 1) {
logger.debug(`unin params length 1, use eth_getLogs`)
let result = await ethGetLogs(this.rpc, uninParams[0].params)
if (result.error) {
throw result.error
let events = results[i].result
await this.processEvents(events)
}
} else if (uninParams.length == 1) {
logger.debug(`unin params length 1, use eth_getLogs`)
let result = await ethGetLogs(this.rpc, uninParams[0].params)
if (result.error) {
throw result.error
}
await this.processEvents(result.result)
}
if (params.length > 0) {
logger.debug(`params: ${params.length}`)
let results = await batchEthLogs(this.rpc, params)
for (let i = 0; i < results.length; i++) {
if (results[i].error) {
throw results[i].error
}
await this.processEvents(result.result)
let events = results[i].result
await this.processEvents(events)
}
if (params.length > 0) {
logger.debug(`params: ${params.length}`)
let results = await batchEthLogs(this.rpc, params)
for (let i = 0; i < results.length; i++) {
if (results[i].error) {
throw results[i].error
}
let events = results[i].result
await this.processEvents(events)
}
}
nextBlock = toBlock + 1;
for (let cfg of this.eventCfgs) {
cfg.fromBlock = nextBlock
const redisKey = this.buildRedisKey(cfg)
await new RedisClient().set(redisKey, cfg.fromBlock + '')
}
await new RedisClient().set(this.redisKey, nextBlock + '')
}
nextBlock = toBlock + 1
for (let cfg of this.eventCfgs) {
cfg.fromBlock = nextBlock
const redisKey = this.buildRedisKey(cfg)
await new RedisClient().set(redisKey, cfg.fromBlock + '')
}
await new RedisClient().set(this.redisKey, nextBlock + '')
}
buildRedisKey(cfg: IEventCfg) {
@ -127,14 +126,14 @@ export class EventBatchSvr {
const params: any = {
fromBlock: '0x' + cfg.fromBlock.toString(16),
toBlock: toBlock ? '0x' + toBlock?.toString(16) : 'latest',
address: [cfg.address]
address: [cfg.address],
}
params.topics = [cfg.topic]
const result = {
jsonrpc: "2.0",
method: "eth_getLogs",
jsonrpc: '2.0',
method: 'eth_getLogs',
params: [params],
id: `${cfg.address}_${cfg.event}`
id: `${cfg.address}_${cfg.event}`,
}
return result
}
@ -148,13 +147,13 @@ export class EventBatchSvr {
for (const event of events) {
const address = events[0].address
const topic = events[0].topics[0]
const cfg = this.processer.get((address+topic).toLowerCase())
const cfg = this.processer.get((address + topic).toLowerCase())
if (!cfg) {
continue;
continue
}
event.chain = this.chainCfg.id + ''
event.event = cfg.event
let result = decodeEvent(cfg, event);
let result = decodeEvent(cfg, event)
// cfg.fromBlock = Math.max (parseInt(event.blockNumber, 16) + 1, cfg.fromBlock)
event.decodedData = result
const record = await GeneralEvent.saveEvent(event)

View File

@ -1,27 +1,50 @@
import { batchEthBlocks } from "chain/chain.api";
import { IScriptionCfg } from "interface/IScriptionCfg";
import logger from "logger/logger";
import { RedisClient } from "redis/RedisClient";
import { utf8ToHex } from "./string.util";
import { batchEthBlocks } from 'chain/chain.api'
import { IScriptionCfg } from 'interface/IScriptionCfg'
import logger from 'logger/logger'
import { RedisClient } from 'redis/RedisClient'
import { utf8ToHex } from './string.util'
const MAX_BATCH_AMOUNT = +process.env.MAX_BLOCK_BATCH_AMOUNT
const REQUEST_INTERVAL = 0.5 * 1000
export async function divQueryPassBlocks({chainId, rpc, fromBlock, amount}
: {chainId: number, rpc: string, fromBlock: number, amount: number}) {
export async function divQueryPassBlocks({
chainId,
rpc,
fromBlock,
amount,
}: {
chainId: number
rpc: string
fromBlock: number
amount: number
}) {
const middleBlock = fromBlock + Math.floor(amount / 2)
const firstBlocks = await getPastBlocks({chainId, rpc, fromBlock, amount: middleBlock - fromBlock})
const secondBlocks = await getPastBlocks({chainId, rpc, fromBlock: middleBlock, amount: amount - (middleBlock - fromBlock)})
const firstBlocks = await getPastBlocks({ chainId, rpc, fromBlock, amount: middleBlock - fromBlock })
const secondBlocks = await getPastBlocks({
chainId,
rpc,
fromBlock: middleBlock,
amount: amount - (middleBlock - fromBlock),
})
return [...firstBlocks, ...secondBlocks]
}
export async function getPastBlocks({chainId, rpc, fromBlock, amount}
: {chainId: number, rpc: string, fromBlock: number, amount: number}) {
export async function getPastBlocks({
chainId,
rpc,
fromBlock,
amount,
}: {
chainId: number
rpc: string
fromBlock: number
amount: number
}) {
let blocks = []
logger.info(`chain: ${chainId} from: ${fromBlock} amount: ${amount}`)
let blockNumber = fromBlock
const redisKey = `blocknum_${chainId}`
let retryCount = 0;
let retryCount = 0
const parseBlocksAndRetry = async (blockNums: number[]) => {
let records = await batchEthBlocks(rpc, blockNums)
if (records.error) {
@ -31,7 +54,7 @@ export async function getPastBlocks({chainId, rpc, fromBlock, amount}
let retryNums: number[] = []
let maxBlockNumber = 0
for (let i = 0; i < records.length; i++) {
const block = records[i].result;
const block = records[i].result
if (block?.hash) {
blocks.push(block)
realAmount++
@ -40,21 +63,20 @@ export async function getPastBlocks({chainId, rpc, fromBlock, amount}
if (block) {
logger.warn(`block ${blockNumber + i}: ${block}`)
} else {
logger.warn(`block ${blockNumber + i} is null`)
retryNums.push(blockNumber + i)
}
}
}
if (retryNums.length > 0 && ++retryCount < 3) {
logger.info(`${retryCount} retry ${retryNums.length} blocks`)
if (retryNums.length > 0 && ++retryCount < 5) {
logger.info(`${retryCount} retry: ${retryNums.join(', ')}`)
const retryBlocks = await parseBlocksAndRetry(retryNums)
realAmount += retryBlocks
}
return realAmount
}
try {
const numsArr = Array.from({length: amount}, (v, k) => k + blockNumber)
const realAmount = await parseBlocksAndRetry(numsArr)
const numsArr = Array.from({ length: amount }, (v, k) => k + blockNumber)
await parseBlocksAndRetry(numsArr)
if (retryCount > 0) {
blocks.sort((a, b) => parseInt(a.number) - parseInt(b.number))
}
@ -63,31 +85,39 @@ export async function getPastBlocks({chainId, rpc, fromBlock, amount}
} catch (e) {
logger.log(e.message || e)
if (e.message && /Too Many Requests/.test(e.message) && amount > 1) {
blocks = await divQueryPassBlocks({chainId, rpc, fromBlock, amount})
blocks = await divQueryPassBlocks({ chainId, rpc, fromBlock, amount })
} else if (e.message && /Public RPC Rate Limit Hit, limit will reset in \d+ seconds/.test(e.message)) {
const match = e.message.match(/Public RPC Rate Limit Hit, limit will reset in (\d+) seconds/)
const seconds = parseInt(match[1])
await new Promise(resolve => setTimeout(resolve, seconds * 1000))
blocks = await getPastBlocks({chainId, rpc, fromBlock, amount})
}else {
blocks = await getPastBlocks({ chainId, rpc, fromBlock, amount })
} else {
throw e
}
}
return blocks
}
export function* getPastBlocksIter({chainId, rpc, fromBlock, amount}
: {chainId: number, rpc: string, fromBlock: number, amount: number}) {
export function* getPastBlocksIter({
chainId,
rpc,
fromBlock,
amount,
}: {
chainId: number
rpc: string
fromBlock: number
amount: number
}) {
logger.info(`chain: ${chainId} from: ${fromBlock} amount: ${amount}`)
let remain = amount
while (remain > 0) {
yield getPastBlocks({chainId, rpc, fromBlock, amount: Math.min(MAX_BATCH_AMOUNT, remain)})
yield getPastBlocks({ chainId, rpc, fromBlock, amount: Math.min(MAX_BATCH_AMOUNT, remain) })
fromBlock += MAX_BATCH_AMOUNT
remain -= MAX_BATCH_AMOUNT
}
}
export const buildScriptionFilters = (cfg: IScriptionCfg) => {
if (cfg.filter) {
return cfg.filter
@ -144,7 +174,7 @@ export const buildScriptionFilters = (cfg: IScriptionCfg) => {
} else if (filter.type === 'utf8_data') {
value = `'0x${utf8ToHex(value)}'`
} else if (filter.type === 'hex_data') {
value = `'${value.indexOf('0x') === 0 ? value : '0x'+value}'`
value = `'${value.indexOf('0x') === 0 ? value : '0x' + value}'`
} else if (filter.type === 'number') {
value = parseInt(value)
} else if (filter.type === 'boolean') {

View File

@ -1,39 +1,39 @@
// format the date to the format we want
export const formatDate = (date: Date): string => {
const year = date.getFullYear();
const month = (date.getMonth() + 1 + '').padStart(2, '0');
const day = (date.getDate() + '').padStart(2, '0');
return `${year}${month}${day}`;
};
const year = date.getFullYear()
const month = (date.getMonth() + 1 + '').padStart(2, '0')
const day = (date.getDate() + '').padStart(2, '0')
return `${year}${month}${day}`
}
// get begin of one day
export const getDayBegin = (date: Date): Date => {
const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate();
return new Date(year, month, day);
};
const year = date.getFullYear()
const month = date.getMonth()
const day = date.getDate()
return new Date(year, month, day)
}
// get begin of n day ago
export const getNDayAgo = (n: number, begin: boolean): Date => {
const date = new Date(Date.now() - n * 24 * 60 * 60 * 1000)
if (begin) {
return getDayBegin(date);
return getDayBegin(date)
} else {
return date;
return date
}
};
}
// get begin of this month
export const getMonthBegin = (date: Date): Date => {
const year = date.getFullYear();
const month = date.getMonth();
return new Date(year, month, 1);
const year = date.getFullYear()
const month = date.getMonth()
return new Date(year, month, 1)
}
// get formated datestring of yesterday
export const yesterday = () => {
const date = new Date();
date.setDate(date.getDate() - 1);
return date;
};
const date = new Date()
date.setDate(date.getDate() - 1)
return date
}

View File

@ -1,8 +1,7 @@
//@ts-ignore
import { keccak256, _jsonInterfaceMethodToString, AbiInput } from "web3-utils";
import web3abi from 'web3-eth-abi';
import { IEventCfg } from "interface/IEventCfg";
import { keccak256, _jsonInterfaceMethodToString, AbiInput } from 'web3-utils'
import web3abi from 'web3-eth-abi'
import { IEventCfg } from 'interface/IEventCfg'
export const getTopics = (cfg: IEventCfg) => {
// let abi = cfg.abi
@ -12,21 +11,21 @@ export const getTopics = (cfg: IEventCfg) => {
// }
// topic = topic.slice(0, -1)
// topic += ')'
return keccak256(_jsonInterfaceMethodToString(cfg.abi))
return keccak256(_jsonInterfaceMethodToString(cfg.abi))
}
export const decodeEvent = (cfg: IEventCfg, eventData: {data: string, topics: string[]}) => {
const abiInputs = cfg.abi.inputs;
let result = web3abi.decodeLog(abiInputs, eventData.data, eventData.topics.slice(1));
export const decodeEvent = (cfg: IEventCfg, eventData: { data: string; topics: string[] }) => {
const abiInputs = cfg.abi.inputs
let result = web3abi.decodeLog(abiInputs, eventData.data, eventData.topics.slice(1))
let decodedData: any = {}
for (let i = 0; i < abiInputs.length; i++) {
const input: AbiInput = abiInputs[i];
const input: AbiInput = abiInputs[i]
if (input.type === 'tuple[]') {
// @ts-ignore
decodedData[input.name] = result[i].map(item => {
let itemData = {}
for (let j = 0; j < input.components.length; j++) {
const component = input.components[j];
const component = input.components[j]
itemData[component.name] = item[j]
}
return itemData
@ -34,7 +33,7 @@ export const decodeEvent = (cfg: IEventCfg, eventData: {data: string, topics: st
} else if (input.type === 'tuple') {
let itemData = {}
for (let j = 0; j < input.components.length; j++) {
const component = input.components[j];
const component = input.components[j]
itemData[component.name] = result[i][j]
}
decodedData[input.name] = itemData

View File

@ -1,5 +1,5 @@
import Web3 from 'web3';
import { BN } from 'ethereumjs-util';
import Web3 from 'web3'
import { BN } from 'ethereumjs-util'
/**
* Converts some token minimal unit to render format string, showing 5 decimals
@ -10,23 +10,17 @@ import { BN } from 'ethereumjs-util';
* @returns {String} - Number of token minimal unit, in render format
* If value is less than 5 precision decimals will show '< 0.00001'
*/
export function renderFromTokenMinimalUnit(
tokenValue,
decimals,
decimalsToShow = 5
) {
const minimalUnit = fromTokenMinimalUnit(tokenValue || 0, decimals);
const minimalUnitNumber = parseFloat(minimalUnit);
let renderMinimalUnit;
export function renderFromTokenMinimalUnit(tokenValue, decimals, decimalsToShow = 5) {
const minimalUnit = fromTokenMinimalUnit(tokenValue || 0, decimals)
const minimalUnitNumber = parseFloat(minimalUnit)
let renderMinimalUnit
if (minimalUnitNumber < 0.00001 && minimalUnitNumber > 0) {
renderMinimalUnit = "< 0.00001";
renderMinimalUnit = '< 0.00001'
} else {
const base = Math.pow(10, decimalsToShow);
renderMinimalUnit = (
Math.round(minimalUnitNumber * base) / base
).toString();
const base = Math.pow(10, decimalsToShow)
renderMinimalUnit = (Math.round(minimalUnitNumber * base) / base).toString()
}
return renderMinimalUnit;
return renderMinimalUnit
}
/**
* Converts token minimal unit to readable string value
@ -36,25 +30,25 @@ export function renderFromTokenMinimalUnit(
* @returns {string} - String containing the new number
*/
export function fromTokenMinimalUnit(minimalInput, decimals) {
minimalInput = addHexPrefix(Number(minimalInput).toString(16));
let minimal = safeNumberToBN(minimalInput);
const negative = minimal.lt(new BN(0));
const base = Web3.utils.toBN(Math.pow(10, decimals).toString());
minimalInput = addHexPrefix(Number(minimalInput).toString(16))
let minimal = safeNumberToBN(minimalInput)
const negative = minimal.lt(new BN(0))
const base = Web3.utils.toBN(Math.pow(10, decimals).toString())
if (negative) {
minimal = minimal.mul(new BN(-1));
minimal = minimal.mul(new BN(-1))
}
let fraction = minimal.mod(base).toString(10);
let fraction = minimal.mod(base).toString(10)
while (fraction.length < decimals) {
fraction = "0" + fraction;
fraction = '0' + fraction
}
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1];
const whole = minimal.div(base).toString(10);
let value = "" + whole + (fraction === "0" ? "" : "." + fraction);
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1]
const whole = minimal.div(base).toString(10)
let value = '' + whole + (fraction === '0' ? '' : '.' + fraction)
if (negative) {
value = "-" + value;
value = '-' + value
}
return value;
return value
}
/**
@ -65,20 +59,20 @@ export function fromTokenMinimalUnit(minimalInput, decimals) {
* @returns {String} - Number of token minimal unit, in render format
* If value is less than 5 precision decimals will show '< 0.00001'
*/
export function renderFromWei(value, decimalsToShow = 5) {
let renderWei = '0';
export function renderFromWei(value, decimalsToShow = 5) {
let renderWei = '0'
// avoid undefined
if (value) {
const wei = Web3.utils.fromWei(value);
const weiNumber = parseFloat(wei);
const wei = Web3.utils.fromWei(value)
const weiNumber = parseFloat(wei)
if (weiNumber < 0.00001 && weiNumber > 0) {
renderWei = '< 0.00001';
renderWei = '< 0.00001'
} else {
const base = Math.pow(10, decimalsToShow);
renderWei = (Math.round(weiNumber * base) / base).toString();
const base = Math.pow(10, decimalsToShow)
renderWei = (Math.round(weiNumber * base) / base).toString()
}
}
return renderWei;
return renderWei
}
/**
@ -89,7 +83,7 @@ export function fromTokenMinimalUnit(minimalInput, decimals) {
* @returns {string} - String of the hex token value
*/
export function calcTokenValueToSend(value, decimals) {
return value ? (value * Math.pow(10, decimals)).toString(16) : 0;
return value ? (value * Math.pow(10, decimals)).toString(16) : 0
}
/**
@ -99,11 +93,7 @@ export function calcTokenValueToSend(value, decimals) {
* @returns {boolean} - True if the string is a valid decimal
*/
export function isDecimal(value) {
return (
Number.isFinite(parseFloat(value)) &&
!Number.isNaN(parseFloat(value)) &&
!isNaN(+value)
);
return Number.isFinite(parseFloat(value)) && !Number.isNaN(parseFloat(value)) && !isNaN(+value)
}
/**
@ -113,7 +103,7 @@ export function isDecimal(value) {
* @returns {Object} - BN instance
*/
export function toBN(value) {
return Web3.utils.toBN(value);
return Web3.utils.toBN(value)
}
/**
@ -123,20 +113,20 @@ export function toBN(value) {
* @returns {string} The prefixed string.
*/
export const addHexPrefix = (str: string) => {
if (typeof str !== "string" || str.match(/^-?0x/u)) {
return str;
if (typeof str !== 'string' || str.match(/^-?0x/u)) {
return str
}
if (str.match(/^-?0X/u)) {
return str.replace("0X", "0x");
return str.replace('0X', '0x')
}
if (str.startsWith("-")) {
return str.replace("-", "-0x");
if (str.startsWith('-')) {
return str.replace('-', '-0x')
}
return `0x${str}`;
};
return `0x${str}`
}
/**
* Wraps 'numberToBN' method to avoid potential undefined and decimal values
@ -145,8 +135,8 @@ export const addHexPrefix = (str: string) => {
* @returns {Object} - The converted value as BN instance
*/
export function safeNumberToBN(value: number | string) {
const safeValue = fastSplit(value.toString()) || "0";
return numberToBN(safeValue);
const safeValue = fastSplit(value.toString()) || '0'
return numberToBN(safeValue)
}
/**
@ -157,60 +147,52 @@ export function safeNumberToBN(value: number | string) {
* @returns {string} - the selected splitted element
*/
export function fastSplit(value, divider = ".") {
value += "";
const [from, to] = [value.indexOf(divider), 0];
return value.substring(from, to) || value;
export function fastSplit(value, divider = '.') {
value += ''
const [from, to] = [value.indexOf(divider), 0]
return value.substring(from, to) || value
}
export function stripHexPrefix(str: string) {
if (typeof str !== "string") {
return str;
if (typeof str !== 'string') {
return str
}
return str.slice(0, 2) === "0x" ? str.slice(2) : str;
return str.slice(0, 2) === '0x' ? str.slice(2) : str
}
export function numberToBN(arg) {
if (typeof arg === "string" || typeof arg === "number") {
if (typeof arg === 'string' || typeof arg === 'number') {
var multiplier = Web3.utils.toBN(1); // eslint-disable-line
var formattedString = String(arg).toLowerCase().trim();
var isHexPrefixed =
formattedString.substr(0, 2) === "0x" ||
formattedString.substr(0, 3) === "-0x";
var formattedString = String(arg).toLowerCase().trim()
var isHexPrefixed = formattedString.substr(0, 2) === '0x' || formattedString.substr(0, 3) === '-0x'
var stringArg = stripHexPrefix(formattedString); // eslint-disable-line
if (stringArg.substr(0, 1) === "-") {
stringArg = stripHexPrefix(stringArg.slice(1));
multiplier = Web3.utils.toBN(-1);
if (stringArg.substr(0, 1) === '-') {
stringArg = stripHexPrefix(stringArg.slice(1))
multiplier = Web3.utils.toBN(-1)
}
stringArg = stringArg === "" ? "0" : stringArg;
stringArg = stringArg === '' ? '0' : stringArg
if (
(!stringArg.match(/^-?[0-9]+$/) && stringArg.match(/^[0-9A-Fa-f]+$/)) ||
stringArg.match(/^[a-fA-F]+$/) ||
(isHexPrefixed === true && stringArg.match(/^[0-9A-Fa-f]+$/))
) {
return Web3.utils.toBN(stringArg).mul(multiplier);
return Web3.utils.toBN(stringArg).mul(multiplier)
}
if (
(stringArg.match(/^-?[0-9]+$/) || stringArg === "") &&
isHexPrefixed === false
) {
return Web3.utils.toBN(stringArg).mul(multiplier);
if ((stringArg.match(/^-?[0-9]+$/) || stringArg === '') && isHexPrefixed === false) {
return Web3.utils.toBN(stringArg).mul(multiplier)
}
} else if (typeof arg === "object" && arg.toString && !arg.pop && !arg.push) {
if (
arg.toString(10).match(/^-?[0-9]+$/) &&
(arg.mul || arg.dividedToIntegerBy)
) {
return Web3.utils.toBN(arg.toString(10));
} else if (typeof arg === 'object' && arg.toString && !arg.pop && !arg.push) {
if (arg.toString(10).match(/^-?[0-9]+$/) && (arg.mul || arg.dividedToIntegerBy)) {
return Web3.utils.toBN(arg.toString(10))
}
}
throw new Error(
"[number-to-bn] while converting number " +
'[number-to-bn] while converting number ' +
JSON.stringify(arg) +
" to BN.js instance, error: invalid number value. Value must be an integer, hex string, BN or BigNumber instance. Note, decimals are not supported."
);
' to BN.js instance, error: invalid number value. Value must be an integer, hex string, BN or BigNumber instance. Note, decimals are not supported.',
)
}

View File

@ -107,18 +107,17 @@ export function string62to10(numberCode: string) {
export function hexToUtf8(hexString) {
// Remove any leading "0x" prefix and split into pairs of characters
let _hexString = hexString.replace(/^0x/, "");
let _hexString = hexString.replace(/^0x/, '')
let buffer = Buffer.from(_hexString, 'hex')
return buffer.toString('utf8')
}
export function utf8ToHex(utf8String) {
// Create a Buffer object from the UTF-8 string
const buffer = Buffer.from(utf8String, "utf8");
const buffer = Buffer.from(utf8String, 'utf8')
// Convert the Buffer object to a hex string
const hexString = buffer.toString("hex");
const hexString = buffer.toString('hex')
return hexString;
return hexString
}

763
yarn.lock

File diff suppressed because it is too large Load Diff