1
1
import { MultiLayer2DRenderer } from '@rmrk-team/rmrk-2d-renderer' ;
2
- import {
3
- RMRKCatalogImpl ,
4
- RMRKEquippableImpl ,
5
- mapChainIdToNetwork ,
6
- } from '@rmrk-team/rmrk-evm-utils' ;
2
+ import { RMRKCatalogImpl , RMRKEquippableImpl } from '@rmrk-team/rmrk-evm-utils' ;
7
3
import {
8
4
useFetchIpfsMetadata ,
9
5
useGetAssetData ,
10
6
useGetComposedState ,
11
7
useGetInterfaceSupport ,
12
- useRMRKConfig ,
13
8
} from '@rmrk-team/rmrk-hooks' ;
14
9
import React , { useEffect , useRef , useState } from 'react' ;
15
10
import { css } from 'styled-system/css' ;
@@ -20,6 +15,57 @@ import type { Chain } from 'wagmi/chains';
20
15
import '../styles/index.css' ;
21
16
import type { RenderPart } from '../types/types.js' ;
22
17
18
+ const useIsAddressAContract = ( {
19
+ address,
20
+ chainId,
21
+ onError,
22
+ } : {
23
+ address : Address ;
24
+ chainId : Chain [ 'id' ] ;
25
+ onError ?: ( error : Error ) => void ;
26
+ } ) => {
27
+ const publicClient = usePublicClient ( {
28
+ chainId,
29
+ } ) ;
30
+
31
+ const [ isContract , setIsContract ] = useState < boolean > ( ) ;
32
+ const [ isLoading , setIsLoading ] = useState < boolean > ( false ) ;
33
+ const [ error , setError ] = useState < Error > ( ) ;
34
+
35
+ useEffect ( ( ) => {
36
+ const isValidAddress = isAddress ( address ) ;
37
+
38
+ if ( isValidAddress ) {
39
+ ( async ( ) => {
40
+ setIsLoading ( true ) ;
41
+ const isContract = await publicClient . getBytecode ( {
42
+ address,
43
+ } ) ;
44
+ setIsContract ( ! ! isContract ) ;
45
+ setIsLoading ( false ) ;
46
+ if ( ! isContract ) {
47
+ setError ( new Error ( `Address ${ address } is not a contract` ) ) ;
48
+ }
49
+ } ) ( ) ;
50
+ } else {
51
+ setError ( new Error ( `Address ${ address } is not a valid address` ) ) ;
52
+ }
53
+ } , [ address , publicClient ] ) ;
54
+
55
+ useEffect ( ( ) => {
56
+ if ( error && onError ) {
57
+ onError ( error ) ;
58
+ }
59
+ } , [ error , onError ] ) ;
60
+
61
+ return {
62
+ isContract,
63
+ isLoading,
64
+ error,
65
+ isError : ! ! error ,
66
+ } ;
67
+ } ;
68
+
23
69
type NFTRenderer = {
24
70
chainId : Chain [ 'id' ] ;
25
71
contractAddress : Address ;
@@ -30,42 +76,31 @@ type NFTRenderer = {
30
76
} ;
31
77
32
78
/**
33
- * @description To use this component, make sure you have a WagmiProvider wrapped it
79
+ * Renders a multi layered RMRK NFT based on the provided parameters.
80
+ *
81
+ * @param {Object } options - The options for rendering the NFT.
82
+ * @param {string } options.chainId - The chain ID of the blockchain network.
83
+ * @param {string } options.contractAddress - The address of the contract containing the NFT.
84
+ * @param {string } options.tokenId - The ID of the token to render.
85
+ * @param {ReactNode } options.loader - The loader component to display while the NFT is loading.
86
+ * @param {Function } options.onError - The callback function to handle errors.
34
87
*/
35
88
export function NFTRenderer ( {
36
89
chainId,
37
90
contractAddress,
38
91
tokenId,
39
- advancedMode,
40
92
loader,
41
93
onError,
42
94
} : NFTRenderer ) {
43
95
const rendererContainerRef = useRef < null | HTMLDivElement > ( null ) ;
44
96
const tokenIdBigint = BigInt ( tokenId ) ;
45
- const network = mapChainIdToNetwork ( chainId ) ;
46
-
47
- const config = useRMRKConfig ( ) ;
48
-
49
- const publicClient = usePublicClient ( {
50
- chainId,
51
- } ) ;
52
97
53
- const isValidAddress = isAddress ( contractAddress ) ;
54
- const [ isContract , setIsContract ] = useState < boolean > ( ) ;
55
- const [ isGettingIsContract , setIsGettingIsContract ] = useState < boolean > ( true ) ;
56
-
57
- useEffect ( ( ) => {
58
- ( async ( ) => {
59
- if ( isValidAddress ) {
60
- setIsGettingIsContract ( true ) ;
61
- const isContract = await publicClient . getBytecode ( {
62
- address : contractAddress ,
63
- } ) ;
64
- setIsContract ( ! ! isContract ) ;
65
- setIsGettingIsContract ( false ) ;
66
- }
67
- } ) ( ) ;
68
- } , [ contractAddress , isValidAddress , publicClient ] ) ;
98
+ const {
99
+ isContract,
100
+ isLoading : isLoadingIsContract ,
101
+ isError : isErrorIsContract ,
102
+ error : errorIsContract ,
103
+ } = useIsAddressAContract ( { address : contractAddress , chainId } ) ;
69
104
70
105
const {
71
106
isLoading : isLoadingGetInterfaceSupport ,
@@ -129,6 +164,7 @@ export function NFTRenderer({
129
164
data : catalogType ,
130
165
isLoading : loadingCatalogType ,
131
166
error : errorCatalogType ,
167
+ isError : isErrorCatalogType ,
132
168
} = useReadContract ( {
133
169
address : catalogAddress ,
134
170
abi : RMRKCatalogImpl ,
@@ -179,9 +215,15 @@ export function NFTRenderer({
179
215
isErrorTokenUri ||
180
216
isErrorTokenMetadata ||
181
217
isErrorPrimaryAsset ||
182
- isErrorComposableState ;
218
+ isErrorComposableState ||
219
+ isErrorIsContract ||
220
+ isErrorCatalogType ;
183
221
184
- const error = errorComposableState || errorPrimaryAsset ;
222
+ const error =
223
+ errorComposableState ||
224
+ errorPrimaryAsset ||
225
+ errorIsContract ||
226
+ errorCatalogType ;
185
227
186
228
useEffect ( ( ) => {
187
229
if ( error && onError ) {
@@ -204,7 +246,7 @@ export function NFTRenderer({
204
246
}
205
247
206
248
const isLoading =
207
- isGettingIsContract ||
249
+ isLoadingIsContract ||
208
250
isLoadingTokenUri ||
209
251
isLoadingPrimaryAsset ||
210
252
isLoadingTokenMetadata ||
@@ -241,32 +283,6 @@ export function NFTRenderer({
241
283
</ div >
242
284
) : (
243
285
< >
244
- { isValidAddress === false ? < p > Invalid address</ p > : null }
245
- { isValidAddress && ! isContract ? < p > Not a contract</ p > : null }
246
- { isContract && isErrorTokenUri ? < p > Failed to get NFT data</ p > : null }
247
-
248
- { advancedMode ? (
249
- < >
250
- < h1 >
251
- Token { tokenId . toString ( ) } on { network } in { contractAddress }
252
- </ h1 >
253
- { composableState ? (
254
- < div >
255
- < >
256
- < p > Is Equippable</ p >
257
- < p > metadataURI: { assetMetadataUri } </ p >
258
- < p > groupId: { equippableGroupId ?. toString ( ) } </ p >
259
- < p > catalog: { catalogAddress } </ p >
260
- </ >
261
- </ div >
262
- ) : primaryAsset ? (
263
- < p > metadataURI: { primaryAsset . metadataUri } </ p >
264
- ) : tokenUri ? (
265
- < p > metadataURI: { tokenUri } </ p >
266
- ) : null }
267
- </ >
268
- ) : null }
269
-
270
286
{ renderParts && renderParts . length > 0 ? (
271
287
< MultiLayer2DRenderer
272
288
resources = { renderParts }
0 commit comments