packageDocumentation module hidden import { hexToNumber , isHex , isAddress , strip0x , ChainType } from '@harmony-js/utils' ; import { decode , encode , keccak256 , hexlify , BN , hexZeroPad , recoverAddress , Signature , getAddress , sign , } from '@harmony-js/crypto' ; import { HttpProvider , Messenger } from '@harmony-js/network' ; import { TxParams } from './types' ; import { Transaction } from './transaction' ; export const transactionFields = [ { name : 'nonce' , length : 32 , fix : false } , { name : 'gasPrice' , length : 32 , fix : false , transform : 'hex' } , { name : 'gasLimit' , length : 32 , fix : false , transform : 'hex' } , { name : 'shardID' , length : 16 , fix : false } , { name : 'toShardID' , length : 16 , fix : false } , { name : 'to' , length : 20 , fix : true } , { name : 'value' , length : 32 , fix : false , transform : 'hex' } , { name : 'data' , fix : false } , ] ; export const transactionFieldsETH = [ { name : 'nonce' , length : 32 , fix : false } , { name : 'gasPrice' , length : 32 , fix : false , transform : 'hex' } , { name : 'gasLimit' , length : 32 , fix : false , transform : 'hex' } , { name : 'to' , length : 20 , fix : true } , { name : 'value' , length : 32 , fix : false , transform : 'hex' } , { name : 'data' , fix : false } , ] ; export const handleNumber = ( value ) => { if ( isHex ( value ) && value === '0x' ) { return hexToNumber ( '0x00' ) ; } else if ( isHex ( value ) && value !== '0x' ) { return hexToNumber ( value ) ; } else { return value ; } } ; export const handleAddress = ( value ) : string => { if ( value === '0x' ) { return '0x' ; } else if ( isAddress ( value ) ) { return value ; } else { return '0x' ; } } ; export const recover = ( rawTransaction ) => { const transaction = decode ( rawTransaction ) ; if ( transaction . length !== 11 && transaction . length !== 8 ) { throw new Error ( 'invalid rawTransaction' ) ; } const tx = { id : '0x' , from : '0x' , rawTransaction : '0x' , unsignedRawTransaction : '0x' , nonce : new BN ( strip0x ( handleNumber ( transaction [ 0 ] ) ) ) . toNumber ( ) , gasPrice : new BN ( strip0x ( handleNumber ( transaction [ 1 ] ) ) ) , gasLimit : new BN ( strip0x ( handleNumber ( transaction [ 2 ] ) ) ) , shardID : new BN ( strip0x ( handleNumber ( transaction [ 3 ] ) ) ) . toNumber ( ) , toShardID : new BN ( strip0x ( handleNumber ( transaction [ 4 ] ) ) ) . toNumber ( ) , to : handleAddress ( transaction [ 5 ] ) !== '0x' ? getAddress ( handleAddress ( transaction [ 5 ] ) ) . checksum : '0x' , value : new BN ( strip0x ( handleNumber ( transaction [ 6 ] ) ) ) , data : transaction [ 7 ] , chainId : 0 , signature : { r : '' , s : '' , recoveryParam : 0 , v : 0 , } , } ; if ( transaction . length === 8 ) { tx . unsignedRawTransaction = rawTransaction ; return tx ; } try { tx . signature . v = new BN ( strip0x ( handleNumber ( transaction [ 8 ] ) ) ) . toNumber ( ) ; } catch ( error ) { throw error ; } tx . signature . r = hexZeroPad ( transaction [ 9 ] , 32 ) ; tx . signature . s = hexZeroPad ( transaction [ 10 ] , 32 ) ; if ( new BN ( strip0x ( handleNumber ( tx . signature . r ) ) ) . isZero ( ) && new BN ( strip0x ( handleNumber ( tx . signature . s ) ) ) . isZero ( ) ) { tx . chainId = tx . signature . v ; tx . signature . v = 0 ; } else { tx . chainId = Math . floor ( ( tx . signature . v - 35 ) / 2 ) ; if ( tx . chainId < 0 ) { tx . chainId = 0 ; } let recoveryParam = tx . signature . v - 27 ; const raw = transaction . slice ( 0 , 8 ) ; if ( tx . chainId !== 0 ) { raw . push ( hexlify ( tx . chainId ) ) ; raw . push ( '0x' ) ; raw . push ( '0x' ) ; recoveryParam -= tx . chainId * 2 + 8 ; } const digest = keccak256 ( encode ( raw ) ) ; try { const recoveredFrom = recoverAddress ( digest , { r : hexlify ( tx . signature . r ) , s : hexlify ( tx . signature . s ) , recoveryParam , } ) ; tx . from = recoveredFrom === '0x' ? '0x' : getAddress ( recoveredFrom ) . checksum ; } catch ( error ) { throw error ; } tx . rawTransaction = rawTransaction ; tx . id = keccak256 ( rawTransaction ) ; } return tx ; } ; export const recoverETH = ( rawTransaction ) => { const transaction = decode ( rawTransaction ) ; if ( transaction . length !== 9 && transaction . length !== 6 ) { throw new Error ( 'invalid rawTransaction' ) ; } const tx = { id : '0x' , from : '0x' , rawTransaction : '0x' , unsignedRawTransaction : '0x' , nonce : new BN ( strip0x ( handleNumber ( transaction [ 0 ] ) ) ) . toNumber ( ) , gasPrice : new BN ( strip0x ( handleNumber ( transaction [ 1 ] ) ) ) , gasLimit : new BN ( strip0x ( handleNumber ( transaction [ 2 ] ) ) ) , shardID : 0 , toShardID : 0 , to : handleAddress ( transaction [ 3 ] ) !== '0x' ? getAddress ( handleAddress ( transaction [ 3 ] ) ) . checksum : '0x' , value : new BN ( strip0x ( handleNumber ( transaction [ 4 ] ) ) ) , data : transaction [ 5 ] , chainId : 0 , signature : { r : '' , s : '' , recoveryParam : 0 , v : 0 , } , } ; if ( transaction . length === 6 ) { tx . unsignedRawTransaction = rawTransaction ; return tx ; } try { tx . signature . v = new BN ( strip0x ( handleNumber ( transaction [ 6 ] ) ) ) . toNumber ( ) ; } catch ( error ) { throw error ; } tx . signature . r = hexZeroPad ( transaction [ 7 ] , 32 ) ; tx . signature . s = hexZeroPad ( transaction [ 8 ] , 32 ) ; if ( new BN ( strip0x ( handleNumber ( tx . signature . r ) ) ) . isZero ( ) && new BN ( strip0x ( handleNumber ( tx . signature . s ) ) ) . isZero ( ) ) { tx . chainId = tx . signature . v ; tx . signature . v = 0 ; } else { tx . chainId = Math . floor ( ( tx . signature . v - 35 ) / 2 ) ; if ( tx . chainId < 0 ) { tx . chainId = 0 ; } let recoveryParam = tx . signature . v - 27 ; const raw = transaction . slice ( 0 , 6 ) ; if ( tx . chainId !== 0 ) { raw . push ( hexlify ( tx . chainId ) ) ; raw . push ( '0x' ) ; raw . push ( '0x' ) ; recoveryParam -= tx . chainId * 2 + 8 ; } const digest = keccak256 ( encode ( raw ) ) ; try { const recoveredFrom = recoverAddress ( digest , { r : hexlify ( tx . signature . r ) , s : hexlify ( tx . signature . s ) , recoveryParam , } ) ; tx . from = recoveredFrom === '0x' ? '0x' : getAddress ( recoveredFrom ) . checksum ; } catch ( error ) { throw error ; } tx . rawTransaction = rawTransaction ; tx . id = keccak256 ( rawTransaction ) ; } return tx ; } ; export const sleep = async ( ms ) => new Promise ( ( resolve ) => { setTimeout ( ( ) => resolve ( ) , ms ) ; } ) ; export enum TransactionEvents { transactionHash = 'transactionHash' , error = 'error' , confirmation = 'confirmation' , receipt = 'receipt' , track = 'track' , cxConfirmation = 'cxConfirmation' , cxReceipt = 'cxReceipt' , cxTrack = 'cxTrack' } export const defaultMessenger = new Messenger ( new HttpProvider ( 'http://localhost:9500' ) , ChainType . Harmony ) ; export const RLPSign = ( transaction , prv ) : [ Signature , string ] => { const [ unsignedRawTransaction , raw ] = transaction . getRLPUnsigned ( ) ; const regroup = { ... transaction . txParams , unsignedRawTransaction , } ; transaction . setParams ( regroup ) ; const signature = sign ( keccak256 ( unsignedRawTransaction ) , prv ) ; const signed = transaction . getRLPSigned ( raw , signature ) ; return [ signature , signed ] ; } ;