import { currentNetwork , EthApi , requireAccount } from "@joincivil/ethapi" ; import { BigNumber , EthAddress , EthSignedMessage , TxHash , parseEther , ContentData , StorageHeader , } from "@joincivil/typescript-types" ; import { CivilErrors , networkNames } from "@joincivil/utils" ; import * as Debug from "debug" ; import { Observable } from "rxjs/Observable" ; import { CivilTransactionReceipt , FallbackProvider , TwoStepEthTransaction } from "." ; import { ContentProvider , ContentProviderCreator } from "./content/contentprovider" ; import { IPFSProvider } from "./content/ipfsprovider" ; import { Artifact , artifacts } from "./contracts/generated/artifacts" ; import { Newsroom } from "./contracts/newsroom" ; import { CivilTCR } from "./contracts/tcr/civilTCR" ; import { Council } from "./contracts/tcr/council" ; import { createTwoStepSimple } from "./contracts/utils/contracts" ; import { CVLToken } from "./contracts/tcr/cvltoken" ; import { provider as Provider } from "web3-core" ; const debug = Debug ( "civil:main" ) ; export interface CivilOptions { web3Provider ? : Provider ; ContentProvider ? : ContentProviderCreator ; debug ? : true ; } /**
 * Single entry-point to the civil.ts library
 * It abstracts most of the web3 and Ethereum communication.
 * Since all the calls to the Ethereum network take time, it is written using Promises,
 * and all of them can fail (for eg. when the connection to the node drops)
 */ export class Civil { private ethApi : EthApi ; private contentProvider : ContentProvider ; param web3Provider constructor ( options ? ) { const opts = { ... options } ; if ( opts . debug === true ) { Debug . enable ( "civil:*" ) ; debug ( 'Enabled debug for "civil:*" namespace' ) ; } if ( ! opts . web3Provider ) { throw new Error ( "no web3Provider in options" ) ; } const provider = opts . web3Provider ; this . ethApi = new EthApi ( provider , Object . values < Artifact > ( artifacts ) . map ( a => a . abi ) ) ; const providerConstructor = opts . ContentProvider || FallbackProvider . build ( [ IPFSProvider ] ) ; this . contentProvider = new providerConstructor ( { ethApi : this . ethApi } ) ; } public toBigNumber ( num ) { return this . ethApi . toBigNumber ( num ) ; } public toWei ( num ) { return this . ethApi . toWei ( num ) ; } public toChecksumAddress ( address ) { return this . ethApi . toChecksumAddress ( address ) ; } public async signMessage ( message , account ? ) { return this . ethApi . signMessage ( message , account ) ; } public async currentProviderEnable ( ) { if ( this . ethApi . currentProvider && ( this . ethApi . currentProvider as any ) . enable ) { try { await ( this . ethApi . currentProvider as any ) . enable ( ) ; return true ; } catch ( e ) { return false ; } } else { return true ; } } returns public get accountStream ( ) : Observable < EthAddress | undefined > { return this . ethApi . accountStream ; } public get networkStream ( ) : Observable < number > { return this . ethApi . networkStream ; } public get networkNameStream ( ) : Observable < string > { return this . ethApi . networkStream . map ( ( item ) : string => networkNames [ item ] || "unknown" ) ; } /**
     * Returns the current provider that is used by all things Civil in the Core
     */ public get currentProvider ( ) : Provider { return this . ethApi . currentProvider ; } param web3Provider public set currentProvider ( web3Provider ) { this . ethApi . currentProvider = web3Provider ; } /**
     * Create a new Newsroom owned by a multisig on the current Ethereum network with the
     * bytecode included in this library
     * The smart contract is trusted since it comes from a trusted source (us).
     * This call may require user input - such as approving a transaction in Metamask
     */ public async newsroomDeployTrusted ( newsroomName , charterUri = "" , charterHash = "" ) { return Newsroom . deployTrusted ( this . ethApi , this . contentProvider , newsroomName , charterUri , charterHash ) ; } public async estimateNewsroomDeployTrusted ( newsroomName , charterUri , charterHash ) { return Newsroom . estimateDeployTrusted ( this . ethApi , newsroomName , charterUri , charterHash ) ; } /**
     * Create a new Newsroom which is not owned by a multisig on the current Ethereum network with the
     * bytecode included in this library
     * The smart contract is trusted since it comes from a trusted source (us).
     * This call may require user input - such as approving a transaction in Metamask
     */ public async newsroomDeployNonMultisigTrusted ( newsroomName ) { return Newsroom . deployNonMultisigTrusted ( this . ethApi , this . contentProvider , newsroomName ) ; } see Civil . awaitReceipt param transactionHash param blockConfirmations throws public async newsroomFromTxHashUntrusted ( transactionHash , blockConfirmations ? ) { const receipt = await this . awaitReceipt ( transactionHash , blockConfirmations ) ; if ( ! receipt . contractAddress ) { throw new Error ( CivilErrors . MalformedParams ) ; } return this . newsroomAtUntrusted ( receipt . contractAddress ) ; } see Civil . awaitReceipt param transactionHash param blockConfirmations public async newsroomFromFactoryTxHashUntrusted ( transactionHash , blockConfirmations ? ) { const receipt = await this . awaitReceipt ( transactionHash , blockConfirmations ) ; return Newsroom . fromFactoryReceipt ( receipt , this . ethApi , this . contentProvider ) ; } param address public async newsroomAtUntrusted ( address ) { return Newsroom . atUntrusted ( this . ethApi , this . contentProvider , address ) ; } returns throws public async tcrSingletonTrusted ( ) { return CivilTCR . singleton ( this . ethApi , this . contentProvider ) ; } public async councilSingletonTrusted ( ) { return Council . singleton ( this . ethApi ) ; } public async cvlTokenSingletonTrusted ( multisigAddress ? ) { return CVLToken . singletonTrusted ( this . ethApi , multisigAddress ) ; } param multisigAddress returns throws public async tcrSingletonTrustedMultisigSupport ( multisigAddress ? ) { return CivilTCR . singletonMultisigProxy ( this . ethApi , this . contentProvider , multisigAddress ) ; } param transactionHash param blockConfirmations public async awaitReceipt ( transactionHash , blockConfirmations ? ) { return this . ethApi . awaitReceipt < CivilTransactionReceipt > ( transactionHash , blockConfirmations ) ; } param content param options returns public async publishContent ( content , options ? ) { return this . contentProvider . put ( content , options ) ; } public async getContent ( header ) { try { const content = await this . contentProvider . get ( header ) ; return content ; } catch ( e ) { debug ( `Resolving Content failed for EthContentHeader: ${ header }` , e ) ; return ; } } public async getBareContent ( uri ) { try { const content = await this . contentProvider . get ( { uri , contentHash : "" , } ) ; return content ; } catch ( e ) { debug ( `Resolving Content failed for uri: ${ uri }` , e ) ; return ; } } public async currentBlock ( ) { return this . ethApi . getLatestBlockNumber ( ) ; } public async networkName ( ) { return networkNames [ await currentNetwork ( this . ethApi ) ] || "unknown network" ; } public async getGasPrice ( ) { return this . ethApi . getGasPrice ( ) ; } public async accountBalance ( account ) { return this . ethApi . accountBalace ( account ) ; } public async simplePayment ( recipient , amountInETH ) { const wei = parseEther ( amountInETH ) ; const account = await requireAccount ( this . ethApi ) . toPromise ( ) ; return createTwoStepSimple ( this . ethApi , await this . ethApi . sendTransaction ( { from : account , to : recipient , value : wei . toString ( ) , gas : 26000 } ) ) ; } }