Skip to content

Commit

Permalink
add useCentrifugeQuery hook
Browse files Browse the repository at this point in the history
  • Loading branch information
onnovisser committed Dec 10, 2024
1 parent 5e8ca4a commit 3b6a0f4
Show file tree
Hide file tree
Showing 12 changed files with 588 additions and 276 deletions.
11 changes: 6 additions & 5 deletions sdk-consumer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
"preview": "vite preview"
},
"dependencies": {
"@centrifuge/centrifuge-sdk": "portal:/Users/kattybarroso/desktop/centrifuge/centrifuge-sdk",
"@centrifuge/fabric": "workspace:*",
"@centrifuge/sdk": "0.0.0-alpha.0",
"@talismn/wagmi-connector": "^0.3.1",
"@tanstack/react-query": "^5.59.16",
"@wagmi/core": "^2.14.1",
"ethers": "^6.13.4",
"@wagmi/core": "^2.15.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"viem": "2.x",
"wagmi": "latest"
"rxjs": "^7.8.1",
"viem": "^2.21.54",
"wagmi": "^2.13.3"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
Expand Down
17 changes: 11 additions & 6 deletions sdk-consumer/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FabricProvider, centrifugeTheme } from '@centrifuge/fabric'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'

import { WagmiProvider, useAccount } from 'wagmi'
import { TransactionProvider } from './components/Transactions/TransactionsProvider'
import { Account } from './components/account'
import { WalletOptions } from './components/wallet-options'
import { wagmiConfig } from './config/wagmiConfig'
Expand All @@ -15,11 +16,15 @@ function ConnectWallet() {

function App() {
return (
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<ConnectWallet />
</QueryClientProvider>
</WagmiProvider>
<FabricProvider theme={centrifugeTheme}>
<TransactionProvider>
<WagmiProvider config={wagmiConfig}>
<QueryClientProvider client={queryClient}>
<ConnectWallet />
</QueryClientProvider>
</WagmiProvider>
</TransactionProvider>
</FabricProvider>
)
}

Expand Down
2 changes: 2 additions & 0 deletions sdk-consumer/src/centrifuge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Centrifuge from '@centrifuge/sdk'
export const centrifuge = new Centrifuge({ environment: 'demo' })
66 changes: 66 additions & 0 deletions sdk-consumer/src/components/Transactions/TransactionToasts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { Stack, Toast, ToastStatus } from '@centrifuge/fabric'
import { useTransactions } from './TransactionsProvider'

const toastStatus: { [key: string]: ToastStatus } = {
creating: 'pending',
unconfirmed: 'pending',
pending: 'pending',
succeeded: 'ok',
failed: 'critical',
}

const toastSublabel = {
creating: 'Creating transaction',
unconfirmed: 'Signing transaction',
pending: 'Transaction pending',
succeeded: 'Transaction successful',
failed: 'Transaction failed',
}

const TOAST_DURATION = 10000
const ERROR_TOAST_DURATION = 60000

export type TransactionToastsProps = {
positionProps?: {
top?: number | string
right?: number | string
bottom?: number | string
left?: number | string
width?: number | string
zIndex?: number | string
}
}

export function TransactionToasts({
positionProps = {
top: 64,
right: 1,
},
}: TransactionToastsProps) {
const { transactions, updateTransaction } = useTransactions()

const dismiss = (txId: string) => () => updateTransaction(txId, { dismissed: true })

return (
<Stack gap={2} position="fixed" width={330} zIndex="onTopOfTheWorld" {...positionProps}>
{transactions
.filter((tx) => !tx.dismissed && !['creating', 'unconfirmed'].includes(tx.status))
.map((tx) => {
return (
<Toast
label={tx.title}
sublabel={(tx.status === 'failed' && tx.failedReason) || toastSublabel[tx.status]}
status={toastStatus[tx.status]}
onDismiss={dismiss(tx.id)}
onStatusChange={(newStatus) => {
if (['ok', 'critical'].includes(newStatus)) {
setTimeout(dismiss(tx.id), newStatus === 'ok' ? TOAST_DURATION : ERROR_TOAST_DURATION)
}
}}
key={tx.id}
/>
)
})}
</Stack>
)
}
83 changes: 83 additions & 0 deletions sdk-consumer/src/components/Transactions/TransactionsProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import * as React from 'react'
import { TransactionToasts } from './TransactionToasts'

export type TransactionStatus = 'creating' | 'unconfirmed' | 'pending' | 'succeeded' | 'failed'
export type Transaction = {
id: string
title: string
status: TransactionStatus
hash?: string
result?: any
failedReason?: string
error?: any
dismissed?: boolean
}

type TransactionsContextType = {
transactions: Transaction[]
addTransaction: (tx: Transaction) => void
addOrUpdateTransaction: (tx: Transaction) => void
updateTransaction: (id: string, update: Partial<Transaction> | ((prev: Transaction) => Partial<Transaction>)) => void
}

const TransactionsContext = React.createContext<TransactionsContextType>(null as any)

type TransactionProviderProps = {
children: React.ReactNode
}

export function TransactionProvider({ children }: TransactionProviderProps) {
const [transactions, setTransactions] = React.useState<Transaction[]>([])

const addTransaction = React.useCallback((tx: Transaction) => {
setTransactions((prev) => [...prev, tx])
}, [])

const updateTransaction = React.useCallback(
(id: string, update: Partial<Transaction> | ((prev: Transaction) => Partial<Transaction>)) => {
setTransactions((prev) =>
prev.map((tx) =>
tx.id === id ? { ...tx, dismissed: false, ...(typeof update === 'function' ? update(tx) : update) } : tx
)
)
},
[]
)

const addOrUpdateTransaction = React.useCallback((tx: Transaction) => {
setTransactions((prev) => {
if (prev.find((t) => t.id === tx.id)) {
return prev.map((t) => (t.id === tx.id ? { ...t, dismissed: false, ...tx } : t))
}
return [...prev, tx]
})
}, [])

const ctx: TransactionsContextType = React.useMemo(
() => ({
transactions,
addTransaction,
updateTransaction,
addOrUpdateTransaction,
}),
[transactions, addTransaction, updateTransaction, addOrUpdateTransaction]
)

return (
<TransactionsContext.Provider value={ctx}>
{children}
<TransactionToasts />
</TransactionsContext.Provider>
)
}

export function useTransactions() {
const ctx = React.useContext(TransactionsContext)
if (!ctx) throw new Error('useTransactions must be used within Provider')
return ctx
}

export function useTransaction(id?: string) {
const { transactions } = useTransactions()
return id ? transactions.find((tx) => tx.id === id) : null
}
6 changes: 3 additions & 3 deletions sdk-consumer/src/components/account.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { useAccount, useDisconnect, useEnsName } from 'wagmi'
import { useAccountBalance } from '../hooks/useAccountbalance'
import { useAccountBalance } from '../hooks/useAccount'

export function Account() {
const { address } = useAccount()
const { disconnect } = useDisconnect()
const { data: ensName } = useEnsName({ address })
const balance = useAccountBalance()
const { data: balance } = useAccountBalance()

return (
<div>
{address && <div>{ensName ? `${ensName} (${address})` : address}</div>}
<h1>Your balance is {balance !== null ? balance.toString() : 'Loading...'}</h1>
<h1>Your balance is {balance?.toFloat() ?? 'Loading...'}</h1>
<button onClick={() => disconnect()}>Disconnect</button>
</div>
)
Expand Down
7 changes: 3 additions & 4 deletions sdk-consumer/src/config/wagmiConfig.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { createConfig, http } from 'wagmi'
import { base, mainnet } from 'wagmi/chains'
import { sepolia } from 'wagmi/chains'
import { injected } from 'wagmi/connectors'

export const wagmiConfig = createConfig({
chains: [mainnet, base],
chains: [sepolia],
connectors: [injected()],
transports: {
[mainnet.id]: http(),
[base.id]: http(),
[sepolia.id]: http(),
},
})
13 changes: 13 additions & 0 deletions sdk-consumer/src/hooks/useAccount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useMemo } from 'react'
import { useAccount } from 'wagmi'
import { centrifuge } from '../centrifuge'
import { useCentrifugeQuery } from './useCentrifugeQuery'

const tUSD = '0x8503b4452Bf6238cC76CdbEE223b46d7196b1c93'

export function useAccountBalance() {
const { address } = useAccount()
const balance$ = useMemo(() => (address ? centrifuge.balance(tUSD, address) : undefined), [address])
console.log('balance$', balance$)
return useCentrifugeQuery(balance$)
}
42 changes: 0 additions & 42 deletions sdk-consumer/src/hooks/useAccountbalance.ts

This file was deleted.

Loading

0 comments on commit 3b6a0f4

Please sign in to comment.