@@ -2,10 +2,13 @@ import { DropdownSelector } from '@/components/DropdownSelector';
22import { Layout } from '@/components/Layout' ;
33import { Truncated } from '@/components/Truncated' ;
44import { Textarea } from '@/components/ui/textarea' ;
5+ import { Nft } from '@/contexts/MintGardenContext' ;
56import { useDexie } from '@/hooks/useDexie' ;
7+ import { useMintGarden } from '@/hooks/useMintGarden' ;
68import { Precision , toDecimal } from '@/lib/conversions' ;
79import { parseJson } from '@/lib/json' ;
810import {
11+ AssetType ,
912 ConditionType ,
1013 ParsedCoinSpend ,
1114 ParsedCondition ,
@@ -22,7 +25,7 @@ import {
2225 SpendBundle ,
2326} from 'chia-wallet-sdk-wasm' ;
2427import { CoinsIcon , TriangleAlertIcon } from 'lucide-react' ;
25- import { useMemo , useState } from 'react' ;
28+ import { useEffect , useMemo , useState } from 'react' ;
2629import { useLocalStorage } from 'usehooks-ts' ;
2730
2831export function Tools ( ) {
@@ -79,7 +82,90 @@ function BundleViewer({ bundle }: BundleViewerProps) {
7982 const [ selectedSpend , setSelectedSpend ] = useState < ParsedCoinSpend | null > (
8083 bundle . coinSpends [ 0 ] ?? null ,
8184 ) ;
82- const { tokens } = useDexie ( ) ;
85+ const { getToken } = useDexie ( ) ;
86+ const { fetchNft } = useMintGarden ( ) ;
87+
88+ const [ nfts , setNfts ] = useState < Record < string , Nft | null > > ( { } ) ;
89+
90+ useEffect ( ( ) => {
91+ // Fetch NFT data for all NFT spends
92+ bundle . coinSpends . forEach ( ( spend ) => {
93+ if ( spend . assetType === AssetType . Nft ) {
94+ const launcherId = spend . assetId ;
95+ if ( ! nfts [ launcherId ] ) {
96+ fetchNft ( launcherId ) . then ( ( nft ) => {
97+ setNfts ( ( prev ) => ( { ...prev , [ launcherId ] : nft } ) ) ;
98+ } ) ;
99+ }
100+ }
101+ } ) ;
102+ } , [ bundle . coinSpends , fetchNft , nfts ] ) ;
103+
104+ const renderCoinInfo = ( spend : ParsedCoinSpend ) => {
105+ const nft = spend . assetType === AssetType . Nft ? nfts [ spend . assetId ] : null ;
106+ const token =
107+ spend . assetType === AssetType . Token ? getToken ( spend . assetId ) : null ;
108+
109+ console . log ( nft ) ;
110+
111+ return (
112+ < div className = 'flex items-center gap-2 w-full' >
113+ { nft ? (
114+ < img
115+ src = { nft . data ?. thumbnail_uri }
116+ alt = { nft . data ?. metadata_json ?. name ?? 'Unnamed' }
117+ className = 'w-6 h-6 rounded flex-shrink-0 object-cover'
118+ />
119+ ) : token ?. icon ? (
120+ < img
121+ src = { token . icon }
122+ alt = { token . name }
123+ className = 'w-6 h-6 rounded-full flex-shrink-0'
124+ />
125+ ) : (
126+ < div className = 'w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0' >
127+ < CoinsIcon className = 'w-3.5 h-3.5 text-primary' />
128+ </ div >
129+ ) }
130+ < div className = 'flex flex-col min-w-0' >
131+ < div className = 'font-medium flex flex-wrap items-center gap-1.5' >
132+ { nft ? (
133+ < span className = 'break-all' >
134+ { nft . data ?. metadata_json ?. name ?? 'Unnamed' }
135+ </ span >
136+ ) : (
137+ < >
138+ < span className = 'break-all' >
139+ { toDecimal (
140+ spend . coin . amount ,
141+ spend . assetType === AssetType . Token
142+ ? spend . assetId === 'xch'
143+ ? Precision . Xch
144+ : Precision . Cat
145+ : Precision . Singleton ,
146+ ) }
147+ </ span >
148+ < span className = 'text-muted-foreground font-normal' >
149+ { spend . assetType === AssetType . Token
150+ ? token ?. code || ( spend . assetId === 'xch' ? 'XCH' : 'CAT' )
151+ : spend . assetType === AssetType . Nft
152+ ? 'NFT'
153+ : spend . assetType === AssetType . Did
154+ ? 'DID'
155+ : spend . assetType === AssetType . Singleton
156+ ? 'VAULT'
157+ : '' }
158+ </ span >
159+ </ >
160+ ) }
161+ </ div >
162+ < div className = 'font-mono text-xs text-muted-foreground truncate' >
163+ < Truncated value = { spend . coin . coinId } disableCopy />
164+ </ div >
165+ </ div >
166+ </ div >
167+ ) ;
168+ } ;
83169
84170 return (
85171 < div className = 'flex flex-col gap-4 mt-4' >
@@ -108,64 +194,12 @@ function BundleViewer({ bundle }: BundleViewerProps) {
108194 < DropdownSelector
109195 loadedItems = { bundle . coinSpends }
110196 onSelect = { setSelectedSpend }
111- renderItem = { ( spend ) => (
112- < div className = 'flex items-center gap-2 w-full' >
113- { tokens ?. xch ?. icon ? (
114- < img
115- src = { tokens . xch . icon }
116- alt = 'XCH'
117- className = 'w-6 h-6 rounded-full flex-shrink-0'
118- />
119- ) : (
120- < div className = 'w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0' >
121- < CoinsIcon className = 'w-3.5 h-3.5 text-primary' />
122- </ div >
123- ) }
124- < div className = 'flex flex-col min-w-0' >
125- < div className = 'font-medium flex flex-wrap items-center gap-1.5' >
126- < span className = 'break-all' >
127- { toDecimal ( spend . coin . amount , Precision . Xch ) }
128- </ span >
129- < span className = 'text-muted-foreground font-normal' >
130- XCH
131- </ span >
132- </ div >
133- < div className = 'font-mono text-xs text-muted-foreground truncate' >
134- < Truncated value = { spend . coin . coinId } disableCopy />
135- </ div >
136- </ div >
137- </ div >
138- ) }
197+ renderItem = { ( spend ) => renderCoinInfo ( spend ) }
139198 width = 'w-[350px]'
140199 className = 'rounded-b-none'
141200 >
142201 { selectedSpend ? (
143- < div className = 'flex items-center gap-2 min-w-0' >
144- { tokens ?. xch ?. icon ? (
145- < img
146- src = { tokens . xch . icon }
147- alt = 'XCH'
148- className = 'w-6 h-6 rounded-full flex-shrink-0'
149- />
150- ) : (
151- < div className = 'w-6 h-6 rounded-full bg-primary/10 flex items-center justify-center flex-shrink-0' >
152- < CoinsIcon className = 'w-3.5 h-3.5 text-primary' />
153- </ div >
154- ) }
155- < div className = 'flex flex-col min-w-0' >
156- < div className = 'font-medium flex flex-wrap items-center gap-1.5' >
157- < span className = 'break-all' >
158- { toDecimal ( selectedSpend . coin . amount , Precision . Xch ) }
159- </ span >
160- < span className = 'text-muted-foreground font-normal' >
161- XCH
162- </ span >
163- </ div >
164- < div className = 'font-mono text-xs text-muted-foreground truncate' >
165- < Truncated value = { selectedSpend . coin . coinId } disableCopy />
166- </ div >
167- </ div >
168- </ div >
202+ renderCoinInfo ( selectedSpend )
169203 ) : (
170204 < div className = 'text-muted-foreground' >
171205 Select a spend to view
@@ -226,6 +260,10 @@ function SpendViewer({ spend }: SpendViewerProps) {
226260 < div className = 'text-muted-foreground' > Cost</ div >
227261 < div > { spend . cost } </ div >
228262 </ div >
263+ < div className = 'flex flex-col' >
264+ < div className = 'text-muted-foreground' > Asset ID</ div >
265+ < Truncated value = { spend . assetId } />
266+ </ div >
229267 </ div >
230268 </ div >
231269
0 commit comments