feat: add apollolink split to query both lamassu and pazuz apollo servers

feat: integrate accounting with pazuz related screens
This commit is contained in:
Sérgio Salgado 2021-10-12 19:03:41 +01:00
parent 16513a8238
commit 9260e4a698
5 changed files with 314 additions and 193 deletions

View file

@ -97,8 +97,8 @@
"storybook": "start-storybook -p 9009 -s public",
"postinstall": "patch-package",
"build-storybook": "build-storybook -s public",
"start-lamassu": "REACT_APP_BUILD_TARGET=LAMASSU react-scripts start",
"start-pazuz": "REACT_APP_BUILD_TARGET=PAZUZ react-scripts start"
"lamassu": "REACT_APP_BUILD_TARGET=LAMASSU react-scripts start",
"pazuz": "REACT_APP_BUILD_TARGET=PAZUZ react-scripts start"
},
"browserslist": {
"production": [

View file

@ -1,9 +1,12 @@
import { useQuery } from '@apollo/react-hooks'
import { Paper } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import classnames from 'classnames'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React from 'react'
import React, { useContext } from 'react'
import AppContext from 'src/AppContext'
import TitleSection from 'src/components/layout/TitleSection'
import { H3, Info2, Label2, Label3, P } from 'src/components/typography'
import { ReactComponent as BitcoinLogo } from 'src/styling/logos/icon-bitcoin-colour.svg'
@ -17,6 +20,37 @@ import styles from './ATMWallet.styles'
const useStyles = makeStyles(styles)
const GET_OPERATOR_BY_USERNAME = gql`
query operatorByUsername($username: String) {
operatorByUsername(username: $username) {
id
entityId
name
fiatBalances
cryptoBalances
machines
joined
assetValue
preferredFiatCurrency
contactInfo {
name
email
}
fundings {
id
origin
destination
fiatAmount
fiatBalanceAfter
fiatCurrency
created
status
description
}
}
}
`
const CHIPS_PER_ROW = 6
const Assets = ({ balance, wallets, currency }) => {
@ -35,7 +69,7 @@ const Assets = ({ balance, wallets, currency }) => {
{balance.toLocaleString('en-US', { maximumFractionDigits: 2 })}
</Info2>
<Info2 noMargin className={classes.fieldCurrency}>
{currency}
{R.toUpper(currency)}
</Info2>
</div>
</div>
@ -49,7 +83,7 @@ const Assets = ({ balance, wallets, currency }) => {
})}
</Info2>
<Info2 noMargin className={classes.fieldCurrency}>
{currency}
{R.toUpper(currency)}
</Info2>
</div>
</div>
@ -61,7 +95,7 @@ const Assets = ({ balance, wallets, currency }) => {
{balance.toLocaleString('en-US', { maximumFractionDigits: 2 })}
</Info2>
<Info2 noMargin className={classes.fieldCurrency}>
{currency}
{R.toUpper(currency)}
</Info2>
</div>
</div>
@ -129,56 +163,71 @@ const WalletInfoChip = ({ wallet, currency }) => {
const ATMWallet = () => {
const classes = useStyles({ numberOfChips: CHIPS_PER_ROW })
const { userData } = useContext(AppContext)
const { data, loading } = useQuery(GET_OPERATOR_BY_USERNAME, {
context: { clientName: 'pazuz' },
variables: { username: userData?.username }
})
const operatorData = R.path(['operatorByUsername'], data)
const wallets = [
{
cryptoCode: 'BTC',
name: 'Bitcoin',
amount: 2.7,
fiatValue: 81452,
amount: operatorData?.cryptoBalances.xbt ?? 0,
fiatValue: 0,
isHedged: true
},
{
cryptoCode: 'ETH',
name: 'Ethereum',
amount: 4.1,
fiatValue: 4924,
amount: operatorData?.cryptoBalances.eth ?? 0,
fiatValue: 0,
isHedged: true
},
{
cryptoCode: 'LTC',
name: 'Litecoin',
amount: 15,
fiatValue: 3016,
amount: operatorData?.cryptoBalances.ltc ?? 0,
fiatValue: 0,
isHedged: true
},
{
cryptoCode: 'ZEC',
name: 'Z-Cash',
amount: 20,
fiatValue: 2887,
amount: operatorData?.cryptoBalances.zec ?? 0,
fiatValue: 0,
isHedged: false
},
{
cryptoCode: 'BCH',
name: 'Bitcoin Cash',
amount: 10.7,
fiatValue: 7074,
amount: operatorData?.cryptoBalances.bch ?? 0,
fiatValue: 0,
isHedged: true
},
{
cryptoCode: 'DASH',
name: 'Dash',
amount: 10.7,
fiatValue: 1091,
amount: operatorData?.cryptoBalances.dash ?? 0,
fiatValue: 0,
isHedged: false
}
]
return (
!loading && (
<>
<TitleSection title="ATM Wallets" />
<Assets balance={8952} wallets={wallets} currency={'USD'} />
<Assets
balance={
operatorData.fiatBalances[operatorData.preferredFiatCurrency]
}
wallets={wallets}
currency={operatorData.preferredFiatCurrency}
/>
<H3 className={classes.walletChipTitle}>ATM Wallets</H3>
<div className={classes.walletChipList}>
{R.map(
@ -190,6 +239,7 @@ const ATMWallet = () => {
</div>
</>
)
)
}
export default ATMWallet

View file

@ -1,7 +1,11 @@
import { useQuery } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core/styles'
import gql from 'graphql-tag'
import moment from 'moment'
import React from 'react'
import * as R from 'ramda'
import React, { useContext } from 'react'
import AppContext from 'src/AppContext'
import { Tooltip } from 'src/components/Tooltip'
import TitleSection from 'src/components/layout/TitleSection'
import DataTable from 'src/components/tables/DataTable'
@ -9,47 +13,42 @@ import { H4, Info2, P } from 'src/components/typography'
import styles from './Accounting.styles'
const mockData = [
{
operation: 'Hedging summary',
direction: 'in',
extraInfo: 'This is mocked information',
amount: 486,
currency: 'USD',
balanceAfterTx: 10438,
date: '2021-02-22T20:16:12.020Z'
},
{
operation: 'Funding transaction',
direction: 'in',
amount: 2000,
currency: 'USD',
balanceAfterTx: 9952,
date: '2021-02-22T12:40:32.020Z'
},
{
operation: 'ZEC hot wallet top up',
direction: 'out',
amount: 1000,
currency: 'USD',
balanceAfterTx: 7952,
date: '2021-02-21T16:30:44.020Z'
},
{
operation: 'Funding transaction',
direction: 'in',
amount: 8000,
currency: 'USD',
balanceAfterTx: 8952,
date: '2021-02-21T08:16:20.020Z'
}
]
const formatCurrency = amount =>
amount.toLocaleString('en-US', { maximumFractionDigits: 2 })
const useStyles = makeStyles(styles)
const GET_OPERATOR_BY_USERNAME = gql`
query operatorByUsername($username: String) {
operatorByUsername(username: $username) {
id
entityId
name
fiatBalances
cryptoBalances
machines
joined
assetValue
preferredFiatCurrency
contactInfo {
name
email
}
fundings {
id
origin
destination
fiatAmount
fiatBalanceAfter
fiatCurrency
created
status
description
}
}
}
`
const Assets = ({ balance, hedgingReserve, currency }) => {
const classes = useStyles()
@ -62,7 +61,7 @@ const Assets = ({ balance, hedgingReserve, currency }) => {
{formatCurrency(balance)}
</Info2>
<Info2 noMargin className={classes.fieldCurrency}>
{currency}
{R.toUpper(currency)}
</Info2>
</div>
</div>
@ -74,7 +73,7 @@ const Assets = ({ balance, hedgingReserve, currency }) => {
{formatCurrency(hedgingReserve)}
</Info2>
<Info2 noMargin className={classes.fieldCurrency}>
{currency}
{R.toUpper(currency)}
</Info2>
</div>
</div>
@ -86,7 +85,7 @@ const Assets = ({ balance, hedgingReserve, currency }) => {
{formatCurrency(balance - hedgingReserve)}
</Info2>
<Info2 noMargin className={classes.fieldCurrency}>
{currency}
{R.toUpper(currency)}
</Info2>
</div>
</div>
@ -96,6 +95,14 @@ const Assets = ({ balance, hedgingReserve, currency }) => {
const Accounting = () => {
const classes = useStyles()
const { userData } = useContext(AppContext)
const { data, loading } = useQuery(GET_OPERATOR_BY_USERNAME, {
context: { clientName: 'pazuz' },
variables: { username: userData?.username }
})
const operatorData = R.path(['operatorByUsername'], data)
const elements = [
{
@ -106,7 +113,7 @@ const Accounting = () => {
view: it => {
return (
<span className={classes.operation}>
{it.operation}
{it.description}
{!!it.extraInfo && (
<Tooltip width={175}>
<P>{it.extraInfo}</P>
@ -122,18 +129,15 @@ const Accounting = () => {
size: 'sm',
textAlign: 'right',
view: it =>
`${
it.direction === 'in'
? formatCurrency(it.amount)
: formatCurrency(-it.amount)
} ${it.currency}`
`${formatCurrency(it.fiatAmount)} ${R.toUpper(it.fiatCurrency)}`
},
{
header: 'Balance after operation',
width: 250,
size: 'sm',
textAlign: 'right',
view: it => `${formatCurrency(it.balanceAfterTx)} ${it.currency}`
view: it =>
`${formatCurrency(it.fiatBalanceAfter)} ${R.toUpper(it.fiatCurrency)}`
},
{
header: 'Date',
@ -152,19 +156,27 @@ const Accounting = () => {
]
return (
!loading && (
<>
<TitleSection title="Accounting" />
<Assets balance={10438} hedgingReserve={1486} currency={'USD'} />
<Assets
balance={
operatorData.fiatBalances[operatorData.preferredFiatCurrency]
}
hedgingReserve={operatorData.hedgingReserve ?? 0}
currency={operatorData.preferredFiatCurrency}
/>
<H4 className={classes.tableTitle}>Fiat balance history</H4>
<DataTable
loading={false}
emptyText="No transactions so far"
elements={elements}
data={mockData}
data={operatorData.fundings ?? []}
rowSize="sm"
/>
</>
)
)
}
export default Accounting

View file

@ -1,3 +1,4 @@
import { useQuery } from '@apollo/react-hooks'
import Grid from '@material-ui/core/Grid'
import Table from '@material-ui/core/Table'
import TableBody from '@material-ui/core/TableBody'
@ -6,78 +7,47 @@ import TableContainer from '@material-ui/core/TableContainer'
import TableHead from '@material-ui/core/TableHead'
import TableRow from '@material-ui/core/TableRow'
import { makeStyles, withStyles } from '@material-ui/core/styles'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React from 'react'
import React, { useContext } from 'react'
import AppContext from 'src/AppContext'
import TitleSection from 'src/components/layout/TitleSection'
import { H4, Label2, P, Info2 } from 'src/components/typography'
import styles from './Assets.styles'
const useStyles = makeStyles(styles)
const mockData = [
{
id: 'fiatBalance',
display: 'Fiat balance',
amount: 10438,
currency: 'USD',
class: 'Available balance'
},
{
id: 'hedgingReserve',
display: 'Hedging reserve',
amount: -1486,
currency: 'USD',
class: 'Available balance',
direction: 'out'
},
{
id: 'hedgedWalletAssets',
display: 'Hedged wallet assets',
amount: 96446,
currency: 'USD',
class: 'Wallet assets',
direction: 'in'
},
{
id: 'unhedgedWalletAssets',
display: 'Unhedged wallet assets',
amount: 3978,
currency: 'USD',
class: 'Wallet assets',
direction: 'in'
const GET_OPERATOR_BY_USERNAME = gql`
query operatorByUsername($username: String) {
operatorByUsername(username: $username) {
id
entityId
name
fiatBalances
cryptoBalances
machines
joined
assetValue
preferredFiatCurrency
contactInfo {
name
email
}
]
const mockDataTotal = [
{
id: 'fiatBalance',
display: 'Fiat balance',
amount: 10438,
currency: 'USD'
},
{
id: 'hedgingReserve',
display: 'Hedging reserve',
amount: -1486,
currency: 'USD',
direction: 'out'
},
{
id: 'hedgedWalletAssets',
display: 'Market value of hedged wallet assets',
amount: 94980,
currency: 'USD',
direction: 'in'
},
{
id: 'unhedgedWalletAssets',
display: 'Unhedged wallet assets',
amount: 3978,
currency: 'USD',
direction: 'in'
fundings {
id
origin
destination
fiatAmount
fiatBalanceAfter
fiatCurrency
created
status
description
}
]
}
}
`
const cellStyling = {
borderBottom: '4px solid white',
@ -163,11 +133,89 @@ const formatCurrency = amount =>
const Assets = () => {
const classes = useStyles()
const { userData } = useContext(AppContext)
const filterByClass = x =>
R.filter(it => R.path(['class'])(it) === x)(mockData)
const { data, loading } = useQuery(GET_OPERATOR_BY_USERNAME, {
context: { clientName: 'pazuz' },
variables: { username: userData?.username }
})
const operatorData = R.path(['operatorByUsername'], data)
console.log('operatorData', operatorData)
const balanceData = [
{
id: 'fiatBalance',
display: 'Fiat balance',
amount:
operatorData?.fiatBalances[operatorData?.preferredFiatCurrency] ?? 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
class: 'Available balance'
},
{
id: 'hedgingReserve',
display: 'Hedging reserve',
amount:
operatorData?.fiatBalances[operatorData?.preferredFiatCurrency] ?? 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
class: 'Available balance',
direction: 'out'
}
]
const walletData = [
{
id: 'hedgedWalletAssets',
display: 'Hedged wallet assets',
amount: 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
class: 'Wallet assets',
direction: 'in'
},
{
id: 'unhedgedWalletAssets',
display: 'Unhedged wallet assets',
amount: 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
class: 'Wallet assets',
direction: 'in'
}
]
const totalData = [
{
id: 'fiatBalance',
display: 'Fiat balance',
amount:
operatorData?.fiatBalances[operatorData?.preferredFiatCurrency] ?? 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? '')
},
{
id: 'hedgingReserve',
display: 'Hedging reserve',
amount: 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
direction: 'out'
},
{
id: 'hedgedWalletAssets',
display: 'Market value of hedged wallet assets',
amount: 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
direction: 'in'
},
{
id: 'unhedgedWalletAssets',
display: 'Unhedged wallet assets',
amount: 0,
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
direction: 'in'
}
]
return (
!loading && (
<>
<TitleSection title="Balance sheet" />
<div className={classes.root}>
@ -177,15 +225,15 @@ const Assets = () => {
<div className={classes.leftSide}>
<AssetsAmountTable
title="Available balance"
data={filterByClass('Available balance')}
numToRender={mockData.length}
data={balanceData}
numToRender={balanceData.length}
/>
</div>
<div className={classes.leftSide}>
<AssetsAmountTable
title="Wallet assets"
data={filterByClass('Wallet assets')}
numToRender={mockData.length}
data={walletData}
numToRender={walletData.length}
/>
</div>
</Grid>
@ -195,8 +243,8 @@ const Assets = () => {
<div className={classes.rightSide}>
<AssetsAmountTable
title="Total assets"
data={mockDataTotal}
numToRender={mockDataTotal.length}
data={totalData}
numToRender={totalData.length}
/>
</div>
</Grid>
@ -205,6 +253,7 @@ const Assets = () => {
</div>
</>
)
)
}
export default Assets

View file

@ -12,6 +12,9 @@ import AppContext from 'src/AppContext'
const URI =
process.env.NODE_ENV === 'development' ? 'https://localhost:8070' : ''
const ALT_URI =
process.env.NODE_ENV === 'development' ? 'http://localhost:4001' : ''
const getClient = (history, location, getUserData, setUserData, setRole) =>
new ApolloClient({
link: ApolloLink.from([
@ -43,10 +46,17 @@ const getClient = (history, location, getUserData, setUserData, setRole) =>
return response
})
}),
ApolloLink.split(
operation => operation.getContext().clientName === 'pazuz',
new HttpLink({
credentials: 'include',
uri: `${ALT_URI}/graphql`
}),
new HttpLink({
credentials: 'include',
uri: `${URI}/graphql`
})
)
]),
cache: new InMemoryCache(),
defaultOptions: {