{"version":3,"sources":["components/unconfirmed-tx.tsx","components/wallet.tsx","context/actions.ts","components/block.tsx","components/header.tsx","context/context-provider.tsx","components/blockchain.tsx","components/control-panel.tsx","components/status-message.tsx","components/modal.tsx","App.tsx","context/connector.tsx","reportWebVitals.js","index.js","services/index.ts","context/reducer.ts","components/transaction.tsx"],"names":["UnconfirmedTx","unconfirmedTxData","className","formatKey","vin","txid","Buffer","from","vout","scriptPubKey","toString","value","Wallet","index","host","address","totalAmount","dispatch","useState","to","setTo","amount","setAmount","pay","a","spendCoinRelay","fetchControlPanel","statusMessageAction","level","StatusLevel","ERROR","message","console","log","onClick","navigator","clipboard","writeText","onChange","event","parseInt","target","rows","placeholder","ActionType","blockchainAction","payload","type","BLOCKCHAIN","blockAction","BLOCK","hostDetailsAction","HOST_DETAILS","unconfirmedTxPoolAction","UNCONFIRMED_TX_POOL","STATUS_MESSAGE","Direction","HoverElement","isHovering","setIsHovering","onMouseOver","onMouseOut","style","position","zIndex","height","Header","state","href","GlobalStateContext","React","createContext","initialState","action","warn","FirstcoinStateProvider","children","useReducer","reducer","Provider","Block","blockData","last","direction","expand","setExpand","duration","hash","substring","previousHash","difficultyLevel","timestamp","transactions","map","tx","txData","Forwards","Button","fetching","setFetching","mine","mineBlock","block","src","Blockchain","useEffect","fetchBlockchain","chain","blocks","f","messagesEndRef","useRef","current","scrollIntoView","behavior","blockchain","length","ref","ControlPanel","unconfirmedTxPool","hostDetails","hostDetail","hostname","StatusMessage","setTimeout","BLANK","statusMessage","MyModal","modalIsOpen","setIsOpen","closeModal","isOpen","onRequestClose","content","top","left","right","bottom","marginRight","transform","contentLabel","Component","useCheckMobileScreen","window","innerWidth","width","setWidth","handleWindowSizeChange","addEventListener","removeEventListener","connect","props","Consumer","reportWebVitals","onPerfEntry","Function","then","getCLS","getFID","getFCP","getLCP","getTTFB","ReactDOM","render","StrictMode","document","getElementById","HOST_NAME","process","REACT_APP_HOST_NAME","HOST_PORT","fetch","response","ok","json","Error","status","method","body","JSON","stringify","b","fetchHosts","fetchUnconfirmedTxPool","resp","e","pool","Object","values","clone","parse","hostArray","forEach","push","ipAddress","split","sortedHosts","sort","first","second","CLEAR_HOSTS","TxOut","txOData","TxIn","txInData","scriptSig","key","Transaction","txO","txIn"],"mappings":"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","file":"static/js/main.bbae0554.chunk.js","sourcesContent":["import { ITransaction } from \"../context/reducer\"\nimport { formatKey } from \"./transaction\"\n\nconst UnconfirmedTx = ({unconfirmedTxData}: {unconfirmedTxData: ITransaction}) => {\n return(\n <div className=\"border border-black w-11/12 mb-10 bg-white\">\n <div className=\"p-2\">\n <span className=\"font-bold\">In tx:</span>{formatKey(unconfirmedTxData.vin[0].txid)}\n </div>\n <div className=\"p-2\">\n <span className=\"font-bold\">pay to:</span> {formatKey(Buffer.from(unconfirmedTxData.vout[0].scriptPubKey, 'base64').toString('ascii'))} <span className=\"font-bold\">amount: </span>{unconfirmedTxData.vout[0].value}\n </div>\n <div className=\"p-2\">\n {unconfirmedTxData?.vout[1]&&\n <>\n <span className=\"font-bold\">pay from:</span> {formatKey(Buffer.from(unconfirmedTxData?.vout[1]?.scriptPubKey, 'base64').toString('ascii'))} <span className=\"font-bold\">vout: </span>{unconfirmedTxData?.vout[1]?.value}\n </>\n }\n </div>\n </div>\n )\n}\n\nexport default UnconfirmedTx","import { useState, useRef, useEffect } from 'react'\nimport { IAction, statusMessageAction } from '../context/actions'\nimport { spendCoinRelay } from '../services'\nimport { formatKey } from './transaction'\nimport { fetchControlPanel } from \"../services\"\n\nimport './wallet.css'\nimport { StatusLevel } from '../context/reducer'\n\ninterface IWallet{\n colour?: string;\n address: string;\n totalAmount: number;\n host: string;\n dispatch: React.Dispatch<IAction<any>>;\n index: number\n}\n\nconst Wallet = ({index, host, address, totalAmount, dispatch}: IWallet) => {\n const [to, setTo] = useState(\"\")\n const [amount, setAmount] = useState(0)\n const copy = () => {\n navigator.clipboard.writeText(address)\n }\n const pay = async () => {\n try{\n const response = await spendCoinRelay(host, to, amount)\n fetchControlPanel(dispatch)\n setTo(\"\")\n setAmount(0)\n }catch(e: any){\n dispatch(statusMessageAction({\n level: StatusLevel.ERROR,\n message: e\n }))\n console.log(e)\n }\n }\n\n return (\n <div className={`rounded-md text-white p-4 w-4/5 ${index == 0 ? \"bg-trendyRed\": \"bg-trendyBlue\"} mb-10`}>\n <div className=\"flex justify-center font-bold pb-4\">\n {index == 0 ? \"Miner & Wallet\" : \"Wallet\"}\n </div>\n <div className=\"flex w-full justify-between pb-4 items-center\">\n <div>\n <span className='font-bold'>Address</span>: {formatKey(Buffer.from(address, 'base64').toString('ascii'))}\n </div>\n\n <button onClick={copy} className={`h-10 w-16 ml-2 bg-trendyYellow text-white flex justify-center focus:ring-4 focus:ring-white items-center transform transition duration-500 hover:scale-105 cursor-pointer font-semibold rounded`}>\n Copy\n </button>\n </div>\n <div className=\"mb-4\">\n <div className=\"grid xl:grid-cols-1 grid-cols-3 gap-4\">\n <textarea value={amount ? amount: \"\"} onChange={(event) => setAmount(parseInt(event.target.value))} className=\"form-textarea block text-black border-white overflow-hidden\" rows={1} placeholder=\"Amount\"></textarea>\n <textarea value={to ? to : \"\"} onChange={(event) => setTo(event.target.value)} className=\"form-textarea block border-white overflow-hidden whitespace-nowrap\" rows={1} placeholder=\"Recipient\"></textarea>\n <button onClick={pay} className={`h-10 focus:ring-4 focus:ring-white bg-trendyYellow text-white flex justify-center items-center transform transition duration-500 hover:scale-105 cursor-pointer font-semibold rounded`}>\n Pay\n </button> \n </div>\n </div>\n <div>\n <span className='font-bold'>Balance</span>: {totalAmount}\n </div>\n </div>\n )\n}\n\nexport default Wallet","import { Blockchain, IBlock, IHostDetails, IStatusMessage, ITransaction } from \"./reducer\"\n\nexport enum ActionType {\n BLOCKCHAIN=\"BLOCKCHAIN\",\n BLOCK=\"BLOCK\",\n HOST_DETAILS=\"HOST_DETAILS\",\n UNCONFIRMED_TX_POOL=\"UNCONFIRMED_TX_POOL\",\n CLEAR_HOSTS=\"CLEAR_HOSTS\",\n STATUS_MESSAGE=\"STATUS_MESSAGE\"\n}\n\nexport interface IAction<T> {\n type: ActionType;\n payload: T\n}\n\nexport const blockchainAction = (payload: Blockchain) : IAction<Blockchain> => {\n return {\n type: ActionType.BLOCKCHAIN,\n payload: payload\n }\n}\n\nexport const blockAction = (payload: IBlock) : IAction<IBlock> => {\n return {\n type: ActionType.BLOCK,\n payload: payload\n }\n}\n\n\nexport const hostDetailsAction = (payload: IHostDetails[]) : IAction<IHostDetails[]> => {\n return {\n type: ActionType.HOST_DETAILS,\n payload: payload\n }\n}\n\nexport const clearHostDetailsAction = (payload: {}) : IAction<{}> => {\n return {\n type: ActionType.CLEAR_HOSTS,\n payload: payload\n }\n}\n\ninterface Pool{\n pool: ITransaction[]\n}\n\nexport const unconfirmedTxPoolAction = (payload: Pool) : IAction<Pool> => {\n return {\n type: ActionType.UNCONFIRMED_TX_POOL,\n payload: payload\n }\n}\n\nexport const statusMessageAction = (payload: IStatusMessage) : IAction<IStatusMessage> => {\n return {\n type: ActionType.STATUS_MESSAGE,\n payload: payload\n }\n}","import 'animate.css'\nimport './block.css'\nimport {IBlock} from '../context/reducer'\nimport { useState } from 'react'\nimport Transaction from './transaction'\nimport '../styles/theme.css'\nimport AnimateHeight from 'react-animate-height';\n\nexport enum Direction {\n Backwards,\n Forwards\n}\n\ninterface IBlockProps{\n blockData: IBlock; \n last: boolean;\n direction: Direction;\n}\n\nconst Block = ({blockData, last, direction}: IBlockProps) => {\n const [expand, setExpand] = useState(false)\n \n return (\n <div className=\"w-full flex flex-col items-center\">\n <div className=\"w-5/12 transform transition duration-500 hover:scale-105 flex flex-col items-center\">\n <AnimateHeight\n duration={ 500 }\n height={ expand ? 'auto': 150}\n className=\"w-full border-2 border-trendyGrey rounded-lg animate__animated animate__rubberBand\"\n >\n <div onClick={() => setExpand(!expand)} className=\" cursor-pointer\">\n <div className={`rounded text-trendyGrey bg-trendyGreen tran block p-2 overflow-hidden`}>\n <div>\n index: {blockData.index}\n </div>\n <div>\n hash: {blockData.hash.substring(0,10)}...\n </div> \n <div>\n prev: {blockData.previousHash ? blockData.previousHash.substring(0,10) : null}\n </div>\n <div>\n difficulty: {blockData.difficultyLevel}\n </div>\n <div>\n time: {blockData.timestamp}\n </div>\n <div>\n transactions: {blockData.transactions.map((tx, index) => {\n return <Transaction key={index} txData={tx}/>\n })}\n </div>\n </div>\n\n {/* {!displayArrow && <img className=\"\" src={'minecoin.gif'} alt=\"loading...\" />} */}\n\n </div>\n </AnimateHeight>\n </div>\n \n {direction == Direction.Forwards &&\n !last && <span className=\"arrow arrow-down\"></span>\n }\n </div>\n \n\n \n )\n}\n\nexport default Block","import {Context} from '../context/context-provider'\nimport {useState} from 'react';\n\nconst Header = ({state, dispatch}: Context) => {\n\n return(\n <div className=\"fixed z-50 w-8/12 bg-background2 flex flex-col items-center h-24 border-b border-grey mb-10\">\n <div className=\"text-trendyBlue font-bold text-xl\">Firstcoin</div>\n <div className=\"flex space-between w-full\">\n <div className=\"w-2/6\"><div className='ml-10'><HoverElement/></div></div>\n <div className=\"flex text-trendyGrey justify-center font-bold w-2/6 whitespace-nowrap\">Freddie O'Donnell</div>\n <a href=\"https://github.com/FreddieFruitSticks\" target=\"_blank\" className=\"flex justify-end w-2/6 text-trendyBlue underline font-bold whitespace-nowrap\"><div className='mr-10'>My Github Profile</div></a>\n </div>\n <div className=\"text-trendyGrey\">Cape Town</div>\n </div>\n )\n}\n\nconst HoverElement = ({}) => {\n const [isHovering, setIsHovering] = useState(false);\n\n const handleMouseOver = () => {\n setIsHovering(true);\n };\n\n const handleMouseOut = () => {\n setIsHovering(false);\n };\n return (<div>\n <div>\n <div className=\"w-3/6 underline cursor-help whitespace-nowrap\" onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}>\n How this works? \n </div>\n\n {isHovering && (\n <div\n style={{\n position: 'fixed',\n zIndex: 1000,\n height: !isHovering ? 0 : 'auto'\n }} >\n <div className=\"bg-oliveGreen text-white border-1 rounded border-white p-2 max-w-lg\">\n This is a demonstration blockchain, and it's very simple to use! In the middle you will see the blockchain. \n Click on \"Mine\" to manually mine a block. \n <div className='mt-3'>\n On the right you will see the \"Control Panel\". This is where you can transfer coins between wallets. \n Click \"copy\" to copy the address you want to pay <b>to</b>. Select an amount you wish to pay, and click \"pay\". \n Only the first miner (coloured red) mines and is rewarded 100 coin + 1 coin per transaction. \n </div>\n <div className='mt-3'>\n In the control panel you will also see the unconfirmed transaction pool. It will indicate the payer, payee, transaction id used \n to confirm the payment, and the \"vout\" which is the change awarded to the payer. To confirm a transaction\n click \"Mine\" to add it to the blockchain.\n </div>\n <div className='mt-3'>\n Happy mining!\n </div>\n </div>\n </div>\n )}\n </div>\n </div>)\n}\n\nexport default Header","import React, { ReactChild, useReducer } from 'react'\nimport { IAction } from './actions'\nimport reducer, { InitialState, initialState } from './reducer'\n\nexport interface Context {\n state: InitialState,\n dispatch: React.Dispatch<IAction<any>>\n}\n\nexport const GlobalStateContext = React.createContext<Context>({\n state: initialState,\n dispatch: (action: IAction<any>) => console.warn(`WARNING! Dispatch function not set. Attemting to dispatch ${action}`)\n})\n\nconst FirstcoinStateProvider = ({children}:{children: ReactChild}) => {\n let localState = {}\n \n let [state, dispatch] = useReducer(reducer, {...initialState, ...localState})\n console.log(\"-------------state after-----------------\")\n console.log(state)\n \n return (\n <GlobalStateContext.Provider value={{state, dispatch}}>\n {children}\n </GlobalStateContext.Provider>\n )\n}\n\nexport default FirstcoinStateProvider","import 'animate.css'\nimport './block.css'\nimport Block, { Direction } from './block'\nimport { useEffect, useRef, useState } from 'react'\nimport { fetchBlockchain, fetchControlPanel, mineBlock } from '../services'\nimport { Context } from '../context/context-provider'\nimport { blockAction, blockchainAction, IAction } from '../context/actions'\nimport './style.css'\nimport React from 'react'\n\ninterface IBlockchain extends Context{\n}\n\nconst Blockchain = ({state, dispatch}: IBlockchain) => {\n useEffect(() => {\n async function f(){\n try{\n const chain = await fetchBlockchain()\n dispatch(blockchainAction({\n blocks: chain.blocks\n }))\n }catch(e){\n console.log(e)\n }\n }\n\n f()\n\n },[dispatch])\n const messagesEndRef = useRef<any>(null)\n\n const scrollToBottom = () => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n \n useEffect(scrollToBottom, [state.blockchain]);\n \n return (\n <div>\n <div className=\"grid grid-cols-1 gap-4\">\n <div className='w-full font-bold flex flex-col items-center'>\n Firstcoin Blockchain\n <span className=\"arrow arrow-down\"></span>\n </div>\n {state.blockchain.blocks.map((block, index) => {\n return (\n <Block \n key={index} \n direction={Direction.Forwards} \n last={index === state.blockchain.blocks.length - 1} \n blockData={block}\n /> \n )})}\n <div ref={messagesEndRef}/>\n\n </div>\n <div className=\"pt-10 flex justify-center items-center w-full\">\n <Button dispatch={dispatch}/>\n </div>\n </div>\n \n )\n}\n\nconst Button : any = ({dispatch}:{dispatch:React.Dispatch<IAction<any>>}) => {\n const [fetching, setFetching] = useState(false)\n const mine = async () => {\n try{\n setFetching(true)\n const block = await mineBlock()\n dispatch(blockAction(block))\n fetchControlPanel(dispatch)\n }catch(e){\n console.log(e)\n }\n setFetching(false)\n\n }\n return (\n <div>\n {fetching ?\n <div className=\"flex justify-center\">\n <img className=\"w-3/6\" src=\"ezgif.gif\">\n </img>\n </div>\n :\n <div onClick={mine} className={`h-24 w-36 mb-28 bg-trendyBlue text-white flex justify-center items-center transform transition duration-500 hover:scale-105 cursor-pointer font-semibold py-2 px-4 rounded`}>\n Mine\n </div>}\n </div> \n )\n}\n\nexport default Blockchain","import { useEffect, useRef } from \"react\"\nimport { Context } from \"../context/context-provider\"\nimport { fetchControlPanel } from \"../services\"\nimport UnconfirmedTx from \"./unconfirmed-tx\"\nimport Wallet from \"./wallet\"\nimport Header from './header'\n\ninterface IControlPanel extends Context{\n}\n\nconst ControlPanel = ({state, dispatch}: IControlPanel) => {\n useEffect(() => {\n fetchControlPanel(dispatch)\n },[dispatch])\n\n const messagesEndRef = useRef<any>(null)\n\n const scrollToBottom = () => {\n if (state?.unconfirmedTxPool.length > 0){\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }\n }\n \n useEffect(scrollToBottom, [state?.unconfirmedTxPool]);\n \n return (\n <div className=\"flex flex-col items-center border-4 border-trendyTurquoise rounded-lg fixed right-0 h-screen bottom-0 w-4/12 overflow-y-scroll\">\n <div className=\"flex mb-16 items-center justify-center mt-10 font-trendyGrey text-3xl font-medium\">\n Control Panel\n </div>\n <div className=\"flex mb-10 items-center justify-center font-trendyGrey text-xl font-medium\">\n Global Wallets\n </div>\n {state?.hostDetails?.map((hostDetail, index) => {\n return (\n <Wallet index={index} key={index} dispatch={dispatch} host={hostDetail.hostname} address={hostDetail.address} totalAmount={hostDetail.totalAmount}/>\n )\n })}\n <div className=\"flex mb-10 items-center justify-center font-trendyGrey text-xl font-medium\">\n Unconfirmed Transaction pool\n </div>\n {state?.unconfirmedTxPool?.map((tx, index) => {\n return (\n <UnconfirmedTx key={index} unconfirmedTxData={tx}/>\n )\n })}\n <div ref={messagesEndRef}/>\n </div>\n )\n}\n\nexport default ControlPanel","import { useEffect } from \"react\"\nimport { statusMessageAction } from \"../context/actions\"\nimport { Context } from \"../context/context-provider\"\nimport { StatusLevel } from \"../context/reducer\"\nimport './status-message.css'\n\ninterface IStatusMessage extends Context{\n}\n\nconst StatusMessage = ({state, dispatch}: IStatusMessage) => {\n useEffect(() => {\n setTimeout(() => dispatch(statusMessageAction({\n message:\"\",\n level: StatusLevel.BLANK,\n })), 10000)\n },[state.statusMessage])\n \n return (\n <div>\n <div \n style={{\n position: 'fixed',\n zIndex: 1000,\n height: !state.statusMessage.level ? 0 : 'auto'\n }} \n className={`status-message-${state.statusMessage.level} ${state.statusMessage.level && state.statusMessage.level != StatusLevel.BLANK ? \"visible\" : \"invisible\"} w-8/12 p-10`}\n >\n {state?.statusMessage?.message &&\n `${state?.statusMessage?.message}`\n }\n </div>\n </div>\n )\n}\n\nexport default StatusMessage","import { useState } from 'react';\nimport Modal from 'react-modal';\n\nconst MyModal = ({}) => {\n const customStyles = {\n content: {\n top: '50%',\n left: '50%',\n right: 'auto',\n bottom: 'auto',\n marginRight: '-50%',\n transform: 'translate(-50%, -50%)',\n },\n };\n let subtitle: HTMLHeadingElement | null;\n const [modalIsOpen, setIsOpen] = useState(true);\n const [modalHasOpened, setModalHasOpened] = useState(false);\n \n function openModal() {\n if (!modalHasOpened){\n setIsOpen(true);\n setModalHasOpened(true)\n }\n }\n\n \n function closeModal() {\n setIsOpen(false);\n }\n return (\n <div>\n <Modal\n isOpen={modalIsOpen}\n onRequestClose={closeModal}\n style={customStyles}\n contentLabel=\"Example Modal\"\n >\n <h2 className=\"text-trendyRed font-bold mb-4\">Welcome to Firstcoin!</h2>\n <div>I see you are on a mobile phone. Please use landscape mode, or a larger screen, to use the functionality of this app. Happy mining!</div>\n <button onClick={closeModal} className={`h-10 w-16 mt-4 focus:ring-4 focus:ring-white bg-trendyRed text-white flex justify-center items-center transform transition duration-500 hover:scale-105 cursor-pointer font-semibold py-2 px-4 rounded`}>\n Close\n </button> \n </Modal>\n </div>\n\n )\n}\n\nexport default MyModal","import './App.css';\nimport Header from './components/header'\nimport { connect } from './context/connector';\nimport { Context } from './context/context-provider';\nimport Blockchain from './components/blockchain';\nimport ControlPanel from './components/control-panel';\nimport StatusMessage from './components/status-message';\nimport React, {useEffect, useState} from \"react\";\nimport MyModal from './components/modal';\n\nfunction App({state, dispatch}: Context) {\n return (\n <div className=\"bg-background\">\n <div className=\"w-8/12\">\n {useCheckMobileScreen() &&\n <MyModal/>\n }\n <StatusMessage {...{state, dispatch}}/>\n <Header {...{state, dispatch}}/>\n <div className=\"pt-28\">\n\n <Blockchain {...{state, dispatch}}/>\n </div>\n </div>\n <ControlPanel {...{state, dispatch}}/>\n </div>\n );\n}\n\n\n\nconst useCheckMobileScreen = () => {\n const [width, setWidth] = useState(window.innerWidth);\n const handleWindowSizeChange = () => {\n setWidth(window.innerWidth);\n }\n\n useEffect(() => {\n window.addEventListener('resize', handleWindowSizeChange);\n return () => {\n window.removeEventListener('resize', handleWindowSizeChange);\n }\n }, []);\n\n return (width <= 768);\n}\n\n\nexport default connect(App);\n","import React from 'react'\nimport {GlobalStateContext} from './context-provider'\n\nexport const connect = (Component: any) => {\n return (props: any) => (\n <GlobalStateContext.Consumer>\n {value => {\n const {state, dispatch} = value\n return (\n <Component {...props} state={state} dispatch={dispatch}/>\n )\n }}\n </GlobalStateContext.Consumer>\n )\n}","const reportWebVitals = onPerfEntry => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\nimport FirstcoinStateProvider from \"../src/context/context-provider\"\nimport './styles/theme.css'\n\nReactDOM.render(\n <FirstcoinStateProvider>\n <React.StrictMode>\n <App />\n </React.StrictMode>\n </FirstcoinStateProvider>\n,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n","import { clearHostDetailsAction, hostDetailsAction, IAction, unconfirmedTxPoolAction } from '../context/actions';\nimport {Blockchain, IHostDetails, IBlock, ITransaction} from '../context/reducer'\n\nvar HOST_NAME = process.env.REACT_APP_HOST_NAME ? process.env.REACT_APP_HOST_NAME : \"\"\nvar HOST_PORT = process.env.HOST_PORT ? process.env.HOST_PORT : \"\"\n\nexport const fetchBlockchain : () => Promise<Blockchain> = async () => {\n const response = await fetch(`${HOST_NAME}${HOST_PORT ? `:${HOST_PORT}` : \"\"}/block-chain`);\n if (response.ok){\n return response.json()\n }\n throw new Error(\"fetch blockchain returns \"+response.status)\n}\n\nexport const mineBlock : () => Promise<IBlock> = async () => {\n const response = await fetch(`${HOST_NAME}${HOST_PORT ? `:${HOST_PORT}` : \"\"}/create-block`,{\n method: \"POST\",\n body:JSON.stringify({a: 1, b: 'Textual content'})\n });\n if (response.ok){\n return response.json()\n }\n const message = await response.json()\n console.log(message)\n throw new Error(\"create blockchain returns \"+response.status)\n}\n\nexport const fetchHosts : () => Promise<IHostDetails[]> = async () => {\n const response = await fetch(`${HOST_NAME}${HOST_PORT ? `:${HOST_PORT}` : \"\"}/hosts`,{\n method: \"POST\",\n body: JSON.stringify({})\n });\n if (response.ok){\n return response.json()\n }\n throw new Error(\"fetch hosts returns \"+response.status)\n}\n\ntype txPoolObject = { [key: string]: ITransaction };\n\nexport const fetchUnconfirmedTxPool : () => Promise<txPoolObject> = async () => {\n const response = await fetch(`${HOST_NAME}${HOST_PORT ? `:${HOST_PORT}` : \"\"}/txpool`,{\n method: \"GET\"\n });\n if (response.ok){\n return response.json()\n }\n throw new Error(\"fetch host details returns \"+response.status)\n}\n\n//this sends the request to the main node - which passes the request on to the internal network\nexport const spendCoinRelay : (host: string, to: string, amount: number) => Promise<txPoolObject> = async (host, to, amount) => {\n const response = await fetch(`${HOST_NAME}${HOST_PORT ? `:${HOST_PORT}` : \"\"}/spend-coin-relay`,{\n method: \"POST\",\n body: JSON.stringify({host:host, address: to, amount: amount})\n });\n \n if (response.ok){\n return response.json()\n }\n \n const resp = await response.json()\n throw new Error(`pay from host ${host} returns ${response.status} ${resp.message}`)\n}\n\nexport const fetchControlPanel = async (dispatch: React.Dispatch<IAction<any>>) => {\n try{\n const hostDetails = await fetchHosts() \n try{\n dispatch(hostDetailsAction({\n ...hostDetails\n }))\n }catch(e){\n console.log(e)\n }\n \n const unconfirmedTxPool = await fetchUnconfirmedTxPool()\n dispatch(unconfirmedTxPoolAction({\n pool: Object.values(unconfirmedTxPool)\n })) \n \n }catch(e){\n console.log(e)\n }\n}","import { format } from 'path';\nimport { ActionType, hostDetailsAction, IAction } from './actions';\n\nexport interface IBlock{\n index: number;\n previousHash: string;\n transactions: ITransaction[];\n timestamp: number;\n difficultyLevel: number;\n nonce: number;\n hash: string;\n}\n\nexport interface ITxOutputs{\n scriptPubKey: string;\n value: number;\n}\n\nexport interface ITxInputs{\n txid: string;\n vout: number;\n scriptSig: string;\n}\n\nexport interface ITransaction{\n txid: string;\n locktime: number;\n vin: ITxInputs[];\n vout: ITxOutputs[];\n timestamp: number;\n}\n\nexport interface Blockchain{\n blocks: IBlock[]\n}\n\nexport enum StatusLevel {\n ERROR = \"ERROR\",\n SUCCESS = \"SUCCESS\",\n NOTICE = \"NOTICE\",\n BLANK = \"BLANK\"\n }\n\nexport interface IStatusMessage{\n message: string;\n level?: StatusLevel;\n}\n\nexport interface IHostDetails {\n address: string;\n totalAmount: number;\n hostname: string;\n}\n\nexport interface InitialState {\n blockchain: Blockchain;\n hostDetails: IHostDetails[];\n unconfirmedTxPool: ITransaction[];\n statusMessage: IStatusMessage;\n}\n\nexport const initialState: InitialState = {\n blockchain: {\n blocks: []\n },\n hostDetails: [],\n unconfirmedTxPool: [],\n statusMessage:{\n message:\"\"\n }\n}\n\n\nconst reducer : (state: InitialState, action: IAction<any>) => InitialState = (state, action) => {\n console.log(\"-------------state before-----------------\")\n console.log(state)\n console.log(\"----------------action--------------------\")\n console.log(action)\n\n switch (action.type) {\n case ActionType.BLOCKCHAIN:{\n const newState = {\n ...state,\n blockchain: {\n ...state.blockchain,\n ...action.payload\n }\n }\n \n return newState\n }\n \n case ActionType.BLOCK:{\n const newState = {\n ...state,\n blockchain: {\n ...state.blockchain,\n ...action.payload\n }\n }\n \n return newState\n }\n \n case ActionType.HOST_DETAILS:{\n const clone:{[key: number]: IHostDetails} = JSON.parse(JSON.stringify(action.payload));\n const hostArray: IHostDetails[] = []\n Object.values(clone).forEach(hostDetails => hostArray.push(hostDetails))\n \n const ipAddress = (hostname : string) => {\n return parseInt(hostname.split(\":\")[1])\n }\n \n const sortedHosts = hostArray.sort((first: IHostDetails, second: IHostDetails) => {\n if (ipAddress(first.hostname) < ipAddress(second.hostname)){\n return -1\n }\n \n return 1\n })\n \n const newState = {\n ...state,\n hostDetails: sortedHosts,\n }\n \n return newState\n }\n \n case ActionType.CLEAR_HOSTS:{ \n const newState = {\n ...state,\n hostDetails: []\n }\n \n return newState\n }\n \n case ActionType.UNCONFIRMED_TX_POOL:{ \n const newState = {\n ...state,\n unconfirmedTxPool: action.payload.pool\n }\n \n return newState\n }\n \n case ActionType.STATUS_MESSAGE:{ \n if (action.payload.message !== state.statusMessage.message && action.payload.level !== state.statusMessage.level){\n const newState = {\n ...state,\n statusMessage: {...action.payload}\n }\n \n return newState\n }\n \n \n return state\n }\n \n default:\n return state;\n }\n }\n \n export default reducer","\nimport 'animate.css'\nimport './block.css'\nimport {ITransaction, ITxInputs, ITxOutputs} from '../context/reducer'\n\nconst Transaction = ({txData}: {txData: ITransaction}) => {\n return (\n <div className=\"text-xs\">\n <div>\n id: {txData.txid.substring(0,5)}...\n </div> \n <div>\n timestamp: {txData.timestamp.toString().substring(0,10)}...\n </div>\n <div>\n txO: [\n {txData.vout.map((txO, index) => {\n return (\n <div key={index} className=\"pl2\">\n <TxOut txOData={txO}/>\n </div>\n )\n })}\n ]\n </div>\n <div>\n txIn: [\n {txData.vin.map((txIn, index) => {\n return (\n <div key={index} className=\"pl2\">\n <TxIn txInData={txIn}/>\n </div>\n )\n })}\n ]\n </div>\n </div> \n )\n}\n\nconst TxOut = ({txOData}: {txOData: ITxOutputs}) => {\n return (\n <div>\n <div>\n scriptPubKey: {formatKey(txOData.scriptPubKey)}\n </div>\n <div>\n value: {txOData.value}\n </div>\n </div>\n )\n}\n\nconst TxIn = ({txInData}: {txInData: ITxInputs}) => {\n return (\n <div>\n <div>\n txid: {txInData.txid}\n </div>\n <div>\n vout: {txInData.vout}\n </div>\n <div>\n scriptSig: {txInData.scriptSig.substring(0,5)} ...\n </div>\n </div>\n )\n}\n\nexport const formatKey : (key: string) => string = (key: string) => {\n return(\n `${key.substring(0,5)}...`\n )\n}\n\nexport default Transaction"],"sourceRoot":""}