import React from 'react';
import { View, Text, Pressable } from 'react-native';
import { Image } from 'expo-image';
import Svg, { Path } from 'react-native-svg';
import type { TradeOffer as TradeOfferType, ASA, AlgorandAccount, ComponentSize } from '../types/algorand';
import { formatAddress, formatRelativeTime } from '../utils/format';
import { CopyButton } from '../ui/CopyButton';
import { SizeContainer } from '../ui/SizeContainer';
import { StatusBadge } from '../ui/StatusBadge';
function ArrowRightLeftIcon({ size = 20, color = '#a1a1aa' }: { size?: number; color?: string }) {
return (
);
}
function SwapIcon({ size = 20, color = '#a1a1aa' }: { size?: number; color?: string }) {
return (
);
}
function CheckIcon({ size = 16, color = '#fff' }: { size?: number; color?: string }) {
return (
);
}
function XIcon({ size = 16, color = '#fff' }: { size?: number; color?: string }) {
return (
);
}
function ClockIcon({ size = 16, color = '#a1a1aa' }: { size?: number; color?: string }) {
return (
);
}
function MessageIcon({ size = 16, color = '#a1a1aa' }: { size?: number; color?: string }) {
return (
);
}
// Helper to determine if something is an ASA
function isASA(item: ASA | AlgorandAccount): item is ASA {
return 'unitName' in item;
}
function AssetItem({ asset, imageUrl }: { asset: ASA | AlgorandAccount; imageUrl?: string }) {
if (isASA(asset)) {
const isNFT = asset.total === 1 && asset.decimals === 0;
return (
{imageUrl && (
)}
{asset.name}
{asset.unitName} - #{asset.id}
{asset.price !== undefined && (
${asset.price}
)}
);
}
// AlgorandAccount
return (
ACC
{formatAddress(asset.address)}
ALGO Account
);
}
function AssetGroup({ title, assets }: { title: string; assets: (ASA | AlgorandAccount)[] }) {
if (assets.length === 0) {
return (
No assets
);
}
return (
{title}
{assets.map((asset, index) => (
))}
);
}
interface TradeOfferProps {
data: TradeOfferType;
showActions?: boolean;
size?: ComponentSize;
className?: string;
currentUserAddress?: string;
onAccept?: (offer: TradeOfferType) => void;
onReject?: (offer: TradeOfferType) => void;
}
export function TradeOfferComponent({
data: offer,
showActions = true,
size = 'full',
className,
currentUserAddress,
onAccept,
onReject,
}: TradeOfferProps) {
const isExpired = new Date() > offer.expiresAt;
const isRecipient = currentUserAddress ? offer.recipients.includes(currentUserAddress) : false;
const canRespond = isRecipient && offer.status === 'pending' && !isExpired;
const statusVariant =
offer.status === 'pending'
? 'info'
: offer.status === 'accepted'
? 'success'
: offer.status === 'rejected'
? 'error'
: 'neutral';
const isFullscreen = size === 'fullscreen';
return (
{/* Header */}
{isRecipient ? 'Incoming Trade' : 'Trade Offer'}
{isExpired && }
{formatRelativeTime(offer.expiresAt)}
From {formatAddress(offer.creator)}
{/* Trade Content */}
{/* Offering */}
{/* Swap Icon */}
{/* Requesting */}
{/* Message */}
{offer.message && (
{offer.message}
)}
{/* Action Buttons */}
{showActions && canRespond && (
onReject?.(offer)}
className="flex-1 flex-row items-center justify-center gap-2 py-2.5 px-4 rounded-xl bg-red-500/20"
>
Reject
onAccept?.(offer)}
className="flex-1 flex-row items-center justify-center gap-2 py-2.5 px-4 rounded-xl bg-green-600"
>
Accept
)}
);
}