use solana connector

This commit is contained in:
thesn10
2026-05-23 01:51:34 +02:00
parent b56bada0fa
commit b4cea41a93
14 changed files with 915 additions and 5466 deletions

3
.gitignore vendored
View File

@@ -10,3 +10,6 @@ test-ledger
spec.md
app_old
connectorkit
create-solana-dapp-template

View File

@@ -4,7 +4,6 @@ const nextConfig: NextConfig = {
transpilePackages: [
'@tamagui/lucide-icons-2',
'@descro/sdk',
'@solana/wallet-adapter-react-ui',
],
turbopack: {
resolveAlias: {

View File

@@ -9,10 +9,7 @@
"dependencies": {
"@coral-xyz/anchor": "^0.32.1",
"@descro/sdk": "workspace:*",
"@solana/wallet-adapter-base": "^0.9.27",
"@solana/wallet-adapter-react": "^0.15.39",
"@solana/wallet-adapter-react-ui": "^0.9.39",
"@solana/wallet-adapter-wallets": "^0.19.38",
"@solana/connector": "^0.2.4",
"@solana/web3.js": "^1.98.4",
"@tamagui/config": "^2.0.0-rc.42",
"@tamagui/next-theme": "^2.0.0-rc.42",

View File

@@ -1,54 +1,37 @@
'use client'
import React, { useCallback, useMemo, useState } from 'react'
import { ConnectionProvider, WalletProvider } from '@solana/wallet-adapter-react'
import { WalletAdapterNetwork, type WalletError } from '@solana/wallet-adapter-base'
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui'
import { clusterApiUrl } from '@solana/web3.js'
import { UnsafeBurnerWalletAdapter } from '@solana/wallet-adapter-wallets'
import type { ReactNode } from 'react'
import { useMemo } from 'react'
import { AppProvider } from '@solana/connector/react'
import { getDefaultConfig } from '@solana/connector/headless'
export type Network = 'devnet' | 'localnet'
interface NetworkContextValue {
network: WalletAdapterNetwork
setNetwork: (n: WalletAdapterNetwork) => void
function getOrigin() {
if (typeof window !== 'undefined') return window.location.origin
return 'http://localhost:3000'
}
export const NetworkContext = React.createContext<NetworkContextValue>({
network: WalletAdapterNetwork.Devnet,
setNetwork: () => undefined,
})
export function WalletProviders({ children }: { children: React.ReactNode }) {
const [network, setNetwork] = useState<WalletAdapterNetwork>(WalletAdapterNetwork.Devnet)
const endpoint = useMemo(
export function WalletProviders({ children }: { children: ReactNode }) {
const connectorConfig = useMemo(
() =>
(network as string) === 'localnet'
? 'http://localhost:8899'
: clusterApiUrl(network),
[network],
);
const wallets = useMemo(
() => network as string === 'localnet' ? [new UnsafeBurnerWalletAdapter()] : [],
// eslint-disable-next-line react-hooks/exhaustive-deps
[network]
);
const onError = useCallback((error: WalletError) => {
console.warn('[wallet]', error.name, error.message, error.error)
}, [])
return (
<NetworkContext.Provider value={{ network, setNetwork }}>
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={wallets} autoConnect onError={onError}>
<WalletModalProvider>
{children}
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
</NetworkContext.Provider>
getDefaultConfig({
appName: 'Descro',
appUrl: getOrigin(),
autoConnect: true,
clusters: [
{
id: 'solana:devnet' as const,
label: 'Devnet',
url: 'https://api.devnet.solana.com',
},
{
id: 'solana:localnet' as const,
label: 'Localnet',
url: 'http://localhost:8899',
},
],
}),
[],
)
return <AppProvider connectorConfig={connectorConfig}>{children}</AppProvider>
}

View File

@@ -1,5 +1,4 @@
import '../../public/tamagui.generated.css'
import '@solana/wallet-adapter-react-ui/styles.css'
import { Metadata } from 'next'
import { NextTamaguiProvider } from './NextTamaguiProvider'
import { WalletProviders } from './WalletProviders'

View File

@@ -1,6 +1,6 @@
'use client'
import { useContext, useState } from 'react'
import { useState } from 'react'
import { YStack, XStack, Text, Button, Spinner, Separator } from 'tamagui'
import { WalletButton } from '@/components/WalletButton'
import { CreateEscrowForm } from '@/components/CreateEscrowForm'
@@ -8,14 +8,12 @@ import { EscrowCard } from '@/components/EscrowCard'
import { EscrowDetail } from '@/components/EscrowDetail'
import { ResolverPanel } from '@/components/ResolverPanel'
import { useEscrows } from '@/hooks/useEscrows'
import { NetworkContext } from './WalletProviders'
import type { Network } from './WalletProviders'
import { useWallet, useCluster } from '@solana/connector/react'
import type { EscrowAccountWithPda } from '@descro/sdk'
import { useWallet } from '@solana/wallet-adapter-react'
export default function PlaygroundPage() {
const { network, setNetwork } = useContext(NetworkContext)
const { publicKey } = useWallet()
const { cluster, clusters, setCluster, isDevnet } = useCluster()
const { account } = useWallet()
const { escrows, loading, error, refresh } = useEscrows()
const [selected, setSelected] = useState<EscrowAccountWithPda | null>(null)
const [showResolvers, setShowResolvers] = useState(false)
@@ -43,8 +41,8 @@ export default function PlaygroundPage() {
Network:
</Text>
<select
value={network}
onChange={(e) => setNetwork(e.target.value as Network)}
value={cluster?.id ?? ''}
onChange={(e) => setCluster(e.target.value as never)}
style={{
padding: '6px 10px',
borderRadius: 6,
@@ -53,12 +51,15 @@ export default function PlaygroundPage() {
cursor: 'pointer',
}}
>
<option value="devnet">Devnet</option>
<option value="localnet">Localnet</option>
{clusters.map((c) => (
<option key={c.id} value={c.id}>
{c.label}
</option>
))}
</select>
</XStack>
{network === 'devnet' && (
{isDevnet && (
<a
href="https://faucet.solana.com/"
target="_blank"
@@ -100,7 +101,7 @@ export default function PlaygroundPage() {
</Button>
</XStack>
{!publicKey && (
{!account && (
<Text color="$color10" fontSize={13}>
Connect your wallet to see escrows.
</Text>
@@ -114,7 +115,7 @@ export default function PlaygroundPage() {
</XStack>
)}
{publicKey && !loading && escrows.length === 0 && (
{account && !loading && escrows.length === 0 && (
<Text color="$color10" fontSize={13}>
No escrows found for your wallet.
</Text>

View File

@@ -1,10 +1,11 @@
'use client'
import React, { useState } from 'react'
import { useState, useMemo } from 'react'
import { YStack, XStack, Text, Button, Input, Spinner } from 'tamagui'
import { useWallet, useConnection } from '@solana/wallet-adapter-react'
import { PublicKey, Transaction } from '@solana/web3.js'
import { PublicKey, Transaction, Connection } from '@solana/web3.js'
import { AnchorProvider } from '@coral-xyz/anchor'
import { useTransactionSigner, useDisconnectWallet, useCluster } from '@solana/connector/react'
import { useWalletAdapterCompat } from '@solana/connector/compat'
import BN from 'bn.js'
import { EscrowClient } from '@descro/sdk'
@@ -22,8 +23,17 @@ interface CreateEscrowFormProps {
}
export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) {
const { publicKey, sendTransaction, signTransaction } = useWallet()
const { connection } = useConnection()
const { signer } = useTransactionSigner()
const { disconnect } = useDisconnectWallet()
const { cluster } = useCluster()
const walletAdapter = useWalletAdapterCompat(signer, disconnect)
const connection = useMemo(
() => (cluster?.url ? new Connection(cluster.url, 'confirmed') : null),
[cluster?.url],
)
const publicKey = walletAdapter.publicKey ? new PublicKey(walletAdapter.publicKey.toString()) : null
const [buyer, setBuyer] = useState('')
const [amountSol, setAmountSol] = useState('')
@@ -37,7 +47,7 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) {
setError(null)
setSuccess(null)
if (!publicKey) {
if (!publicKey || !connection) {
setError('Connect your wallet first.')
return
}
@@ -70,8 +80,8 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) {
try {
const provider = new AnchorProvider(
connection,
{ publicKey, signTransaction: signTransaction! } as any,
{}
{ publicKey, signTransaction: walletAdapter.signTransaction!.bind(walletAdapter) } as never,
{},
)
const client = new EscrowClient(provider)
const escrowId = getNextEscrowId(publicKey.toBase58())
@@ -85,9 +95,10 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) {
escrowId,
})
const tx = new Transaction().add(ix)
const sig = await sendTransaction(tx, connection)
await connection.confirmTransaction(sig, 'confirmed')
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash()
const tx = new Transaction({ blockhash, lastValidBlockHeight, feePayer: publicKey }).add(ix)
const sig = await walletAdapter.sendTransaction(tx, connection)
await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, 'confirmed')
setSuccess(`Escrow #${escrowId.toString()} created! Tx: ${sig.slice(0, 16)}`)
setBuyer('')
@@ -112,7 +123,7 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) {
value={buyer}
onChangeText={setBuyer}
placeholder="Pubkey..."
fontFamily="monospace"
style={{ fontFamily: 'monospace' }}
fontSize={13}
/>
</YStack>
@@ -134,7 +145,7 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) {
value={resolver}
onChangeText={setResolver}
placeholder="Pubkey..."
fontFamily="monospace"
style={{ fontFamily: 'monospace' }}
fontSize={13}
/>
</YStack>

View File

@@ -1,17 +1,13 @@
'use client'
import React, { useState } from 'react'
import { useState, useMemo } from 'react'
import { YStack, XStack, Text, Button, Spinner, Separator } from 'tamagui'
import { useWallet, useConnection } from '@solana/wallet-adapter-react'
import { PublicKey, Transaction } from '@solana/web3.js'
import { PublicKey, Transaction, Connection } from '@solana/web3.js'
import { AnchorProvider } from '@coral-xyz/anchor'
import { useTransactionSigner, useDisconnectWallet, useCluster } from '@solana/connector/react'
import { useWalletAdapterCompat } from '@solana/connector/compat'
import { StatusBadge } from './StatusBadge'
import {
EscrowClient,
isAwaitingDeposit,
isActive,
isDisputed,
} from '@descro/sdk'
import { EscrowClient, isAwaitingDeposit, isActive, isDisputed } from '@descro/sdk'
import type { EscrowAccountWithPda } from '@descro/sdk'
import { useEscrowDetail } from '@/hooks/useEscrowDetail'
@@ -29,8 +25,18 @@ export function EscrowDetail({ item, onAction }: EscrowDetailProps) {
const { account, loading: detailLoading } = useEscrowDetail(pda)
const escrow = account ?? item.account
const { publicKey, sendTransaction, signTransaction } = useWallet()
const { connection } = useConnection()
const { signer } = useTransactionSigner()
const { disconnect } = useDisconnectWallet()
const { cluster } = useCluster()
const walletAdapter = useWalletAdapterCompat(signer, disconnect)
const connection = useMemo(
() => (cluster?.url ? new Connection(cluster.url, 'confirmed') : null),
[cluster?.url],
)
const publicKey = walletAdapter.publicKey ? new PublicKey(walletAdapter.publicKey.toString()) : null
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [success, setSuccess] = useState<string | null>(null)
@@ -39,13 +45,12 @@ export function EscrowDetail({ item, onAction }: EscrowDetailProps) {
const isSeller = publicKey?.equals(escrow.seller) ?? false
const isBuyer = publicKey?.equals(escrow.buyer) ?? false
const isResolver =
escrow.disputeResolver != null &&
publicKey?.equals(escrow.disputeResolver) === true
escrow.disputeResolver != null && publicKey?.equals(escrow.disputeResolver) === true
async function runTx(
buildFn: (client: EscrowClient) => Promise<import('@solana/web3.js').TransactionInstruction>
buildFn: (client: EscrowClient) => Promise<import('@solana/web3.js').TransactionInstruction>,
) {
if (!publicKey || !signTransaction) {
if (!publicKey || !connection || !walletAdapter.signTransaction) {
setError('Connect your wallet first.')
return
}
@@ -55,14 +60,15 @@ export function EscrowDetail({ item, onAction }: EscrowDetailProps) {
try {
const provider = new AnchorProvider(
connection,
{ publicKey, signTransaction } as any,
{}
{ publicKey, signTransaction: walletAdapter.signTransaction.bind(walletAdapter) } as never,
{},
)
const client = new EscrowClient(provider)
const ix = await buildFn(client)
const tx = new Transaction().add(ix)
const sig = await sendTransaction(tx, connection)
await connection.confirmTransaction(sig, 'confirmed')
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash()
const tx = new Transaction({ blockhash, lastValidBlockHeight, feePayer: publicKey }).add(ix)
const sig = await walletAdapter.sendTransaction(tx, connection)
await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, 'confirmed')
setSuccess(`Done! Tx: ${sig.slice(0, 20)}`)
onAction?.()
} catch (err: unknown) {
@@ -72,25 +78,21 @@ export function EscrowDetail({ item, onAction }: EscrowDetailProps) {
}
}
function handleDeposit() {
const handleDeposit = () =>
runTx((client) => client.buildDeposit({ buyer: publicKey!, escrowPda: pda }))
}
function handleCancel() {
const handleCancel = () =>
runTx((client) => client.buildCancel({ seller: publicKey!, escrowPda: pda }))
}
function handleComplete() {
const handleComplete = () =>
runTx((client) =>
client.buildComplete({ buyer: publicKey!, seller: escrow.seller, escrowPda: pda })
client.buildComplete({ buyer: publicKey!, seller: escrow.seller, escrowPda: pda }),
)
}
function handleDispute() {
const handleDispute = () =>
runTx((client) => client.buildDispute({ initiator: publicKey!, escrowPda: pda }))
}
function handleResolve(winner: 'buyer' | 'seller') {
const handleResolve = (winner: 'buyer' | 'seller') => {
const winnerPubkey = winner === 'buyer' ? escrow.buyer : escrow.seller
runTx((client) =>
client.buildResolve({
@@ -100,18 +102,14 @@ export function EscrowDetail({ item, onAction }: EscrowDetailProps) {
seller: escrow.seller,
escrowPda: pda,
disputeResolver: escrow.disputeResolver,
})
}),
)
}
void detailLoading
return (
<YStack
padding="$4"
borderRadius="$4"
borderWidth={1}
borderColor="$borderColor"
gap="$3"
>
<YStack padding="$4" borderRadius="$4" borderWidth={1} borderColor="$borderColor" gap="$3">
<XStack justifyContent="space-between" alignItems="center">
<Text fontSize={18} fontWeight="700">
Escrow #{escrow.escrowId.toString()}

View File

@@ -1,10 +1,11 @@
'use client'
import React, { useState, useEffect } from 'react'
import React, { useState, useEffect, useMemo } from 'react'
import { YStack, XStack, Text, Button, Input, Spinner, Separator } from 'tamagui'
import { useWallet, useConnection } from '@solana/wallet-adapter-react'
import { PublicKey, Transaction } from '@solana/web3.js'
import { PublicKey, Transaction, Connection } from '@solana/web3.js'
import { AnchorProvider } from '@coral-xyz/anchor'
import { useTransactionSigner, useDisconnectWallet, useCluster } from '@solana/connector/react'
import { useWalletAdapterCompat } from '@solana/connector/compat'
import { RegistryClient, resolverTypeLabel } from '@descro/sdk'
import type { ResolverEntryWithPda, ResolverType } from '@descro/sdk'
@@ -22,8 +23,17 @@ function truncPk(pk: PublicKey): string {
}
export function ResolverPanel() {
const { publicKey, sendTransaction, signTransaction } = useWallet()
const { connection } = useConnection()
const { signer } = useTransactionSigner()
const { disconnect } = useDisconnectWallet()
const { cluster } = useCluster()
const walletAdapter = useWalletAdapterCompat(signer, disconnect)
const connection = useMemo(
() => (cluster?.url ? new Connection(cluster.url, 'confirmed') : null),
[cluster?.url],
)
const publicKey = walletAdapter.publicKey ? new PublicKey(walletAdapter.publicKey.toString()) : null
const [resolvers, setResolvers] = useState<ResolverEntryWithPda[]>([])
const [resolversLoading, setResolversLoading] = useState(false)
@@ -40,9 +50,10 @@ export function ResolverPanel() {
const [success, setSuccess] = useState<string | null>(null)
async function loadResolvers() {
if (!connection) return
setResolversLoading(true)
try {
const provider = new AnchorProvider(connection, {} as any, {})
const provider = new AnchorProvider(connection, {} as never, {})
const client = new RegistryClient(provider)
const all = await client.fetchAllResolvers()
setResolvers(all)
@@ -63,7 +74,7 @@ export function ResolverPanel() {
setError(null)
setSuccess(null)
if (!publicKey || !signTransaction) {
if (!publicKey || !connection || !walletAdapter.signTransaction) {
setError('Connect your wallet first.')
return
}
@@ -92,8 +103,8 @@ export function ResolverPanel() {
try {
const provider = new AnchorProvider(
connection,
{ publicKey, signTransaction } as any,
{}
{ publicKey, signTransaction: walletAdapter.signTransaction.bind(walletAdapter) } as never,
{},
)
const client = new RegistryClient(provider)
const resolverType = RESOLVER_TYPE_OPTIONS[resolverTypeIdx].value
@@ -108,9 +119,10 @@ export function ResolverPanel() {
metadataUri: metadataUri.trim(),
})
const tx = new Transaction().add(ix)
const sig = await sendTransaction(tx, connection)
await connection.confirmTransaction(sig, 'confirmed')
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash()
const tx = new Transaction({ blockhash, lastValidBlockHeight, feePayer: publicKey }).add(ix)
const sig = await walletAdapter.sendTransaction(tx, connection)
await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, 'confirmed')
setSuccess(`Registered! Tx: ${sig.slice(0, 20)}`)
setName('')
@@ -164,7 +176,7 @@ export function ResolverPanel() {
<Text fontSize={12} color="$green9">B: {account.ruledForBuyer.toString()}</Text>
<Text fontSize={12} color="$orange9">S: {account.ruledForSeller.toString()}</Text>
</XStack>
<Text fontSize={11} fontFamily="monospace" color="$color10">
<Text fontSize={11} color="$color10" style={{ fontFamily: 'monospace' }}>
{truncPk(account.authority)}
</Text>
</YStack>
@@ -207,7 +219,7 @@ export function ResolverPanel() {
<YStack gap="$1">
<Text fontSize={13} color="$color11">Fee Recipient (default: your wallet)</Text>
<Input value={feeRecipient} onChangeText={setFeeRecipient} placeholder="Pubkey or leave blank" fontFamily="monospace" fontSize={13} />
<Input value={feeRecipient} onChangeText={setFeeRecipient} placeholder="Pubkey or leave blank" fontSize={13} />
</YStack>
<YStack gap="$1">

View File

@@ -1,22 +1,79 @@
'use client'
import { useState, useEffect } from 'react'
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui'
import { useState } from 'react'
import { useConnector, useConnectWallet, useDisconnectWallet, useWalletConnectors } from '@solana/connector/react'
export function WalletButton() {
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
if (!mounted) return null
const { isConnected, isConnecting, account, connector } = useConnector()
const { connect } = useConnectWallet()
const { disconnect } = useDisconnectWallet()
const connectors = useWalletConnectors()
const [showList, setShowList] = useState(false)
return (
<WalletMultiButton
style={{
const baseStyle: React.CSSProperties = {
backgroundColor: '#512da8',
color: 'white',
border: 'none',
borderRadius: 8,
fontSize: 14,
fontWeight: 600,
padding: '8px 16px',
cursor: 'pointer',
}
if (isConnected && account) {
const short = `${account.slice(0, 4)}${account.slice(-4)}`
return (
<button style={{ ...baseStyle, backgroundColor: '#2e7d32' }} onClick={() => disconnect()}>
{connector?.icon && (
<img src={connector.icon} width={16} height={16} alt="" style={{ marginRight: 6, verticalAlign: 'middle', borderRadius: 4 }} />
)}
{short} · Disconnect
</button>
)
}
if (showList) {
return (
<div style={{ position: 'relative' }}>
<div style={{
position: 'absolute', top: 0, right: 0, zIndex: 100,
backgroundColor: 'white', border: '1px solid #ddd', borderRadius: 8,
padding: 8, minWidth: 200, boxShadow: '0 4px 16px rgba(0,0,0,0.15)',
}}>
{connectors.length === 0 && (
<div style={{ fontSize: 13, color: '#666', padding: '8px 12px' }}>No wallets detected</div>
)}
{connectors.map((w) => (
<button
key={w.id}
onClick={() => { connect(w.id); setShowList(false) }}
style={{
display: 'flex', alignItems: 'center', gap: 8, width: '100%',
padding: '8px 12px', border: 'none', background: 'none',
cursor: 'pointer', fontSize: 13, borderRadius: 6,
}}
/>
onMouseEnter={(e) => { (e.currentTarget as HTMLButtonElement).style.backgroundColor = '#f5f5f5' }}
onMouseLeave={(e) => { (e.currentTarget as HTMLButtonElement).style.backgroundColor = 'transparent' }}
>
{w.icon && <img src={w.icon} width={20} height={20} alt="" style={{ borderRadius: 4 }} />}
{w.name}
</button>
))}
<button
onClick={() => setShowList(false)}
style={{ width: '100%', padding: '4px', border: 'none', background: 'none', cursor: 'pointer', fontSize: 12, color: '#999', marginTop: 4 }}
>
Cancel
</button>
</div>
</div>
)
}
return (
<button style={baseStyle} onClick={() => setShowList(true)} disabled={isConnecting}>
{isConnecting ? 'Connecting…' : 'Connect Wallet'}
</button>
)
}

View File

@@ -1,30 +1,35 @@
'use client'
import { useState, useEffect, useRef } from 'react'
import { PublicKey } from '@solana/web3.js'
import { useConnection } from '@solana/wallet-adapter-react'
import { useState, useEffect, useRef, useMemo } from 'react'
import { PublicKey, Connection } from '@solana/web3.js'
import { useCluster } from '@solana/connector/react'
import { AnchorProvider } from '@coral-xyz/anchor'
import { EscrowClient, subscribeEscrow } from '@descro/sdk'
import type { EscrowAccount } from '@descro/sdk'
export function useEscrowDetail(pda: PublicKey | null) {
const { connection } = useConnection()
const { cluster } = useCluster()
const connection = useMemo(
() => (cluster?.url ? new Connection(cluster.url) : null),
[cluster?.url],
)
const [account, setAccount] = useState<EscrowAccount | null>(null)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const unsubRef = useRef<(() => void) | null>(null)
useEffect(() => {
if (!pda) {
if (!pda || !connection) {
setAccount(null)
return
}
let cancelled = false
setLoading(true)
const provider = new AnchorProvider(connection, {} as any, {})
const provider = new AnchorProvider(connection, {} as never, {})
const client = new EscrowClient(provider)
client
.fetchEscrow(pda)
.then((acc) => {

View File

@@ -1,7 +1,8 @@
'use client'
import { useState, useEffect, useCallback, useRef } from 'react'
import { useWallet, useConnection } from '@solana/wallet-adapter-react'
import { useState, useEffect, useCallback, useRef, useMemo } from 'react'
import { Connection, PublicKey } from '@solana/web3.js'
import { useTransactionSigner, useCluster } from '@solana/connector/react'
import { AnchorProvider } from '@coral-xyz/anchor'
import { EscrowClient } from '@descro/sdk'
import type { EscrowAccountWithPda } from '@descro/sdk'
@@ -9,24 +10,31 @@ import type { EscrowAccountWithPda } from '@descro/sdk'
const POLL_INTERVAL_MS = 5000
export function useEscrows() {
const { publicKey } = useWallet()
const { connection } = useConnection()
const { address } = useTransactionSigner()
const { cluster } = useCluster()
const publicKey = useMemo(() => (address ? new PublicKey(address) : null), [address])
const connection = useMemo(
() => (cluster?.url ? new Connection(cluster.url) : null),
[cluster?.url],
)
const [escrows, setEscrows] = useState<EscrowAccountWithPda[]>([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)
const fetchEscrows = useCallback(async () => {
if (!publicKey) {
if (!publicKey || !connection) {
setEscrows([])
return
}
try {
const provider = new AnchorProvider(connection, {} as any, {})
const provider = new AnchorProvider(connection, {} as never, {})
const client = new EscrowClient(provider)
const results = await client.fetchEscrowsForWallet(publicKey)
results.sort((a, b) =>
Number(b.account.escrowId.toString()) - Number(a.account.escrowId.toString())
results.sort(
(a, b) => Number(b.account.escrowId.toString()) - Number(a.account.escrowId.toString()),
)
setEscrows(results)
setError(null)
@@ -38,9 +46,7 @@ export function useEscrows() {
useEffect(() => {
setLoading(true)
fetchEscrows().finally(() => setLoading(false))
intervalRef.current = setInterval(fetchEscrows, POLL_INTERVAL_MS)
return () => {
if (intervalRef.current !== null) clearInterval(intervalRef.current)
}

View File

@@ -10,7 +10,6 @@
"skipLibCheck": true,
"declaration": true,
"declarationMap": true,
"outDir": "./dist"
},
"include": ["src/**/*"]
}

5985
yarn.lock

File diff suppressed because it is too large Load Diff