/**
* Self-fetching wrappers for algomd-rn display components.
*
* Each wrapper adds an optional self-fetch prop (appId, address, txId, etc.)
* alongside the existing `data` prop. If `data` is provided, it renders
* immediately. Otherwise, it fetches from algod via the hooks.
*/
import React from 'react'
import type { ReactNode } from 'react'
import type { ComponentSize } from '../types/algorand'
import { LoadingSkeleton, ErrorState } from '../ui/DataStates'
// Display components (internal names)
import { Account as AccountDisplay } from './Account'
import { ASAComponent } from './ASA'
import { NFTListingComponent } from './NFTListing'
import { NFDProfileComponent } from './NFDProfile'
import { TransactionDetailsComponent } from './TransactionDetails'
import { PollComponent } from './Poll'
import { RaffleListingComponent } from './RaffleListing'
import { AuctionListingComponent } from './AuctionListing'
import { TradeOfferComponent } from './TradeOffer'
// Hooks
import {
useAccountData,
useASAData,
useTransactionData,
useNFDProfileData,
usePollData,
useRaffleData,
useAuctionData,
useNFTListingData,
useTradeOfferData,
} from '../hooks/useAlgomdData'
// Types
import type {
AlgorandAccount,
ASA as ASAType,
NFTListing as NFTListingType,
NFDProfile as NFDProfileType,
TransactionDetails as TransactionDetailsType,
Poll as PollType,
RaffleListing as RaffleListingType,
AuctionListing as AuctionListingType,
TradeOffer as TradeOfferType,
} from '../types/algorand'
// ---------------------------------------------------------------------------
// Shared fetcher wrapper
// ---------------------------------------------------------------------------
function FetcherWrapper({
name,
isLoading,
error,
data,
loadingFallback,
errorFallback,
children,
}: {
name: string
isLoading: boolean
error: Error | null
data: unknown
loadingFallback?: ReactNode
errorFallback?: ReactNode
children: ReactNode
}) {
if (isLoading) return <>{loadingFallback ?? }>
if (error || !data) return <>{errorFallback ?? }>
return <>{children}>
}
// ---------------------------------------------------------------------------
// Poll
// ---------------------------------------------------------------------------
type PollSelfFetchProps = {
data?: PollType
appId?: number
showVoteButton?: boolean
compact?: boolean
size?: ComponentSize
className?: string
onVote?: (pollId: string, optionId: string) => void
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function PollFetcher({ appId, ...rest }: Omit & { appId: number }) {
const { data, isLoading, error } = usePollData(appId)
return (
{data && }
)
}
export function Poll(props: PollSelfFetchProps) {
if (props.data) return
if (props.appId != null) return
return
}
// ---------------------------------------------------------------------------
// RaffleListing
// ---------------------------------------------------------------------------
type RaffleListingSelfFetchProps = {
data?: RaffleListingType
appId?: number
showEntryButton?: boolean
size?: ComponentSize
className?: string
imageUrl?: string
onEnter?: (raffle: RaffleListingType) => void
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function RaffleListingFetcher({ appId, ...rest }: Omit & { appId: number }) {
const { data, isLoading, error } = useRaffleData(appId)
return (
{data && }
)
}
export function RaffleListing(props: RaffleListingSelfFetchProps) {
if (props.data) return
if (props.appId != null) return
return
}
// ---------------------------------------------------------------------------
// AuctionListing
// ---------------------------------------------------------------------------
type AuctionListingSelfFetchProps = {
data?: AuctionListingType
appId?: number
showBidButton?: boolean
size?: ComponentSize
className?: string
imageUrl?: string
onBid?: (auction: AuctionListingType) => void
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function AuctionListingFetcher({ appId, ...rest }: Omit & { appId: number }) {
const { data, isLoading, error } = useAuctionData(appId)
return (
{data && }
)
}
export function AuctionListing(props: AuctionListingSelfFetchProps) {
if (props.data) return
if (props.appId != null) return
return
}
// ---------------------------------------------------------------------------
// NFTListing
// ---------------------------------------------------------------------------
type NFTListingSelfFetchProps = {
data?: NFTListingType
appId?: number
showPurchaseButton?: boolean
size?: ComponentSize
className?: string
imageUrl?: string
onPurchase?: (listing: NFTListingType) => void
onFavorite?: (listing: NFTListingType) => void
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function NFTListingFetcher({ appId, ...rest }: Omit & { appId: number }) {
const { data, isLoading, error } = useNFTListingData(appId)
return (
{data && }
)
}
export function NFTListing(props: NFTListingSelfFetchProps) {
if (props.data) return
if (props.appId != null) return
return
}
// ---------------------------------------------------------------------------
// TradeOffer
// ---------------------------------------------------------------------------
type TradeOfferSelfFetchProps = {
data?: TradeOfferType
appId?: number
offerId?: number
showActions?: boolean
size?: ComponentSize
className?: string
currentUserAddress?: string
onAccept?: (offer: TradeOfferType) => void
onReject?: (offer: TradeOfferType) => void
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function TradeOfferFetcher({ appId, offerId, ...rest }: Omit & { appId: number; offerId: number }) {
const { data, isLoading, error } = useTradeOfferData(appId, offerId)
return (
{data && }
)
}
export function TradeOffer(props: TradeOfferSelfFetchProps) {
if (props.data) return
if (props.appId != null && props.offerId != null) return
return
}
// ---------------------------------------------------------------------------
// Account
// ---------------------------------------------------------------------------
type AccountSelfFetchProps = {
data?: AlgorandAccount
address?: string
showAssets?: boolean
showApps?: boolean
compact?: boolean
size?: ComponentSize
className?: string
onExternalLink?: (address: string) => void
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function AccountFetcher({ address, ...rest }: Omit & { address: string }) {
const { data, isLoading, error } = useAccountData(address)
return (
{data && }
)
}
export function Account(props: AccountSelfFetchProps) {
if (props.data) return
if (props.address) return
return
}
// ---------------------------------------------------------------------------
// ASA
// ---------------------------------------------------------------------------
type ASASelfFetchProps = {
data?: ASAType
assetId?: number
showDetails?: boolean
compact?: boolean
size?: ComponentSize
className?: string
imageUrl?: string
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function ASAFetcher({ assetId, ...rest }: Omit & { assetId: number }) {
const { data, isLoading, error } = useASAData(assetId)
return (
{data && }
)
}
export function ASA(props: ASASelfFetchProps) {
if (props.data) return
if (props.assetId != null) return
return
}
// ---------------------------------------------------------------------------
// TransactionDetails
// ---------------------------------------------------------------------------
type TransactionDetailsSelfFetchProps = {
data?: TransactionDetailsType
txId?: string
showContext?: boolean
showFee?: boolean
compact?: boolean
size?: ComponentSize
className?: string
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function TransactionDetailsFetcher({ txId, ...rest }: Omit & { txId: string }) {
const { data, isLoading, error } = useTransactionData(txId)
return (
{data && }
)
}
export function TransactionDetails(props: TransactionDetailsSelfFetchProps) {
if (props.data) return
if (props.txId) return
return
}
// ---------------------------------------------------------------------------
// NFDProfile
// ---------------------------------------------------------------------------
type NFDProfileSelfFetchProps = {
data?: NFDProfileType
name?: string
showBio?: boolean
showProperties?: boolean
compact?: boolean
size?: ComponentSize
className?: string
loadingFallback?: ReactNode
errorFallback?: ReactNode
}
function NFDProfileFetcher({ name, ...rest }: Omit & { name: string }) {
const { data, isLoading, error } = useNFDProfileData(name)
return (
{data && }
)
}
export function NFDProfile(props: NFDProfileSelfFetchProps) {
if (props.data) return
if (props.name) return
return
}