Skip to content

Commit

Permalink
Add ability to pass custom utility contracts config for chains where …
Browse files Browse the repository at this point in the history
…RMRK did not deploy utility contracts
  • Loading branch information
Yuripetusko committed Jan 23, 2024
1 parent 4e237e6 commit 0aadba0
Show file tree
Hide file tree
Showing 16 changed files with 217 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export default function TokenDisplay({
assertIsEvmNetwork(chain);
const searchParams = useSearchParams();
const advancedMode = searchParams.get('advancedMode') === 'true';
// const emoteMode = searchParams.get('emoteMode') === 'true';

const chainId = getChainIdByNetworkName(chain);

Expand All @@ -30,7 +29,6 @@ export default function TokenDisplay({
contractAddress={collection}
tokenId={BigInt(tokenId)}
advancedMode={advancedMode}
// emoteMode={emoteMode}
loader={<Loader />}
/>
</Flex>
Expand Down
25 changes: 24 additions & 1 deletion apps/composable-nft-renderer-app/components/app/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,36 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { WagmiProvider } from 'components/app/wagmi-provider';
import React from 'react';
import { RMRKContextProvider } from '@rmrk-team/rmrk-hooks';
import {
NETWORK_CONTACTS_PROPS,
RMRKUtilityContracts,
} from '@rmrk-team/rmrk-evm-utils';
import { hardhat } from 'wagmi/chains';

const queryClient = new QueryClient();

// You can pass custom utility contracts to the RMRKContextProvider
const customUtilityContracts = {
[hardhat.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]: '0x00',
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]: '0x00',
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]: '0x00',
},
} satisfies RMRKUtilityContracts;

const rmrkConfig = {
utilityContracts: customUtilityContracts,
};

export const Providers = ({ children }: { children: React.ReactNode }) => {
return (
<WagmiProvider>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
<QueryClientProvider client={queryClient}>
<RMRKContextProvider config={rmrkConfig}>
{children}
</RMRKContextProvider>
</QueryClientProvider>
</WagmiProvider>
);
};
1 change: 1 addition & 0 deletions apps/composable-nft-renderer-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@rainbow-me/rainbowkit": "^2.0.0-beta.1",
"@rmrk-team/nft-renderer": "workspace:*",
"@rmrk-team/rmrk-evm-utils": "workspace:*",
"@rmrk-team/rmrk-hooks": "workspace:*",
"@tanstack/react-query": "^5.17.12",
"lucide-react": "^0.303.0",
"next": "13.4.1",
Expand Down
28 changes: 9 additions & 19 deletions packages/nft-renderer/src/components/nft-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,15 @@ import { usePublicClient, useReadContract } from 'wagmi';
import type { Chain } from 'wagmi/chains';
import '../styles/index.css';
import type { RenderPart } from '../types/types.js';
// import { sanitizeIpfsUrl } from '../lib/ipfs';
import { Providers } from './providers.js';

interface INFTRenderer {
type NFTRenderer = {
chainId: Chain['id'];
contractAddress: Address;
tokenId: bigint;
advancedMode?: boolean;
loader?: React.ReactNode;
onError?: (error: Error) => void;
}
//
// /**
// * @description If you have more than 1 NFT to render in the same time, better use `NFTRenderer` rather than current.
// * Add a `WagmiProvider` and wrap it around `NFTRenderer`s to use it.
// */
// export default function NFTRendererWithProvider(props: INFTRenderer) {
// return (
// <Providers>
// <NFTRenderer {...props} />
// </Providers>
// );
// }
};

/**
* @description To use this component, make sure you have a WagmiProvider wrapped it
Expand All @@ -51,7 +37,7 @@ export function NFTRenderer({
advancedMode,
loader,
onError,
}: INFTRenderer) {
}: NFTRenderer) {
const rendererContainerRef = useRef<null | HTMLDivElement>(null);
const tokenIdBigint = BigInt(tokenId);
const network = mapChainIdToNetwork(chainId);
Expand Down Expand Up @@ -80,6 +66,7 @@ export function NFTRenderer({
const {
isLoading: isLoadingGetInterfaceSupport,
interfaceSupport: { supports721, supportsEquippable, supportsMultiAsset },
isFetching,
} = useGetInterfaceSupport(
{ contractAddress, chainId },
{ enabled: isContract },
Expand Down Expand Up @@ -175,12 +162,15 @@ export function NFTRenderer({
const error = errorComposableState || errorPrimaryAsset;

useEffect(() => {
if (error && onError) onError(error);
if (error && onError) {
onError(error);
}
}, [error, onError]);

useEffect(() => {
if (chainId === undefined && onError)
if (chainId === undefined && onError) {
onError(new Error(`Unsupported chain ${chainId}`));
}
}, [chainId, onError]);

if (error) {
Expand Down
105 changes: 59 additions & 46 deletions packages/rmrk-evm-utils/src/lib/rmrk-contract-addresses.ts
Original file line number Diff line number Diff line change
@@ -1,95 +1,108 @@
import type { Address } from 'viem';
import { EVM_NETWORKS } from './chain-mapping.js';
import type { Address, Chain } from "viem";
import {
astar,
base,
baseSepolia,
hardhat,
mainnet,
moonbaseAlpha,
moonbeam,
polygon,
polygonMumbai,
sepolia,
} from "wagmi/chains";

export const NETWORK_CONTACTS_PROPS = {
RMRKEquipRenderUtils: 'RMRKEquipRenderUtils',
RMRKBulkWriter: 'RMRKBulkWriter',
RMRKCollectionUtils: 'RMRKCollectionUtils',
RMRKEquipRenderUtils: "RMRKEquipRenderUtils",
RMRKBulkWriter: "RMRKBulkWriter",
RMRKCollectionUtils: "RMRKCollectionUtils",
} as const;

export type NETWORK_CONTACTS_PROPS =
(typeof NETWORK_CONTACTS_PROPS)[keyof typeof NETWORK_CONTACTS_PROPS];

export type NETWRORK_CONTRACT_TYPES = Record<NETWORK_CONTACTS_PROPS, Address>;
export type RMRKUtilityContracts = Record<Chain["id"], NETWRORK_CONTRACT_TYPES>;

export const EVM_RMRK_CONTRACTS = {
[EVM_NETWORKS.moonbeam]: {
[moonbeam.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x3bd52D2F911A1243f681d36f1C28bcC6aaa26ef6',
"0x3bd52D2F911A1243f681d36f1C28bcC6aaa26ef6",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0xb6ccec23d23b4ed3f623cafbc90cfff32dbf1834',
"0xb6ccec23d23b4ed3f623cafbc90cfff32dbf1834",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0x244eE3b7F2692191BdA9E9E236e4D2008dd35Ce9',
"0x244eE3b7F2692191BdA9E9E236e4D2008dd35Ce9",
},
[EVM_NETWORKS.ethereum]: {
[mainnet.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0xEEDA3E023A8f0Db4E038f2d16d3CF39369D5bA8C',
"0xEEDA3E023A8f0Db4E038f2d16d3CF39369D5bA8C",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0xA1bE03772e25001df2B8A3F4FC88d8d3810A285e',
"0xA1bE03772e25001df2B8A3F4FC88d8d3810A285e",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0x388e1d9b6509ad62c162cd68ccefa84e09aa8280',
"0x388e1d9b6509ad62c162cd68ccefa84e09aa8280",
},
[EVM_NETWORKS.sepolia]: {
[sepolia.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x6Ee72618573b4c7484D4Ee46b04f4b271a81e882',
"0x6Ee72618573b4c7484D4Ee46b04f4b271a81e882",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0xee04d24462A3952aC8f64F23f5F16e0fFFb5b6CC',
"0xee04d24462A3952aC8f64F23f5F16e0fFFb5b6CC",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0x3ea5D7985718B6bFa75172Dcd0a79E4c587a6694',
"0x3ea5D7985718B6bFa75172Dcd0a79E4c587a6694",
},
[EVM_NETWORKS.polygon]: {
[polygon.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x4e42678e426fdd147a7cf509dd6673b1853e12ed',
"0x4e42678e426fdd147a7cf509dd6673b1853e12ed",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0x28F5550315182D8446e9BFa5eD24a7796ee6e2a1',
"0x28F5550315182D8446e9BFa5eD24a7796ee6e2a1",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0x7cD79daAF8E178Fb4Af7017608633e23587c167e',
"0x7cD79daAF8E178Fb4Af7017608633e23587c167e",
},
[EVM_NETWORKS.polygonMumbai]: {
[polygonMumbai.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x5b583eDC4e212Fb737894D2bE44fa7D0805f0774',
"0x5b583eDC4e212Fb737894D2bE44fa7D0805f0774",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0xA799A6b45ED9BeE6A9bE436aef29469b9BE0DE3F',
"0xA799A6b45ED9BeE6A9bE436aef29469b9BE0DE3F",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0xf57160A562cD87dC786C7388b75BaBAe7EfB60C9',
"0xf57160A562cD87dC786C7388b75BaBAe7EfB60C9",
},
[EVM_NETWORKS.moonbaseAlpha]: {
[moonbaseAlpha.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0xC8EBEdb00cBE44da99c3eE1f0c6F5F5BdEf67843',
"0xC8EBEdb00cBE44da99c3eE1f0c6F5F5BdEf67843",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0x3d3295D71138078df5F470A22628ec4377416e5d',
"0x3d3295D71138078df5F470A22628ec4377416e5d",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0x6407d7D24023348Ff660b6F5Fa0F5D644953cf2c',
"0x6407d7D24023348Ff660b6F5Fa0F5D644953cf2c",
},
[EVM_NETWORKS.base]: {
[base.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x59E1038E3C94B7EFF7C24B0A2d56DBfc606C1b7C',
"0x59E1038E3C94B7EFF7C24B0A2d56DBfc606C1b7C",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0x91d098a91faf61984F965C3A202Ad30747dae275',
"0x91d098a91faf61984F965C3A202Ad30747dae275",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0xBa1eA71FF1695C3fe8dfBC774Af30448316E98dc',
"0xBa1eA71FF1695C3fe8dfBC774Af30448316E98dc",
},
[EVM_NETWORKS.baseSepolia]: {
[baseSepolia.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x0665ddcACB4064044343fb0DBb368Be3851caB4f',
"0x0665ddcACB4064044343fb0DBb368Be3851caB4f",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0xb4F28c86808872f7B368893cbc975F764aD0fdB5',
"0xb4F28c86808872f7B368893cbc975F764aD0fdB5",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0x4aCFECbA1a5d83a6D8868E55f784b9d5453d1339',
"0x4aCFECbA1a5d83a6D8868E55f784b9d5453d1339",
},
[EVM_NETWORKS.astar]: {
[astar.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x248ab178b3342bc843BE7Aacc88eCf3cbf2E25d3',
"0x248ab178b3342bc843BE7Aacc88eCf3cbf2E25d3",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0x5B01637FD17c1ac79df13dFF4F7080Fdd4cfEC46',
"0x5B01637FD17c1ac79df13dFF4F7080Fdd4cfEC46",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0xCeecc3C73284CfB9d3AB87F8b653D14Bd3b65FeC',
"0xCeecc3C73284CfB9d3AB87F8b653D14Bd3b65FeC",
},
[EVM_NETWORKS.hardhat]: {
[hardhat.id]: {
[NETWORK_CONTACTS_PROPS.RMRKEquipRenderUtils]:
'0x0000000000000000000000000000000000000000',
"0x0000000000000000000000000000000000000000",
[NETWORK_CONTACTS_PROPS.RMRKCollectionUtils]:
'0x0000000000000000000000000000000000000000',
"0x0000000000000000000000000000000000000000",
[NETWORK_CONTACTS_PROPS.RMRKBulkWriter]:
'0x0000000000000000000000000000000000000000',
"0x0000000000000000000000000000000000000000",
},
} as const satisfies Record<EVM_NETWORKS, NETWRORK_CONTRACT_TYPES>;
} as const satisfies RMRKUtilityContracts;
8 changes: 3 additions & 5 deletions packages/rmrk-evm-utils/src/scripts/get-rmrk-abis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Abi } from 'abitype/zod';
import 'dotenv/config';
import type { Address } from 'viem';
import { EVM_RMRK_CONTRACTS, NETWORK_CONTACTS_PROPS } from '../index.js';
import { EVM_NETWORKS } from '../index.js';
import { base } from 'wagmi/chains';

const BASESCAN_API_URL = 'https://api.basescan.org/api';

Expand Down Expand Up @@ -32,12 +32,10 @@ const getRmrkAbi = async (contractName: string, contractAddress: Address) => {
};

const getRmrkAbis = async () => {
for (const contractName of Object.keys(
EVM_RMRK_CONTRACTS[EVM_NETWORKS.base],
)) {
for (const contractName of Object.keys(EVM_RMRK_CONTRACTS[base.id])) {
await getRmrkAbi(
contractName,
EVM_RMRK_CONTRACTS[EVM_NETWORKS.base][
EVM_RMRK_CONTRACTS[base.id][
contractName as keyof typeof NETWORK_CONTACTS_PROPS
],
);
Expand Down
2 changes: 2 additions & 0 deletions packages/rmrk-hooks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@
"isomorphic-dompurify": "^2.2.0",
"lucide-react": "^0.303.0",
"pixi.js": "^7.2.4",
"ramda": "^0.29.1",
"use-image": "^1.1.1"
},
"devDependencies": {
"@changesets/changelog-github": "^0.5.0",
"@changesets/cli": "^2.27.1",
"@tanstack/react-query": "^5.17.12",
"@types/node": "18.16.9",
"@types/ramda": "^0.29.10",
"@types/react": "18.2.33",
"@types/react-dom": "18.2.14",
"@vitejs/plugin-react": "^4.1.0",
Expand Down
1 change: 1 addition & 0 deletions packages/rmrk-hooks/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './lib/hooks/index.js';
export * from './lib/RMRKContextProvider.js';
62 changes: 62 additions & 0 deletions packages/rmrk-hooks/src/lib/RMRKContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use client';

import * as React from 'react';
import type { RMRKUtilityContracts } from '@rmrk-team/rmrk-evm-utils';
import { useContext } from 'react';
import { EVM_RMRK_CONTRACTS } from '@rmrk-team/rmrk-evm-utils';
import { mergeDeepRight } from 'ramda';

type RMRKConfigInitial = {
utilityContracts: RMRKUtilityContracts;
};

export type RMRKConfig<
utilityContracts extends RMRKUtilityContracts = RMRKUtilityContracts,
> = {
utilityContracts: utilityContracts;
};

export type ResolveRMRKConfig = {
config: RMRKConfigInitial extends {
config: infer config extends RMRKConfig;
}
? config
: RMRKConfig;
};

export type ConfigParameter<config extends RMRKConfig = RMRKConfig> = {
config?: RMRKConfig | config | undefined;
};

export const RMRKContext = React.createContext<RMRKConfig | undefined>(
undefined,
);

export type UseConfigReturnType<config extends RMRKConfig = RMRKConfig> =
config;

export type UseConfigParameters<config extends RMRKConfig = RMRKConfig> =
ConfigParameter<config>;

export function useRMRKConfig<
config extends RMRKConfig = ResolveRMRKConfig['config'],
>(): UseConfigReturnType<config> {
const config = useContext(RMRKContext);
if (!config) throw new Error('No config found');
return config as UseConfigReturnType<config>;
}

type Props = {
config?: RMRKConfig;
children?: React.ReactNode;
};

export const RMRKContextProvider = ({ children, config }: Props) => {
const defaultConfig = {
utilityContracts: EVM_RMRK_CONTRACTS,
} satisfies RMRKConfig;
const rmrkConfig = mergeDeepRight(defaultConfig, config || {});
return (
<RMRKContext.Provider value={rmrkConfig}>{children}</RMRKContext.Provider>
);
};
Loading

0 comments on commit 0aadba0

Please sign in to comment.