Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query API examples in Reporting #1958

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions centrifuge-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^3.1.4",
"react-graphql-syntax-highlighter": "^0.0.4",
"react-helmet-async": "^1.3.0",
"react-pdf": "^6.2.2",
"react-query": "^3.39.1",
Expand Down
177 changes: 177 additions & 0 deletions centrifuge-app/src/components/Report/QueryDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { AnchorButton, Box, Dialog, Shelf, TextInput, Text, Tabs, TabsItem } from '@centrifuge/fabric'
import * as React from 'react'
import { Report } from './ReportContext'
import { Pool } from '@centrifuge/centrifuge-js'
import { usePoolMetadata } from '../../utils/usePools'
import { GraphQLCodeBlock } from 'react-graphql-syntax-highlighter';
import 'react-graphql-syntax-highlighter/dist/style.css';
import styled from 'styled-components'

type Props = {
open: boolean
onClose: () => void
report: Report
pool: Pool
}

const reportNameMapping = {
'investor-tx': 'investor transactions',
'asset-tx': 'asset transactions',
'pool-balance': 'pool balance',
'asset-list': 'asset list',
'holders': 'holders'
}

const reportCodeMapping = (poolId: string) => {
return {
'investor-tx': `query {
investorTransactions(
orderBy: TIMESTAMP_ASC,
filter: {
poolId: { equalTo: "${poolId}" }
}) {
nodes {
id
timestamp
accountId
account {
chainId
evmAddress
}
poolId
trancheId
epochNumber
type
tokenAmount
currencyAmount
tokenPrice
transactionFee
}
}
}`,
'asset-tx': `query {
borrowerTransactions(
orderBy: TIMESTAMP_ASC,
filter: {
poolId: { equalTo: "${poolId}" }
}) {
nodes {
loanId
epochId
type
timestamp
amount
settlementPrice
quantity
}
}
}
`,
'pool-balance': `TODO`,
'asset-list': `TODO`,
'holders': `query {
trancheBalances(
filter: {
poolId: { equals: "${poolId}" }
}) {
nodes {
accountId
account {
chainId
evmAddress
}
pendingInvestCurrency
claimableTrancheTokens
sumClaimedTrancheTokens
pendingRedeemTrancheTokens
claimableCurrency
sumClaimedCurrency
}
}

currencyBalances(
filter: {
currency: { poolId: { equals: "${poolId}" } }
}) {
nodes {
accountId
account {
chainId
evmAddress
}
currencyId
amount
}
}
}`
}
}

const GraphqlCode = styled(Box)`
background: #efefef;
padding: 20px;
max-height: 250px;
overflow-y: auto;
`

export const QueryDialog: React.FC<Props> = ({ open, onClose, report, pool }) => {
const { data: poolMetadata } = usePoolMetadata(pool)
const [tab, setTab] = React.useState<number>(0)

function close() {
onClose()
}

return (
<Dialog isOpen={open} onClose={close} title={`Query ${reportNameMapping[report]} using API`} subtitle={`Use GraphQL to get access to a live feed of the underlying data of ${poolMetadata?.pool?.name}`}>
<Tabs
selectedIndex={tab}
onChange={(index) => setTab(index)}
>
<TabsItem>Manually</TabsItem>
<TabsItem>cURL</TabsItem>
</Tabs>

{tab === 0 ? (<>
You can run the following query:
<GraphqlCode>
<GraphQLCodeBlock src={reportCodeMapping(pool.id)[report]} />
</GraphqlCode>

On this API endpoint:
<Shelf>
<Box flex={1}>
<TextInput
value={import.meta.env.REACT_APP_SUBQUERY_URL as string}
/>
</Box>
<Box ml="12px">
<AnchorButton variant="secondary" small>
Copy
</AnchorButton>
</Box>
</Shelf>
</>) : (<>
<GraphqlCode>
curl -g -X POST \<br/>
&nbsp; -H "Content-Type: application/json" \<br/>
&nbsp; -d '&#123;"query": "{reportCodeMapping(pool.id)[report].replace(/(\r\n|\n|\r)/gm, "").replace(/[\""]/g, '\\"') }" &#125;' \<br/>
Dismissed Show dismissed Hide dismissed
&nbsp; {import.meta.env.REACT_APP_SUBQUERY_URL as string}
</GraphqlCode>
</>)}

<Text as="p" variant="body3" textAlign="center">
For more information, you can refer to the {' '}
<Text
as="a"
href="https://docs.centrifuge.io/"
target="_blank"
rel="noopener noreferrer"
textDecoration="underline"
>
API documentation
</Text>
</Text>
</Dialog>
)
}
9 changes: 9 additions & 0 deletions centrifuge-app/src/components/Report/ReportContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export type ReportContextType = {
csvData?: CsvDataProps
setCsvData: (data?: CsvDataProps) => void

queryDialogOpen: boolean
setQueryDialogOpen: (open: boolean) => void

startDate: Date
setStartDate: (date: Date) => void

Expand Down Expand Up @@ -42,6 +45,9 @@ const defaultContext = {
csvData: undefined,
setCsvData() {},

queryDialogOpen: false,
setQueryDialogOpen() {},

startDate: new Date(),
setStartDate() {},

Expand All @@ -68,6 +74,7 @@ export const ReportContext = React.createContext<ReportContextType>(defaultConte

export function ReportContextProvider({ children }: { children: React.ReactNode }) {
const [csvData, setCsvData] = React.useState<CsvDataProps | undefined>(undefined)
const [queryDialogOpen, setQueryDialogOpen] = React.useState(false)

// Global filters
const [startDate, setStartDate] = React.useState(defaultContext.startDate)
Expand All @@ -85,6 +92,8 @@ export function ReportContextProvider({ children }: { children: React.ReactNode
value={{
csvData,
setCsvData,
queryDialogOpen,
setQueryDialogOpen,
startDate,
setStartDate,
endDate,
Expand Down
15 changes: 15 additions & 0 deletions centrifuge-app/src/components/Report/ReportFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { AnchorButton, Box, DateRange, Select, Shelf } from '@centrifuge/fabric'
import * as React from 'react'
import { useDebugFlags } from '../DebugFlags'
import { GroupBy, InvestorTxType, Report, ReportContext } from './ReportContext'
import { QueryDialog } from './QueryDialog'

type ReportFilterProps = {
pool: Pool
Expand All @@ -14,6 +15,8 @@ export function ReportFilter({ pool }: ReportFilterProps) {
const {
csvData,
setStartDate,
queryDialogOpen,
setQueryDialogOpen,
endDate,
setEndDate,
range,
Expand Down Expand Up @@ -157,10 +160,22 @@ export function ReportFilter({ pool }: ReportFilterProps) {
/>
)}
<Box ml="auto">
<AnchorButton variant="secondary" small onClick={() => setQueryDialogOpen(true)} disabled={!csvData}>
Query API
</AnchorButton>
</Box>
<Box>
<AnchorButton href={csvData?.dataUrl} download={csvData?.fileName} variant="primary" small disabled={!csvData}>
Export CSV
</AnchorButton>
</Box>

<QueryDialog
open={queryDialogOpen}
report={report}
pool={pool}
onClose={() => setQueryDialogOpen(false)}
/>
</Shelf>
)
}
Loading
Loading