diff --git a/app/components/input.js b/app/components/input.js index 459ae30..68ce8fb 100644 --- a/app/components/input.js +++ b/app/components/input.js @@ -9,7 +9,10 @@ const defaultStyles = ` padding: 10px; width: 100%; outline: none; - font-family: ${props => props.theme.fontFamily} + font-family: ${ + // $FlowFixMe + props => props.theme.fontFamily +} `; const Input = styled.input.attrs({ @@ -39,10 +42,10 @@ export const InputComponent = ({ inputType, onChange, ...props }: Props) => { }; if (!Object.keys(inputTypes).find(key => key === inputType)) { - throw new Error(`Invalid input type: ${inputType}`); + throw new Error(`Invalid input type: ${String(inputType)}`); } - return inputTypes[inputType](); + return inputTypes[inputType || 'input'](); }; InputComponent.defaultProps = { diff --git a/config/daemon/zcashd-child-process.js b/config/daemon/zcashd-child-process.js index c889a3d..af09d67 100644 --- a/config/daemon/zcashd-child-process.js +++ b/config/daemon/zcashd-child-process.js @@ -35,7 +35,7 @@ const getDaemonOptions = ({ username, password }) => { `-rpcuser=${username}`, `-rpcpassword=${password}`, ]; - return isDev ? defaultOptions.concat('-testnet') : defaultOptions; + return isDev ? defaultOptions.concat(['-testnet', '-addnode=testnet.z.cash']) : defaultOptions; }; let resolved = false; diff --git a/services/api.js b/services/api.js new file mode 100644 index 0000000..259f337 --- /dev/null +++ b/services/api.js @@ -0,0 +1,40 @@ +// @flow +import got from 'got'; +/* eslint-disable-next-line */ +import isDev from 'electron-is-dev'; + +import { METHODS, type APIMethods } from './utils'; +import store from '../config/electron-store'; + +const RPC = { + host: '127.0.0.1', + port: isDev ? 18232 : 8232, + user: store.get('rpcuser'), + password: store.get('rpcpassword'), +}; + +const client = got.extend({ + method: 'POST', + json: true, + auth: `${RPC.user}:${RPC.password}`, +}); + +// $FlowFixMe +const api: APIMethods = METHODS.reduce( + (obj, method) => ({ + ...obj, + [method]: (...args) => client + .post(`http://${RPC.host}:${RPC.port}`, { + body: { + method, + jsonrpc: '2.0', + id: Date.now(), + params: args, + }, + }) + .then(data => Promise.resolve(data.body && data.body.result)), + }), + {}, +); + +export default api; diff --git a/services/utils.js b/services/utils.js new file mode 100644 index 0000000..356a15b --- /dev/null +++ b/services/utils.js @@ -0,0 +1,827 @@ +// @flow + +export const METHODS = [ + 'getbestblockhash', + 'getblock', + 'getblockchaininfo', + 'getblockcount', + 'getblockhash', + 'getblockheader', + 'getchaintips', + 'getdifficulty', + 'getmempoolinfo', + 'getrawmempool', + 'gettxout', + 'gettxoutproof', + 'gettxoutsetinfo', + 'verifychain', + 'verifytxoutproof', + 'getinfo', + 'help', + 'stop', + 'z_getpaymentdisclosure', + 'z_validatepaymentdisclosure', + 'generate', + 'getgenerate', + 'setgenerate', + 'getblocksubsidy', + 'getblocktemplate', + 'getlocalsolps', + 'getmininginfo', + 'getnetworkhashps', + 'getnetworksolps', + 'prioritisetransaction', + 'submitblock', + 'addnode', + 'clearbanned', + 'disconnectnode', + 'getaddednodeinfo', + 'getconnectioncount', + 'getdeprecationinfo', + 'getnettotals', + 'getnetworkinfo', + 'getpeerinfo', + 'listbanned', + 'ping', + 'setban', + 'createrawtransaction', + 'decoderawtransaction', + 'decodescript', + 'fundrawtransaction', + 'getrawtransaction', + 'sendrawtransaction', + 'signrawtransaction', + 'createmultisig', + 'estimatefee', + 'estimatepriority', + 'validateaddress', + 'verifymessage', + 'z_validateaddress', + 'addmultisigaddress', + 'backupwallet', + 'dumpprivkey', + 'dumpwallet', + 'encryptwallet', + 'getaccount', + 'getaccountaddress', + 'getaddressesbyaccount', + 'getbalance', + 'getnewaddress', + 'getrawchangeaddress', + 'getreceivedbyaccount', + 'getreceivedbyaddress', + 'gettransaction', + 'getunconfirmedbalance', + 'getwalletinfo', + 'importaddress', + 'importprivkey', + 'importwallet', + 'keypoolrefill', + 'listaccounts', + 'listaddressgroupings', + 'listlockunspent', + 'listreceivedbyaccount', + 'listreceivedbyaddress', + 'listsinceblock', + 'listtransactions', + 'listunspent', + 'lockunspent', + 'move', + 'sendfrom', + 'sendmany', + 'sendtoaddress', + 'setaccount', + 'settxfee', + 'signmessage', + 'z_exportkey', + 'z_exportviewingkey', + 'z_exportwallet', + 'z_getbalance', + 'z_getnewaddress', + 'z_getoperationresult', + 'z_getoperationstatus', + 'z_gettotalbalance', + 'z_importkey', + 'z_importviewingkey', + 'z_importwallet', + 'z_listaddresses', + 'z_listoperationids', + 'z_listreceivedbyaddress', + 'z_listunspent', + 'z_mergetoaddress', + 'z_sendmany', + 'z_shieldcoinbase', +]; + +export type APIMethods = { + getbestblockhash: () => Promise, + getblock: ( + hash: string, + ) => Promise<{ + hash: string, + confirmations: number, + size: number, + height: number, + version: number, + merkleroot: string, + finalsaplingroot: string, + tx: string[], + time: number, + nonce: string, + solution: string, + bits: string, + difficulty: number, + chainwork: string, + anchor: string, + valuePools: { + id: string, + monitored: boolean, + chainValue: number, + chainValueZat: number, + valueDelta: number, + valueDeltaZat: number, + }[], + previousblockhash: string, + nextblockhash: string, + }>, + getblockchaininfo: () => Promise<{ + chain: string, + blocks: number, + headers: number, + bestblockhash: string, + difficulty: number, + verificationprogress: number, + chainwork: string, + pruned: boolean, + commitments: number, + valuePools: { + id: string, + monitored: boolean, + chainValue: number, + chainValueZat: number, + }[], + softforks: { + id: string, + version: number, + enforce: { + status: boolean, + found: number, + required: number, + window: number, + }, + reject: { + status: boolean, + found: number, + required: number, + window: number, + }, + }[], + upgrades: { [x: string]: Object }, + consensus: { + chaintip: string, + nextblock: string, + }, + }>, + getblockcount: () => Promise, + getblockhash: (idx: number) => Promise, + getblockheader: ( + hash: string, + ) => Promise<{ + hash: string, + confirmations: number, + height: number, + version: number, + merkleroot: string, + finalsaplingroot: string, + time: number, + nonce: string, + solution: string, + bits: string, + difficulty: number, + chainwork: string, + previousblockhash: string, + nextblockhash: string, + }>, + /* eslint-disable-next-line flowtype/generic-spacing */ + getchaintips: () => Promise< + Array<{ + height: number, + hash: string, + branchlen: number, + status: string, + }>, + >, + getdifficulty: () => Promise, + getmempoolinfo: () => Promise<{ + size: string, + bytes: string, + usage: string, + }>, + getrawmempool: () => Promise, + gettxout: ( + txid: string, + n: number, + includemempool: boolean, + ) => Promise<{ + bestblock: string, + confirmations: number, + value: number, + scriptPubKey: { + asm: string, + hex: string, + reqSigs: number, + type: string, + addresses: string[], + }, + version: number, + coinbase: number, + }>, + gettxoutproof: (txid: string, n: number, includemempool: boolean) => Promise, + gettxoutsetinfo: () => Promise<{ + height: number, + bestblock: string, + transactions: number, + txouts: number, + bytes_serialized: number, + hash_serialized: string, + total_amount: number, + }>, + verifychain: (checklevel: number, numblocks: number) => Promise, + verifytxoutproof: (proof: string) => Promise, + getinfo: () => Promise<{ + version: number, + protocolversion: number, + walletversion: number, + balance: number, + blocks: number, + timeoffset: number, + connections: number, + proxy: string, + difficulty: number, + testnet: boolean, + keypoololdest: number, + keypoolsize: number, + paytxfee: number, + relayfee: number, + errors: string, + }>, + help: () => Promise, + stop: () => Promise, + z_getpaymentdisclosure: (txid: string, js_index: string, output_index: string, message: string) => Promise, + z_validatepaymentdisclosure: (paymentdisclosure: string) => Promise, + generate: (numblocks: number) => Promise, + getgenerate: () => Promise, + setgenerate: (generate: boolean, genproclimit?: number) => Promise, + getblocksubsidy: (height?: number) => Promise<{ miner: number, founders: number }>, + getblocktemplate: ( + jsonrequestobject: string, + ) => Promise<{ + capabilities: string[], + version: number, + previousblockhash: string, + finalsaplingroothash: string, + transactions: { + data: string, + hash: string, + depends: any[], + fee: number, + sigops: number, + }[], + coinbasetxn: { + data: string, + hash: string, + depends: any[], + fee: number, + sigops: number, + foundersreward: number, + required: boolean, + }, + longpollid: string, + target: string, + mintime: number, + mutable: string[], + noncerange: string, + sigoplimit: number, + sizelimit: number, + curtime: number, + bits: string, + height: number, + }>, + getlocalsolps: () => Promise, + getmininginfo: () => Promise<{ + blocks: number, + currentblocksize: number, + currentblocktx: number, + difficulty: number, + errors: string, + genproclimit: number, + localsolps: number, + networksolps: number, + networkhashps: number, + pooledtx: number, + testnet: boolean, + chain: string, + generate: boolean, + }>, + getnetworkhashps: (blocks?: number, height?: number) => Promise, + getnetworksolps: (blocks?: number, height?: number) => Promise, + prioritisetransaction: (txid: string, priorityDelta: number, feeDelta: number) => Promise, + submitblock: ( + hexdata: string, + jsonparametersobject?: string, + ) => Promise<'duplicate' | 'duplicate-invalid' | 'duplicate-inconclusive' | 'inconclusive' | 'rejected'>, + addnode: (node: string, command: string) => Promise, + clearbanned: () => Promise, + disconnectnode: (node: string) => Promise, + getaddednodeinfo: ( + dns?: boolean, + node?: string, + ) => Promise<{ + addednode: string, + connected: number, + addresses: { + address: string, + connected: string, + }[], + }>, + getconnectioncount: () => Promise, + getdeprecationinfo: () => Promise<{ + version: string, + subversion: string, + deprecationheight: number, + }>, + getnettotals: () => Promise<{ + totalbytesrecv: number, + totalbytessent: number, + timemillis: number, + }>, + getnetworkinfo: () => Promise<{ + version: number, + subversion: string, + protocolversion: number, + localservices: string, + timeoffset: number, + connections: number, + networks: { + name: string, + limited: boolean, + reachable: boolean, + proxy: string, + proxy_randomize_credentials: boolean, + }[], + relayfee: number, + localaddresses: { + name: string, + limited: boolean, + reachable: boolean, + proxy: string, + proxy_randomize_credentials: boolean, + }[], + warnings: string, + }>, + getpeerinfo: () => Promise<{ + id: number, + addr: string, + addrlocal: string, + services: string, + lastsend: number, + lastrecv: number, + bytessent: number, + bytesrecv: number, + conntime: number, + timeoffset: number, + pingtime: number, + version: number, + subver: string, + inbound: boolean, + startingheight: number, + banscore: number, + synced_headers: number, + synced_blocks: number, + inflight: any[], + whitelisted: boolean, + }>, + listbanned: () => Promise, + ping: () => Promise, + setban: (ip: string, command: string, bantime?: number, absolute?: number) => Promise, + createrawtransaction: ( + transactions: { txid: string, vout: number, sequence?: number }[], + addresses: { address: number }[], + locktime?: number, + expiryheight?: number, + ) => Promise, + decoderawtransaction: ( + hex: string, + ) => Promise<{ + txid: string, + overwintered: boolean, + version: number, + versiongroupid: string, + locktime: number, + expiryheight: number, + vin: { + txid: string, + vout: number, + scriptSig: { + value: number, + n: number, + scriptPubKey: { + asm: string, + hex: string, + reqSigs: number, + type: string, + addresses: string[], + }, + }, + sequence: number, + }[], + vout: { + value: number, + n: number, + scriptPubKey: { + asm: string, + hex: string, + reqSigs: number, + type: string, + addresses: string[], + }, + }[], + vjoinsplit: { + value: number, + n: number, + scriptPubKey: { + asm: string, + hex: string, + reqSigs: number, + type: string, + addresses: string[], + }, + }[], + }>, + decodescript: ( + hex: string, + ) => Promise<{ + asm: string, + hex: string, + type: string, + reqSigs: string, + addresses: string[], + p2sh: string, + address: string, + }>, + fundrawtransaction: ( + hex: string, + ) => Promise<{ + hex: string, + fee: number, + changepos: string, + }>, + getrawtransaction: ( + txid: string, + ) => Promise<{ + hex: string, + txid: string, + version: number, + locktime: number, + expiryheight: number, + vin: { + txid: string, + vout: number, + scriptSig: { + asm: string, + hex: string, + }, + sequence: number, + }[], + vout: { + value: number, + n: number, + scriptPubKey: { + asm: string, + hex: string, + reqSigs: number, + type: string, + addresses: string[], + }, + }[], + vjoinsplit: { + vpub_old: number, + vpub_new: number, + anchor: string, + nullifiers: string[], + commitments: string[], + onetimePubKey: string, + randomSeed: string, + macs: string[], + proof: string, + ciphertexts: string[], + }[], + blockhash: string, + confirmations: number, + time: number, + blocktime: number, + }>, + sendrawtransaction: (hex: string, allowHighFees?: boolean) => Promise, + signrawtransaction: ( + hex: string, + prevtxs?: Array<{ txid: string, vout: number, scriptPubKey: string, redeemScript: string, amount: number }>, + privatekeys?: string[], + sighashtype?: 'ALL' | 'NONE' | 'SINGLE' | 'ALL|ANYONECANPAY' | 'NONE|ANYONECANPAY' | 'SINGLE|ANYONECANPAY', + branchid?: string, + ) => Promise<{ + hex: string, + complete: boolean, + errors: { txid: string, vout: number, scriptSig: string, sequence: number, error?: string }[], + }>, + createmultisig: (nrequired: number, keys: string[]) => Promise<{ address: string, redeemScript: string }>, + estimatefee: (nblocks: number) => Promise, + estimatepriority: (nblocks: number) => Promise, + validateaddress: ( + zcashaddress: string, + ) => Promise<{ + isvalid: boolean, + address: string, + scriptPubKey: string, + ismine: boolean, + isscript: boolean, + pubkey: string, + iscompressed: boolean, + account: string, + }>, + verifymessage: (zcashaddress: string, signature: string, message: string) => Promise, + z_validateaddress: ( + zaddr: string, + ) => Promise<{ + isvalid: boolean, + address: string, + type: string, + ismine: boolean, + payingkey: string, + transmissionkey: string, + diversifier: string, + diversifiedtransmissionkey: string, + }>, + addmultisigaddress: (nrequired: string, keysobject: { address: string }[], account: string) => Promise, + backupwallet: (destination: string) => Promise, + dumpprivkey: (tAddr: string) => Promise, + dumpwallet: (filename: string) => Promise, + encryptwallet: (passphrase: string) => Promise, + getaccount: (zcashaddress: string) => Promise, + getaccountaddress: (account: string) => Promise, + getaddressesbyaccount: (account: string) => Promise, + getbalance: (account?: string, minconf?: number, includeWatchonly?: boolean) => Promise, + getnewaddress: (account: string) => Promise, + getrawchangeaddress: (address: string) => Promise, + getreceivedbyaccount: (account: string, minconf?: number) => Promise, + getreceivedbyaddress: (zcashaddress: string, minconf?: number) => Promise, + gettransaction: ( + txid: string, + includeWatchonly?: boolean, + ) => Promise<{ + amount: number, + confirmations: number, + blockhash: string, + blockindex: number, + blocktime: number, + txid: string, + time: number, + timereceived: number, + details: { + account: string, + address: string, + category: string, + amount: number, + vout: number, + }[], + vjoinsplit: { + anchor: string, + nullifiers: string[], + commitments: string[], + macs: string[], + vpub_old: number, + vpub_new: number, + }[], + hex: string, + }>, + getunconfirmedbalance: (account: string) => Promise, + getwalletinfo: () => Promise<{ + walletversion: number, + balance: number, + unconfirmed_balance: number, + immature_balance: number, + txcount: number, + keypoololdest: number, + keypoolsize: number, + paytxfee: number, + seedfp: string, + }>, + importaddress: (address: string, label?: string, rescan?: boolean) => Promise, + importprivkey: (zcashprivkey: string, label?: string, rescan?: boolean) => Promise, + importwallet: (filename: string) => Promise, + keypoolrefill: (newsize?: number) => Promise, + listaccounts: (minconf?: number, includeWatchonly?: boolean) => Promise<{ [account: string]: number }>, + listaddressgroupings: () => Promise, + listlockunspent: () => Promise<{ txid: string, vout: number }[]>, + /* eslint-disable flowtype/generic-spacing */ + listreceivedbyaccount: ( + minconf?: number, + includeempty?: boolean, + includeWatchonly?: boolean, + ) => Promise< + { + involvesWatchonly: boolean, + account: string, + amount: number, + confirmations: number, + }[], + >, + listreceivedbyaddress: ( + minconf?: number, + includeempty?: boolean, + includeWatchonly?: boolean, + ) => Promise< + { involvesWatchonly: boolean, account: string, amount: number, confirmations: number, account: string }[], + >, + listsinceblock: ( + blockhash: string, + targetConfirmations?: number, + includeWatchonly?: boolean, + ) => Promise<{ + transactions: { + account: string, + address: string, + category: string, + amount: number, + vout: number, + fee: number, + confirmations: number, + blockhash: string, + blockindex: number, + blocktime: number, + txid: string, + time: number, + timereceived: number, + comment: string, + to: string, + }[], + lastblock: string, + }>, + listtransactions: ( + account?: string, + count?: number, + from?: number, + includeWatchonly?: boolean, + ) => Promise< + { + account: string, + address: string, + amount: number, + vout: number, + fee: number, + confirmations: number, + blockhash: string, + blockindex: number, + txid: string, + time: number, + timereceived: number, + comment: string, + otheraccount: string, + size: number, + }[], + >, + listunspent: ( + minconf?: number, + maxconf?: number, + addresses: string[], + ) => Promise< + { + txid: string, + vout: number, + generated: boolean, + address: string, + account: string, + scriptPubKey: string, + amount: number, + confirmations: number, + redeemScript: number, + spendable: number, + }[], + >, + lockunspent: (unlock: boolean, transactions: { txid: string, vout: string }[]) => Promise, + move: ( + fromaccount: string, + toaccount: string, + amount: number, + minconf?: number, + comment?: string, + ) => Promise, + sendfrom: ( + fromaccount: string, + tozcashaddress: string, + amount: number, + minconf?: number, + comment?: string, + commentTo: string, + ) => Promise, + sendmany: ( + fromaccount: string, + amounts: { [address: string]: number }[], + minconf?: number, + comment?: string, + subtractfeefromamount?: string[], + ) => Promise, + sendtoaddress: ( + zcashaddress: string, + amount: number, + comment?: string, + commentTo?: string, + subtractfeefromamount?: boolean, + ) => Promise, + setaccount: (zcashaddress: string, account: string) => Promise, + settxfee: (amount: number) => Promise, + signmessage: (tAddr: string, message: string) => Promise, + z_exportkey: (zaddr: string) => Promise, + z_exportviewingkey: (zaddr: string) => Promise, + z_exportwallet: (filename: string) => Promise, + z_getbalance: (address: string, minconf?: number) => Promise, + z_getnewaddress: (type: string) => Promise, + z_getoperationresult: (operationid: string) => Promise, + z_getoperationstatus: (operationid: string) => Promise, + z_gettotalbalance: ( + minconf?: number, + includeWatchonly?: boolean, + ) => Promise<{ + transparent: number, + private: number, + total: number, + }>, + z_importkey: (zkey: string, rescan?: 'yes' | 'no' | 'whenkeyisnew', startHeight?: number) => Promise, + z_importviewingkey: (vkey: string, rescan?: 'yes' | 'no' | 'whenkeyisnew', startHeight?: number) => Promise, + z_importwallet: (filename: string) => Promise, + z_listaddresses: (includeWatchonly?: boolean) => Promise, + z_listoperationids: (status?: string) => Promise, + z_listreceivedbyaddress: ( + address: string, + minconf?: number, + ) => Promise<{ + txid: string, + amount: number, + memo: number, + change: boolean, + }>, + z_listunspent: ( + minconf?: number, + maxconf?: number, + includeWatchonly?: boolean, + addresses: string[], + ) => Promise< + { + txid: string, + jsindex: number, + jsoutindex: number, + outindex: number, + confirmations: number, + spendable: boolean, + address: string, + amount: number, + memo: number, + change: boolean, + }[], + >, + z_mergetoaddress: ( + fromaddresses: string[], + toaddress: string, + fee?: number, + transparent_limit?: number, + shielded_limit?: number, + memo?: string, + ) => Promise<{ + remainingUTXOs: number, + remainingTransparentValue: number, + remainingNotes: number, + remainingShieldedValue: number, + mergingUTXOs: number, + mergingTransparentValue: number, + mergingNotes: number, + mergingShieldedValue: number, + opid: number, + }>, + z_sendmany: ( + fromaddress: string, + amounts: { address: string, amount: number, memo?: string }[], + minconf?: number, + fee?: number, + ) => Promise, + z_shieldcoinbase: ( + fromaddress: string, + toaddress: string, + fee?: number, + limit?: number, + ) => Promise<{ + remainingUTXOs: number, + remainingValue: number, + shieldingUTXOs: number, + shieldingValue: number, + opid: number, + }>, +};