import { RPCMethod, Messenger, ResponseMiddleware, WSProvider, NewPendingTransactions, NewHeaders, LogSub, Syncing, } from '@harmony-js/network'; import { assertObject, AssertType, // HarmonyCore, DefaultBlockParams, } from '@harmony-js/utils'; import { getAddress } from '@harmony-js/crypto'; import { Transaction } from '@harmony-js/transaction'; class Blockchain { messenger: Messenger; constructor(messenger: Messenger) { this.messenger = messenger; } setMessenger(messenger: Messenger) { this.messenger = messenger; } getRpcResult(result: any) { if (result instanceof ResponseMiddleware) { return result.getRaw; } else { return result; } } /** * */ @assertObject({ address: ['isValidAddress', AssertType.required], blockNumber: ['isBlockNumber', AssertType.optional], shardID: ['isNumber', AssertType.optional], }) async getBalance({ address, blockNumber = DefaultBlockParams.latest, shardID = 0, }: { address: string; blockNumber?: string; shardID?: number; }) { const result = await this.messenger.send( RPCMethod.GetBalance, [getAddress(address).checksum, blockNumber], this.messenger.chainPrefix, shardID, ); return this.getRpcResult(result); } async getBlockNumber() { const result = await this.messenger.send(RPCMethod.BlockNumber, [], this.messenger.chainPrefix); return this.getRpcResult(result); } /** * */ @assertObject({ blockHash: ['isHash', AssertType.required], returnObject: ['isBoolean', AssertType.optional], }) async getBlockByHash({ blockHash, returnObject = true, }: { blockHash: string; returnObject?: boolean; }) { const result = await this.messenger.send( RPCMethod.GetBlockByHash, [blockHash, returnObject], this.messenger.chainPrefix, ); return this.getRpcResult(result); } /** * */ @assertObject({ blockNumber: ['isBlockNumber', AssertType.optional], returnObject: ['isBoolean', AssertType.optional], }) async getBlockByNumber({ blockNumber = DefaultBlockParams.latest, returnObject = true, }: { blockNumber?: string; returnObject?: boolean; }) { const result = await this.messenger.send( RPCMethod.GetBlockByNumber, [blockNumber, returnObject], this.messenger.chainPrefix, ); return this.getRpcResult(result); } @assertObject({ blockHash: ['isHash', AssertType.required], }) async getBlockTransactionCountByHash({ blockHash }: { blockHash: string }) { const result = await this.messenger.send( RPCMethod.GetBlockTransactionCountByHash, [blockHash], this.messenger.chainPrefix, ); return this.getRpcResult(result); } @assertObject({ blockNumber: ['isBlockNumber', AssertType.required], }) async getBlockTransactionCountByNumber({ blockNumber }: { blockNumber: string }) { const result = await this.messenger.send( RPCMethod.GetBlockTransactionCountByNumber, [blockNumber], this.messenger.chainPrefix, ); return this.getRpcResult(result); } /** * */ @assertObject({ blockHash: ['isHash', AssertType.required], index: ['isHex', AssertType.required], shardID: ['isNumber', AssertType.optional], }) async getTransactionByBlockHashAndIndex({ blockHash, index, shardID = 0, }: { blockHash: string; index: string; shardID?: number; }) { const result = await this.messenger.send( RPCMethod.GetTransactionByBlockHashAndIndex, [blockHash, index], this.messenger.chainPrefix, shardID, ); return this.getRpcResult(result); } @assertObject({ blockNumber: ['isBlockNumber', AssertType.optional], index: ['isHex', AssertType.required], }) async getTransactionByBlockNumberAndIndex({ blockNumber = DefaultBlockParams.latest, index, }: { blockNumber?: string; index: string; }) { const result = await this.messenger.send( RPCMethod.GetTransactionByBlockNumberAndIndex, [blockNumber, index], this.messenger.chainPrefix, ); return this.getRpcResult(result); } @assertObject({ txnHash: ['isHash', AssertType.required], shardID: ['isNumber', AssertType.optional], }) async getTransactionByHash({ txnHash, shardID = 0 }: { txnHash: string; shardID?: number }) { const result = await this.messenger.send( RPCMethod.GetTransactionByHash, [txnHash], this.messenger.chainPrefix, shardID, ); return this.getRpcResult(result); } /** * */ @assertObject({ txnHash: ['isString', AssertType.required], shardID: ['isNumber', AssertType.optional], }) async getTransactionReceipt({ txnHash, shardID = 0 }: { txnHash: string; shardID?: number }) { const result = await this.messenger.send( RPCMethod.GetTransactionReceipt, [txnHash], this.messenger.chainPrefix, shardID, ); return this.getRpcResult(result); } /** * */ @assertObject({ address: ['isValidAddress', AssertType.required], blockNumber: ['isBlockNumber', AssertType.optional], }) async getCode({ address, blockNumber = DefaultBlockParams.latest, }: { address: string; blockNumber?: string; }) { const result = await this.messenger.send( RPCMethod.GetCode, [getAddress(address).checksum, blockNumber], this.messenger.chainPrefix, ); return this.getRpcResult(result); } async net_peerCount() { const result = await this.messenger.send(RPCMethod.PeerCount, [], 'net'); return this.getRpcResult(result); } async net_version() { const result = await this.messenger.send(RPCMethod.NetVersion, [], 'net'); return this.getRpcResult(result); } async getProtocolVersion() { const result = await this.messenger.send( RPCMethod.ProtocolVersion, [], this.messenger.chainPrefix, ); return this.getRpcResult(result); } @assertObject({ address: ['isValidAddress', AssertType.required], position: ['isHex', AssertType.required], blockNumber: ['isBlockNumber', AssertType.optional], shardID: ['isNumber', AssertType.optional], }) async getStorageAt({ address, position, blockNumber = DefaultBlockParams.latest, shardID = 0, }: { address: string; position: string; blockNumber?: string; shardID?: number; }) { const result = await this.messenger.send( RPCMethod.GetStorageAt, [getAddress(address).checksum, position, blockNumber], this.messenger.chainPrefix, shardID, ); return this.getRpcResult(result); } @assertObject({ address: ['isValidAddress', AssertType.required], blockNumber: ['isBlockNumber', AssertType.optional], shardID: ['isNumber', AssertType.optional], }) async getTransactionCount({ address, blockNumber = DefaultBlockParams.latest, shardID = 0, }: { address: string; blockNumber?: string; shardID?: number; }) { const result = await this.messenger.send( RPCMethod.GetTransactionCount, [getAddress(address).checksum, blockNumber], this.messenger.chainPrefix, shardID, ); return this.getRpcResult(result); } async getShardingStructure() { const result = await this.messenger.send( RPCMethod.GetShardingStructure, [], this.messenger.chainPrefix, ); return this.getRpcResult(result); } async sendTransaction(transaction: Transaction) { if (!transaction.isSigned() || !transaction) { throw new Error('transaction is not signed or not exist'); } const result = await this.messenger.send( RPCMethod.SendRawTransaction, [transaction.getRawTransaction()], this.messenger.chainPrefix, typeof transaction.txParams.shardID === 'string' ? Number.parseInt(transaction.txParams.shardID, 10) : transaction.txParams.shardID, ); return this.getRpcResult(result); } async sendRawTransaction(transaction: Transaction) { if (!transaction.isSigned() || !transaction) { throw new Error('transaction is not signed or not exist'); } const [txn, result] = await transaction.sendTransaction(); if (txn.isPending) { return result; } } createObservedTransaction(transaction: Transaction) { try { transaction.sendTransaction().then((response) => { const [txReturned, TranID] = response; txReturned.confirm(TranID).then((txConfirmed) => { transaction.emitter.resolve(txConfirmed); }); }); return transaction.emitter; } catch (err) { throw err; } } @assertObject({ to: ['isValidAddress', AssertType.optional], data: ['isHex', AssertType.optional], }) async estimateGas({ to, data }: { to: string; data: string }) { const result = await this.messenger.send( RPCMethod.EstimateGas, [{ to: getAddress(to).checksum, data }], this.messenger.chainPrefix, ); return this.getRpcResult(result); } async gasPrice() { const result = await this.messenger.send(RPCMethod.GasPrice, [], this.messenger.chainPrefix); return this.getRpcResult(result); } async call({ payload, blockNumber = DefaultBlockParams.latest, }: { payload: any; blockNumber?: string; }) { const result = await this.messenger.send( RPCMethod.Call, [payload, blockNumber], this.messenger.chainPrefix, ); return this.getRpcResult(result); } newPendingTransactions(shardID: number = 0) { if (this.messenger.provider instanceof WSProvider) { return new NewPendingTransactions(this.messenger, shardID); } else { throw new Error('HttpProvider does not support this feature'); } } newBlockHeaders(shardID: number = 0) { if (this.messenger.provider instanceof WSProvider) { return new NewHeaders(this.messenger, shardID); } else { throw new Error('HttpProvider does not support this feature'); } } syncing(shardID: number = 0) { if (this.messenger.provider instanceof WSProvider) { return new Syncing(this.messenger, shardID); } else { throw new Error('HttpProvider does not support this feature'); } } logs(options: any, shardID: number = 0) { if (this.messenger.provider instanceof WSProvider) { return new LogSub(options, this.messenger, shardID); } else { throw new Error('HttpProvider does not support this feature'); } } } export { Blockchain };