import { BigNumber } from "bignumber.js" ; import * as RestStatus from "http-status-codes" ; import api from "./api" ; import { TxResultStatus } from "./constants" ; import util from "./util/util" ; import { constructMetadata , setAuthHeaders } from "./util/api.util" ; import { RestError , response } from "./util/rest.util" ; import jwt from "jsonwebtoken" ; import { Options , StratoUser , OAuthUser , BlockChainUser , Contract , ContractDefinition , TransactionResultHash , CallArgs , Chain , SendTx } from "./types" ; module typedef User property { String } token property { String } address typedef OAuthConfig property { String } appTokenCookieName property { String } scope property { Number } appTokenCookieMaxAge property { String } clientId property { String } clientSecret property { String } openIdDiscoveryUrl property { String } redirectUri property { String } logoutRedirectUri typedef Node property { Number } id property { String } url property { String } publicKey property { Number } port property { module:rest~OAuthConfig } oauth typedef Config property { String } VM property { Boolean } apiDebug property { module:rest~Node[] } nodes property { Number } timeout typedef Options property { Config } config property { Object } logger property { Object } headers property { Object } query property { String [ ] } history property { String [ ] } noindex property { Boolean } isAsync typedef Account property { String } kind property { String } balance property { String } address property { Number } latestBlockNum property { String } codeHash property { Number } nonce typedef CallArgs property { module:rest~Contract } contract property { String } method property { Object } args property { Number } value property { String } chainid property { module:rest~TxParams } txParams typedef CodeHash property { String } kind property { String } digest typedef Contract property { String } name property { String } source property { Object } args property { String } codeHash property { String } address typedef SendArgs property { String } toAddress property { Number } value property { module:rest~TxParams } txParams property { String } chainid typedef TxData property { String } Tag property { Array | module typedef TxParams property { Number } gasLimit property { Number } gasPrice typedef TxResult property { String } contractsDeleted property { String } gasUsed property { String } stateDiff property { String } time property { String } kind property { String } chainid property { String } response property { String } blockHash property { String } transactionHash property { String } etherUsed property { String } contractsCreated typedef TxResultWrapper property { String } status property { String } hash property { module:rest~TxResult } txResult property { module:rest~TxData } data typedef UploadedContract property { String } name property { String } chainId property { String } address property { module:rest~CodeHash } codeHash property { String } bin property { Object } xabi typedef Chain property { String } label property { String } src property { Array } memberList property { Array } balanceList typedef ChainHash property { String } hash typedef ChainInfo property { Array < Object > } balances property { Array < Object > } members property { String } label function isTxSuccess ( txResult ) { return txResult . status === TxResultStatus . SUCCESS ; } function isTxFailure ( txResult ) { return txResult . status === TxResultStatus . FAILURE ; } function assertTxResult ( txResult ) { if ( isTxFailure ( txResult ) ) { throw new RestError ( RestStatus . BAD_REQUEST , txResult . txResult . message , txResult . txResult ) ; } return txResult ; } function assertTxResultList ( txResultList ) { txResultList . forEach ( ( txResult , index ) => { if ( isTxFailure ( txResult ) ) { throw new RestError ( RestStatus . BAD_REQUEST , `tx:${ index }, message:${ txResult . txResult . message }` , { index , txResult : txResult . txResult } ) ; } } ) ; return txResultList ; } static example param { module:rest~User } user param { module:rest~TxResultWrapper } pendingTxResult param { module:rest~Options } options returns { module:rest~TxResultWrapper } async function resolveResult ( user , pendingTxResult , options ) { return ( await resolveResults ( user , [ pendingTxResult ] , options ) ) [ 0 ] ; } static example param { module:rest~User } user param { module:rest~TxResultWrapper[] } pendingTxResults param { module:rest~Options } options returns { module:rest~TxResultWrapper[] } async function resolveResults ( user , pendingResults , _options ) { const options = Object . assign ( { isAsync : true } , _options ) ; const predicate = results => results . filter ( r => r . status === TxResultStatus . PENDING ) . length === 0 ; const action = async ( ) => getBlocResults ( user , pendingResults . map ( r => r . hash ) , options ) ; const resolvedResults = await util . until ( predicate , action , options ) ; return resolvedResults ; } static example param { module:rest~User } user param { module:rest~Options } options returns { module:rest~Account[] } async function getAccounts ( user , options ) { try { return await api . getAccounts ( user , { ... options , isAsync : true } ) ; } catch ( err ) { throw new RestError ( RestStatus . BAD_REQUEST , err . response . statusText || err . response || err , err . response . data || err . response || err ) ; } } async function getHealth ( user , options ) { try { return await api . getHealth ( user , { ... options , isAsync : true } ) ; } catch ( err ) { throw new RestError ( RestStatus . BAD_REQUEST , err . response . statusText || err . response || err , err . response . data || err . response || err ) ; } } async function getStatus ( user , options ) { try { return await api . getStatus ( user , { ... options , isAsync : true } ) ; } catch ( err ) { throw new RestError ( RestStatus . BAD_REQUEST , err . response . statusText || err . response || err , err . response . data || err . response || err ) ; } } async function getVersion ( user , options ) { try { return await api . getVersion ( user , { ... options , isAsync : true } ) ; } catch ( err ) { throw new RestError ( RestStatus . BAD_REQUEST , err . response . statusText || err . response || err , err . response . data || err . response || err ) ; } } static example param { module:rest~User } user param { module:rest~Options } options returns { module:rest~User } async function createUser ( ouser , options ) { const address = await createOrGetKey ( ouser , options ) ; return Object . assign ( { } , ouser , { address } ) ; } async function fill ( user , options ) { const txResult = await api . fill ( user , options ) ; return assertTxResult ( txResult ) ; } static example param { module:rest~User } user param { module:rest~Contract[] } contracts param { module:rest~Options } options returns { module:rest~Contract[] } async function compileContracts ( user , contracts , options ) { try { return await api . compileContracts ( user , contracts , options ) ; } catch ( err ) { throw new RestError ( RestStatus . BAD_REQUEST , err . response . statusText || err . response || err , err . response . data || err . response || err ) ; } } static example param { module:rest~User } user param { module:rest~Contract } contract param { module:rest~Options } options returns { module:rest~Contract|module:rest~TxResultWrapper } async function createContract ( user , contract , options ) { const [ pendingTxResult ] = await api . createContract ( user , contract , options ) ; return createContractResolve ( user , pendingTxResult , options ) ; } async function createContractResolve ( user , pendingTxResult , options ) { assertTxResult ( pendingTxResult ) ; if ( options . isAsync ) return pendingTxResult ; const resolvedTxResult = await resolveResult ( user , pendingTxResult , options ) ; assertTxResult ( pendingTxResult ) ; if ( options . isDetailed ) return resolvedTxResult . data . contents ; return { name : resolvedTxResult . data . contents . name , address : resolvedTxResult . data . contents . address } ; } static example param { module:rest~User } user param { module:rest~Contract[] } contracts param { module:rest~Options } options returns { module:rest~Contract[]|module:rest~TxResultWrapper[] } async function createContractList ( user , contracts , options ) { const pendingTxResult = await api . createContractList ( user , contracts , options ) ; return createContractListResolve ( user , pendingTxResult , options ) ; } async function createContractListResolve ( user , pendingTxResultList , options ) { assertTxResultList ( pendingTxResultList ) ; if ( options . isAsync ) return pendingTxResultList ; const resolvedTxResultList = await resolveResults ( user , pendingTxResultList , options ) ; assertTxResultList ( resolvedTxResultList ) ; if ( options . isDetailed ) return resolvedTxResultList ; return resolvedTxResultList . map ( resolvedTxResult => resolvedTxResult . data . contents ) ; } static example param { module:rest~User } user param { module:rest~Options } options returns { String } async function getKey ( user , options ) { const response = await api . getKey ( user , options ) ; return response . address ; } static example param { module:rest~User } user param { module:rest~Options } options returns { String } async function createKey ( user , options ) { const response = await api . createKey ( user , options ) ; return response . address ; } static example param { module:rest~User } user param { module:rest~Options } options returns { String } async function createOrGetKey ( user , options ) { try { const getKeyResponse = await api . getKey ( user , options ) ; const balance = await api . getBalance ( user , getKeyResponse , options ) ; if ( balance . isEqualTo ( 0 ) ) { await fill ( { ... user , ... getKeyResponse } , { isAsync : false , ... options } ) ; } if ( getKeyResponse . address ) return getKeyResponse . address ; } catch ( e ) { if ( e . response && e . response . status == 400 ) { const createKeyResponse = await api . createKey ( user , options ) ; await fill ( { ... user , ... createKeyResponse } , { isAsync : false , ... options } ) ; return createKeyResponse . address ; } throw e ; } } async function getBlocResults ( user , hashes , options ) { return api . blocResults ( user , hashes , options ) ; } static example param { module:rest~User } user param { module:rest~Contract } contract param { module:rest~Options } options returns { Object } async function getState ( user , contract , options ) { return api . getState ( user , contract , options ) ; } static example param { module:rest~User } user param { module:rest~Contract } contract param { String } name param { module:rest~Options } options returns { Array } async function getArray ( user , contract , name , options ) { const MAX_SEGMENT_SIZE = 100 ; options . stateQuery = { name , length : true } ; const state = await getState ( user , contract , options ) ; const length = state [ name ] ; const result = [ ] ; for ( let segment = 0 ; segment < length / MAX_SEGMENT_SIZE ; segment ++ ) { options . stateQuery = { name , offset : segment * MAX_SEGMENT_SIZE , count : MAX_SEGMENT_SIZE } ; const state = await getState ( user , contract , options ) ; result . push ( ... state [ name ] ) ; } return result ; } static example param { module:rest~User } user param { module:rest~CallArgs } callArgs param { module:rest~Options } options returns { Array | module async function call ( user , callArgs , options ) { const [ pendingTxResult ] = await api . call ( user , callArgs , options ) ; return callResolve ( user , pendingTxResult , options ) ; } async function callResolve ( user , pendingTxResult , options ) { assertTxResult ( pendingTxResult ) ; if ( options . isAsync ) return pendingTxResult ; const resolvedTxResult = await resolveResult ( user , pendingTxResult , options ) ; assertTxResult ( pendingTxResult ) ; if ( options . isDetailed ) return resolvedTxResult ; return resolvedTxResult . data . contents ; } static example param { module:rest~User } user param { module:rest~CallArgs[] } callListArgs param { module:rest~Options } options returns { Array [ ] | module async function callList ( user , callListArgs , options ) { const pendingTxResultList = await api . callList ( user , callListArgs , options ) ; return callListResolve ( user , pendingTxResultList , options ) ; } async function callListResolve ( user , pendingTxResultList , options ) { assertTxResultList ( pendingTxResultList ) ; if ( options . isAsync ) return pendingTxResultList ; const resolvedTxResultList = await resolveResults ( user , pendingTxResultList , options ) ; assertTxResultList ( resolvedTxResultList ) ; if ( options . isDetailed ) return resolvedTxResultList ; return resolvedTxResultList . map ( resolvedTxResult => resolvedTxResult . data . contents ) ; } static example param { module:rest~User } user param { module:rest~SendArgs } sendTx param { module:rest~Options } options returns { module:rest~TxResultWrapper } async function send ( user , sendTx , options ) { const [ pendingTxResult ] = await api . send ( user , sendTx , options ) ; if ( options . isAsync ) { return pendingTxResult ; } const resolvedResult = await resolveResult ( user , pendingTxResult , options ) ; return resolvedResult . data . contents ; } static example param { module:rest~User } user param { module:rest~SendArgs[] } sendTx param { module:rest~Options } options returns { module:rest~TxResultWrapper[] } async function sendMany ( user , sendTxs , options ) { const pendingTxResults = await api . sendTransactions ( user , { txs : sendTxs . map ( tx => api . getSendArgs ( tx , options ) ) } , options ) ; if ( options . isAsync ) { return pendingTxResults . map ( r => r . hash ) ; } const resolvedResults = await resolveResults ( user , pendingTxResults , options ) ; return resolvedResults . map ( r => r . data . contents ) ; } static example param { module:rest~User } user param { module:rest~Contract } contracts param { module:rest~Options } options returns { Object } async function search ( user , contract , options ) { try { const results = await api . search ( user , contract , options ) ; return results ; } catch ( err ) { if ( err . response && err . response . status === RestStatus . NOT_FOUND ) { return [ ] ; } throw err ; } } static example param { module:rest~User } user param { module:rest~Contract } contract param { Object } predicate param { module:rest~Options } options returns { Object } async function searchUntil ( user , contract , predicate , options ) { const action = async ( o ) => { return search ( user , contract , o ) ; } ; const results = await util . until ( predicate , action , options ) ; return results ; } static example param { module:rest~User } user param { module:rest~Contract } contract param { module:rest~Options } options returns { Object } async function searchWithContentRange ( user , contract , options ) { try { const results = await api . searchWithContentRange ( user , contract , options ) ; return results ; } catch ( err ) { if ( err . response && err . response . status === RestStatus . NOT_FOUND ) { return { } ; } throw err ; } } static example param { module:rest~User } user param { module:rest~Contract } contract param { Object } predicate param { module:rest~Options } options returns { module:rest~TxResultWrapper[] } async function searchWithContentRangeUntil ( user , contract , predicate , options ) { const action = async ( o ) => { return searchWithContentRange ( user , contract , o ) ; } ; const results = await util . until ( predicate , action , options ) ; return results ; } static example param { module:rest~User } user param { module:rest~ChainHash } chainID param { module:rest~Options } options returns { module:rest~ChainInfo } async function getChain ( user , chainId , options ) { const results = await api . getChains ( [ chainId ] , setAuthHeaders ( user , options ) ) ; return results && results . length > 0 ? results [ 0 ] : { } ; } static example param { module:rest~User } user param { module:rest~ChainHash[] } chainIDs param { module:rest~Options } options returns { module:rest~ChainInfo[] } async function getChains ( user , chainIds , options ) { const results = await api . getChains ( chainIds , setAuthHeaders ( user , options ) ) ; return results ; } static example param { module:rest~User } user param { module:rest~Chain } chain param { module:rest~Contract } contract param { module:rest~Options } options returns { module:rest~ChainHash } async function createChain ( user , chain , contract , options ) { const result = await api . createChain ( { ... chain , contract : contract . name , metadata : constructMetadata ( options , contract . name ) } , setAuthHeaders ( user , options ) ) ; return result ; } async function createChains ( user , chains , options ) { const result = await api . createChains ( chains , setAuthHeaders ( user , options ) ) ; return result ; } async function uploadExtStorage ( user , args , options ) { const result = await api . uploadExtStorage ( args , setAuthHeaders ( user , options ) ) ; return result ; } async function attestExtStorage ( user , args , options ) { const result = await api . attestExtStorage ( args , setAuthHeaders ( user , options ) ) ; return result ; } async function verifyExtStorage ( user , contract , options ) { const result = await api . verifyExtStorage ( user , contract , options ) ; return result ; } async function downloadExtStorage ( user , contract , options ) { const result = await api . downloadExtStorage ( user , contract , options ) ; return result ; } async function listExtStorage ( user , args , options ) { const result = await api . listExtStorage ( user , args , options ) ; return result ; } static example param { module:rest~User } user param { module:rest~Options } options returns { String } async function pingOauth ( user , options ) { const response = await api . pingOauth ( user , options ) ; return response ; } async function debugStatus ( user , options ) { const response = await api . debugStatus ( user , options ) ; return response ; } async function debugPause ( user , options ) { const response = await api . debugPause ( user , options ) ; return response ; } async function debugResume ( user , options ) { const response = await api . debugResume ( user , options ) ; return response ; } async function debugGetBreakpoints ( user , options ) { const response = await api . debugGetBreakpoints ( user , options ) ; return response ; } async function debugPutBreakpoints ( user , args , options ) { const response = await api . debugPutBreakpoints ( user , args , options ) ; return response ; } async function debugDeleteBreakpoints ( user , args , options ) { const response = await api . debugDeleteBreakpoints ( user , args , options ) ; return response ; } async function debugClearBreakpoints ( user , options ) { const response = await api . debugClearBreakpoints ( user , options ) ; return response ; } async function debugClearBreakpointsPath ( user , path , options ) { const response = await api . debugClearBreakpointsPath ( user , path , options ) ; return response ; } async function debugStepIn ( user , options ) { const response = await api . debugStepIn ( user , options ) ; return response ; } async function debugStepOver ( user , options ) { const response = await api . debugStepOver ( user , options ) ; return response ; } async function debugStepOut ( user , options ) { const response = await api . debugStepOut ( user , options ) ; return response ; } async function debugGetStackTrace ( user , options ) { const response = await api . debugGetStackTrace ( user , options ) ; return response ; } async function debugGetVariables ( user , options ) { const response = await api . debugGetVariables ( user , options ) ; return response ; } async function debugGetWatches ( user , options ) { const response = await api . debugGetWatches ( user , options ) ; return response ; } async function debugPutWatches ( user , args , options ) { const response = await api . debugPutWatches ( user , args , options ) ; return response ; } async function debugDeleteWatches ( user , args , options ) { const response = await api . debugDeleteWatches ( user , args , options ) ; return response ; } async function debugClearWatches ( user , options ) { const response = await api . debugClearWatches ( user , options ) ; return response ; } async function debugPostEval ( user , args , options ) { const response = await api . debugPostEval ( user , args , options ) ; return response ; } static example param { module:rest~User } user param { module:rest~Contract } contract param { module:rest~Options } options returns { Object } async function waitForAddress ( user , contract , _options ) { const options = Object . assign ( { query : { address : `eq.${ contract . address }` } } , _options ) ; function predicate ( response ) { return ( response !== undefined && response . length != undefined && response . length > 0 ) ; } const results = await searchUntil ( user , contract , predicate , options ) ; return results [ 0 ] ; } export default { fill , getAccounts , getHealth , getStatus , getVersion , createUser , compileContracts , createContract , createContractList , getBlocResults , getState , getArray , call , callList , resolveResult , resolveResults , getKey , createKey , createOrGetKey , send , sendMany , search , searchUntil , searchWithContentRange , searchWithContentRangeUntil , createChain , createChains , getChain , getChains , uploadExtStorage , attestExtStorage , verifyExtStorage , downloadExtStorage , listExtStorage , pingOauth , debugStatus , debugPause , debugResume , debugGetBreakpoints , debugPutBreakpoints , debugDeleteBreakpoints , debugClearBreakpoints , debugClearBreakpointsPath , debugStepIn , debugStepOver , debugStepOut , debugGetStackTrace , debugGetVariables , debugGetWatches , debugPutWatches , debugDeleteWatches , debugClearWatches , debugPostEval , RestError , response , waitForAddress } ;