import { Cert } from '@0xcert/cert' ; import { injectable } from 'tsyringe' ; import { Transaction } from 'web3-core' ; import { NETWORK } from '../../../..' ; import { ArianeeConfig } from '../../../../models/arianeeConfiguration' ; import { ArianeeHttpClient } from '../../../libs/arianeeHttpClient/arianeeHttpClient' ; import { ConfigurationService } from '../configurationService/configurationService' ; import { GasStationService } from '../gasStationService/gasStationService' ; import { WalletService } from '../walletService/walletService' ; import { Web3Service } from '../web3Service/web3Service' ; import { getRandomCharacter , getRandomInt } from '../../../libs/random/randomCharacter' ; @ injectable ( ) export class UtilsService { constructor ( private web3Service , private configurationService , private walletService , private httpService , private gasStationService ) { } private get web3 ( ) { return this . web3Service . web3 ; } public signProofForRequestToken ( certificateId , addressNextOwner , privateKeyPreviousOwner ) { const data = this . web3 . utils . keccak256 ( this . web3 . eth . abi . encodeParameters ( [ 'uint' , 'address' ] , [ certificateId , addressNextOwner ] ) ) ; return this . walletService . signProof ( data , privateKeyPreviousOwner ) ; } public signProofForRpc ( certificateId , privateKey ) { const message = { certificateId : certificateId , timestamp : new Date ( ) } ; return this . walletService . signProof ( JSON . stringify ( message ) , privateKey ) ; } public simplifiedParsedURL ( url ) { const m = url . match ( /^(([^:/?#]+:)?(?:\/\/((?:([^/?#:]*):([^/?#:]*)@)?([^/?#:]*)(?::([^/?#:]*))?)))?([^?#]*)(\?[^#]*)?(#.*)?$/ ) ; const r = { hash : m [ 10 ] || '' , hostname : m [ 6 ] || '' , pathname : m [ 8 ] || ( m [ 1 ] ? '/' : '' ) , port : m [ 7 ] || '' , protocol : m [ 2 ] || '' , search : m [ 9 ] || '' , username : m [ 4 ] || '' , password : m [ 5 ] || '' } ; return m && r ; } public createUID ( ) { return Math . ceil ( Math . random ( ) * 1000000000 ) ; } public createPassphrase ( ) { let result = '' ; for ( var i = 0 ; i < 11 ; i ++ ) { result += getRandomCharacter ( ) ; } const position = getRandomInt ( 0 , 11 ) ; const extraCharacter = getRandomCharacter ( ) ; return result . substring ( 0 , position ) + extraCharacter + result . substring ( position ) ; } public recover ( data , signature ) { return this . web3 . eth . accounts . recover ( < string > data , signature ) ; } param { { $schema : string ; [ p : string ] : any } } content returns { Promise < string > } public calculateImprint = async ( content ) : Promise < string > => { const $schema = await this . httpService . fetch ( content . $schema ) ; return this . cert ( $schema , content ) ; } ; public async cert ( schema , data ) { const cert = new Cert ( { schema : schema } ) ; const cleanData = this . cleanObject ( data ) ; const certif = await cert . imprint ( cleanData ) ; return '0x' + certif ; } private cleanObject ( obj ) { for ( const propName in obj ) { if ( obj [ propName ] && obj [ propName ] . constructor === Array && obj [ propName ] . length === 0 ) { delete obj [ propName ] ; } } return obj ; } param hostname param arianeeConfig private findHostNameInConfig ( hostname , arianeeConfig ) { const isCurrentConfigDeeplink = arianeeConfig . deepLink . split ( ':' ) [ 0 ] === hostname . split ( ':' ) [ 0 ] ; const isCurrentConfigAlternativeDeeplinks = arianeeConfig . alternativeDeeplink . find ( theDeepLink => theDeepLink === hostname ) ; const isCurrentConfig = isCurrentConfigDeeplink || isCurrentConfigAlternativeDeeplinks ; if ( isCurrentConfig ) { return arianeeConfig . networkName ; } } param hostname returns { NETWORK } public findChainFromHostname ( hostname ) { const networkConfigurations = this . configurationService . supportedConfigurations ; const networks = Object . keys ( this . configurationService . supportedConfigurations ) as Array < NETWORK > ; const isCurrentConfigurationNetwork = this . findHostNameInConfig ( hostname , this . configurationService . arianeeConfiguration ) ; if ( isCurrentConfigurationNetwork ) { return this . configurationService . arianeeConfiguration . networkName ; } return networks . find ( key => { const config = networkConfigurations [ key ] ; const network = this . findHostNameInConfig ( hostname , config ) ; if ( network ) { return true ; } else { return false ; } } ) ; } param hostname returns { true } public isRightChain ( hostname ) { const rightChain = this . findChainFromHostname ( hostname ) ; if ( rightChain ) { const currentNetworkName = this . configurationService . arianeeConfiguration . networkName ; if ( rightChain === currentNetworkName ) { return true ; } } const error = new Error ( 'You are not in the right chain' ) ; error . message = 'You are not in the right chain' ; ( error as any ) . chain = rightChain ; throw error ; } public createLink ( certificateId , passphrase , suffix ? ) { let link = `https://${ this . configurationService . arianeeConfiguration . deepLink }` ; if ( suffix ) { link = link + '/' + suffix ; } link = link + `/${ certificateId },${ passphrase }` ; return { certificateId : certificateId , passphrase : passphrase , link } ; } param link param { boolean } checkChain returns { { method : string ; certificateId : number ; passphrase : string } } public readLink ( link , checkChain = true ) { const url = this . simplifiedParsedURL ( link ) ; if ( checkChain ) { this . isRightChain ( url . hostname ) ; } const methodUrl = url . pathname . split ( '/' ) ; const pathName = methodUrl [ methodUrl . length - 1 ] ; const certificateId = parseInt ( pathName . split ( ',' ) [ 0 ] ) ; const passphrase = pathName . split ( ',' ) [ 1 ] ; let method = 'requestOwnership' ; if ( methodUrl . length > 2 ) method = methodUrl [ 1 ] ; return { method : method , certificateId : certificateId , passphrase } ; } public timestampIsMoreRecentThan = UtilsService . timestampIsMoreRecentThan ; public static timestampIsMoreRecentThan ( timestamp , seconds ) { const date = new Date ( ) . valueOf ( ) ; const minTime = date - seconds * 1000 ; return timestamp > minTime / 1000 ; } public async getTimestampFromBlock ( blockNumber ) { const block = await this . web3Service . web3 . eth . getBlock ( blockNumber ) ; return block . timestamp ; } public async prepareTransaction ( encodeABI , contractAddress , overrideNonce ? , transaction ? ) { const nonce = overrideNonce || await this . web3 . eth . getTransactionCount ( this . walletService . address , 'pending' ) ; const gasPrice = await this . gasStationService . fetchGas ( ) ; const defaultTransaction = { nonce , chainId : this . configurationService . arianeeConfiguration . chainId , from : this . walletService . address , data : encodeABI , to : contractAddress , gasLimit : this . configurationService . arianeeConfiguration . transactionOptions . gas , gasPrice , value : '0x00' } ; const mergedTransaction = { ... defaultTransaction , ... transaction } ; return mergedTransaction ; } }