├── src
├── contract_access_object
│ ├── constants.js
│ ├── writerCao.js
│ ├── cao.js
│ └── readerCao.js
├── index.css
├── components
│ ├── common
│ │ ├── images
│ │ │ └── catchon.png
│ │ ├── PowerBy.js
│ │ └── PowerBy.css
│ ├── SignInModal
│ │ ├── SignInModal.css
│ │ ├── SignInModalSlice.js
│ │ └── SignInModal.js
│ ├── muiStyle.js
│ ├── FunctionCallModal
│ │ ├── FunctionCallSlice.js
│ │ ├── FunctionCallView.css
│ │ └── FunctionCallView.js
│ ├── UserModal
│ │ ├── UserModal.css
│ │ ├── UserModal.js
│ │ ├── UserModalSlice.js
│ │ └── UserSection.js
│ └── mint.css
├── wallet
│ ├── web3Helper.js
│ ├── utils.js
│ ├── abiHelper.js
│ └── wallet.js
├── app
│ ├── store.js
│ └── reducer.js
├── divCheck
│ ├── buttonCheckTop.js
│ ├── connectButtonCheck.js
│ └── functionCheck.js
├── setupTests.js
├── reportWebVitals.js
├── __tests__
│ ├── App.test.js
│ └── __snapshots__
│ │ └── App.test.js.snap
├── constants.js
├── App.css
├── publicPath.js
├── index.js
├── App.js
├── logo.svg
├── utils.js
└── componentHelper.js
├── images
└── logo.png
├── public
├── favicon.ico
├── logo192.png
├── logo512.png
├── robots.txt
├── manifest.json
└── index.html
├── babel.config.js
├── .gitignore
├── craco.config.js
├── package.json
└── README.md
/src/contract_access_object/constants.js:
--------------------------------------------------------------------------------
1 | export const MOCK = false;
2 |
3 |
--------------------------------------------------------------------------------
/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nftblackmagic/web3cdn/HEAD/images/logo.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nftblackmagic/web3cdn/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nftblackmagic/web3cdn/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nftblackmagic/web3cdn/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | code {
2 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
3 | monospace;
4 | }
5 |
--------------------------------------------------------------------------------
/src/components/common/images/catchon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nftblackmagic/web3cdn/HEAD/src/components/common/images/catchon.png
--------------------------------------------------------------------------------
/src/wallet/web3Helper.js:
--------------------------------------------------------------------------------
1 |
2 | export const assert = (condition, msg) => {
3 | if (!condition) {
4 | throw msg || "assertion fail!";
5 | }
6 | };
7 |
8 |
9 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@babel/preset-env"],
3 | env: {
4 | test: {
5 | plugins: ["@babel/plugin-transform-modules-commonjs"],
6 | },
7 | },
8 | };
9 |
--------------------------------------------------------------------------------
/src/components/SignInModal/SignInModal.css:
--------------------------------------------------------------------------------
1 | .blur {
2 | position: absolute;
3 | background-color: rgba(0, 0, 0, 0.61);
4 | backdrop-filter: blur(5px);
5 | -webkit-backdrop-filter: blur(5px);
6 | width: 100vw;
7 | height: 100vh;
8 | top: 0;
9 | left: 0;
10 | z-index: 100;
11 | }
--------------------------------------------------------------------------------
/src/app/store.js:
--------------------------------------------------------------------------------
1 | import { configureStore } from "@reduxjs/toolkit";
2 | import rootReducer from "./reducer";
3 |
4 | export const store = configureStore({
5 | reducer: rootReducer,
6 | middleware: (getDefaultMiddleware) =>
7 | getDefaultMiddleware({
8 | serializableCheck: false,
9 | }),
10 | });
11 |
--------------------------------------------------------------------------------
/src/divCheck/buttonCheckTop.js:
--------------------------------------------------------------------------------
1 | // import { updateConnectButton, updateWalletStatus } from "./wallet.js";
2 | import { updateConnectButton } from "./connectButtonCheck";
3 | import { checkDivs } from "./functionCheck";
4 | // import { blacklist } from "./blacklist";
5 |
6 | export const initButtonCheck = async () => {
7 | checkDivs();
8 | updateConnectButton();
9 | }
10 |
11 | // init();
12 |
--------------------------------------------------------------------------------
/src/components/common/PowerBy.js:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import logoImage from "./images/catchon.png";
3 |
4 | import "./PowerBy.css";
5 |
6 | export const PowerBy = () => {
7 | return (
8 |
9 | Powered by
10 |
11 |
12 | )
13 | }
--------------------------------------------------------------------------------
/src/setupTests.js:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import "@testing-library/jest-dom";
6 | import { configure } from "enzyme";
7 | import Adapter from "@wojtekmaj/enzyme-adapter-react-17";
8 |
9 | configure({ adapter: new Adapter() });
10 |
--------------------------------------------------------------------------------
/src/reportWebVitals.js:
--------------------------------------------------------------------------------
1 | const reportWebVitals = onPerfEntry => {
2 | if (onPerfEntry && onPerfEntry instanceof Function) {
3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
4 | getCLS(onPerfEntry);
5 | getFID(onPerfEntry);
6 | getFCP(onPerfEntry);
7 | getLCP(onPerfEntry);
8 | getTTFB(onPerfEntry);
9 | });
10 | }
11 | };
12 |
13 | export default reportWebVitals;
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 | .env
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 | .vercel
26 |
--------------------------------------------------------------------------------
/src/components/muiStyle.js:
--------------------------------------------------------------------------------
1 | import { makeStyles } from '@mui/styles';
2 | import { isMobile } from '../utils';
3 |
4 | export const useStyles = makeStyles({
5 | root: {
6 | "& .MuiOutlinedInput-notchedOutline": {
7 | borderRadius: "10px",
8 | }
9 | }
10 | });
11 |
12 | export const titleClass = { width: "100%", padding: "0px" }
13 |
14 | export const cardClasses = isMobile() ? { minWidth: 275 } : { minWidth: 475 };
15 |
--------------------------------------------------------------------------------
/src/components/common/PowerBy.css:
--------------------------------------------------------------------------------
1 | .powerBy {
2 | display: flex;
3 | flex-direction: row;
4 | justify-content: center;
5 | align-items: center;
6 | gap: 5px;
7 | cursor: pointer;
8 | text-decoration: none;
9 | padding: 8px;
10 | }
11 |
12 | .powerBy h1 {
13 | color: gray;
14 | margin: 0;
15 | font-size: 14px;
16 | padding: 0;
17 | line-height: 120%;
18 | }
19 |
20 | .powerBy img {
21 | height: 14px;
22 | width: auto;
23 | margin: 0;
24 | padding: 0;
25 | }
--------------------------------------------------------------------------------
/src/__tests__/App.test.js:
--------------------------------------------------------------------------------
1 | import App from "../App";
2 | import { store } from "../app/store";
3 | import { Provider } from "react-redux";
4 | import { SnackbarProvider } from "notistack";
5 | import { mount } from "enzyme";
6 |
7 | test("renders learn react link", () => {
8 | const elem = (
9 | <>
10 |
11 |
12 |
13 |
14 |
15 | >
16 | );
17 | const wrapper = mount(elem);
18 | expect(wrapper.render()).toMatchSnapshot();
19 | });
20 |
--------------------------------------------------------------------------------
/src/constants.js:
--------------------------------------------------------------------------------
1 | export const GAS_INCREASE = 1.16;
2 |
3 | export const MINTED_CHECK_CAP = 5000;
4 |
5 | export const API_DB = "https://11xykht95a.execute-api.us-west-1.amazonaws.com/";
6 | export const ENABLE_MOCK = false;
7 |
8 | export const SELF_WALLET_SYMBOL = "--self-wallet";
9 |
10 | export const APP_TYPE_ECOMMERCE = "ecommerce";
11 | export const APP_TYPE_BOXCAT = "boxcat";
12 | export const APP_TYPE_BASE_NFT = "blanknft";
13 | export const APP_TYPE_MEMBERSHIP = "membership";
14 |
15 | export const APP_TYPES = [APP_TYPE_ECOMMERCE, APP_TYPE_BOXCAT, APP_TYPE_BASE_NFT, APP_TYPE_MEMBERSHIP];
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/app/reducer.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from "redux";
2 |
3 | // common reducers
4 | import userModalReducer from "../components/UserModal/UserModalSlice";
5 | import functionCallModalReducer from "../components/FunctionCallModal/FunctionCallSlice";
6 | import signInModalReducer from "../components/SignInModal/SignInModalSlice";
7 |
8 | const rootReducer = combineReducers({
9 | // Define a top-level state field named `todos`, handled by `todosReducer`
10 | userModal: userModalReducer,
11 | functionCallModal: functionCallModalReducer,
12 | signInModal: signInModalReducer,
13 | });
14 |
15 | export default rootReducer;
16 |
--------------------------------------------------------------------------------
/src/wallet/utils.js:
--------------------------------------------------------------------------------
1 |
2 | export const normalizeURL = (u) => new URL(u).host.replace("www.", "");
3 |
4 | export const isMobile = () =>
5 | /Mobi/i.test(window.navigator.userAgent) ||
6 | /iPhone|iPod|iPad/i.test(navigator.userAgent);
7 |
8 | export const objectMap = (object, mapFn) => {
9 | return Object.keys(object).reduce((result, key) => {
10 | result[key] = mapFn(object[key]);
11 | return result;
12 | }, {});
13 | };
14 |
15 |
16 | export const getChainID = () => {
17 | if (window.IS_TEST) {
18 | return 5;
19 | }
20 | else if (window.CHAINID) {
21 | return window.CHAINID;
22 | }
23 | }
24 |
25 | export const isValidAddress = (address) => {
26 | return /^(0x)?[0-9a-f]{40}$/i.test(address);
27 | }
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/publicPath.js:
--------------------------------------------------------------------------------
1 | /* global __webpack_public_path__:writable */
2 |
3 | /*
4 | * Setting webpack's public path dynamically instead of statically at the compilation process.
5 | * This allows users of the library to be able to host JS main bundle and its chunks anywhere they
6 | * like as long as all js files are in the same directory. Setting path dynamically allows entry .html
7 | * file to live separately from JS bundle files which is required for CDN/CMS deployments of
8 | * Mapbuilder.
9 | * https://webpack.js.org/guides/public-path/
10 | *
11 | * */
12 | //@ts-ignore
13 | const url = new URL(document.currentScript.src);
14 | const widgetLink = url.href.substring(0, url.href.lastIndexOf('/') + 1);
15 | //@ts-ignore
16 | __webpack_public_path__ = widgetLink;
17 | console.log(__webpack_public_path__);
--------------------------------------------------------------------------------
/src/components/FunctionCallModal/FunctionCallSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const initialState = {
4 | functionCallModalOpen: false,
5 | functionCallInfo: {},
6 | };
7 |
8 | const functionCallModalSlice = createSlice({
9 | name: "functionCallModal",
10 | initialState,
11 | reducers: {
12 | openFunctionCallModal: (state, action) => {
13 | state.functionCallInfo = action.payload;
14 | state.functionCallModalOpen = true
15 | },
16 | closeFunctionCallModal: (state) => {
17 | state.functionCallModalOpen = false;
18 | },
19 | },
20 | });
21 |
22 | export const {
23 | openFunctionCallModal,
24 | closeFunctionCallModal,
25 | } = functionCallModalSlice.actions;
26 |
27 | export default functionCallModalSlice.reducer;
28 |
--------------------------------------------------------------------------------
/src/components/SignInModal/SignInModalSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const initialState = {
4 | signInModal: false,
5 | orderSignData: ""
6 | };
7 |
8 | const signInModalReducer = createSlice({
9 | name: "signInModal",
10 | initialState,
11 | reducers: {
12 | openSignInModal: (state) => {
13 | console.log("openSignInModal");
14 | state.signInModal = true
15 | },
16 | closeSignInModal: (state) => {
17 | state.signInModal = false;
18 | },
19 | updateOrderSignData: (state, action) => {
20 | state.orderSignData = action.payload;
21 | },
22 | },
23 | });
24 |
25 | export const {
26 | openSignInModal,
27 | closeSignInModal,
28 | } = signInModalReducer.actions;
29 |
30 | export default signInModalReducer.reducer;
31 |
--------------------------------------------------------------------------------
/src/components/UserModal/UserModal.css:
--------------------------------------------------------------------------------
1 | .user-profile-wrapper {
2 | position: absolute;
3 | right: 0;
4 | top: 0;
5 | display: flex;
6 | flex-direction: column;
7 | align-items: center;
8 | justify-content: center;
9 | width: 200px;
10 | height: 600px;
11 | padding: 20px;
12 | }
13 |
14 | .user-modal-account {
15 | display: flex;
16 | flex-direction: row;
17 | gap: 10px;
18 | }
19 |
20 | .user-modal-wrapper {
21 | display: flex;
22 | flex-direction: column;
23 | gap: 10px;
24 | }
25 |
26 | /*
27 | .user-modal-account button {
28 | background-color: transparent;
29 | color: #333;
30 | border: none;
31 | font-size: 14px;
32 | font-weight: 400;
33 | cursor: pointer;
34 | border-radius: 100px;
35 | padding: 4px 8px;
36 | box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px;
37 | } */
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import "./publicPath";
2 | import React from 'react';
3 | import ReactDOM from 'react-dom';
4 | import './index.css';
5 | import App from './App';
6 | import reportWebVitals from './reportWebVitals';
7 | import { initButtonCheck } from './divCheck/buttonCheckTop';
8 | import { Provider } from 'react-redux';
9 | import { store } from './app/store';
10 | import { SnackbarProvider } from "notistack";
11 |
12 | const createDOMElement = () => {
13 | const body = document.getElementsByTagName('body')[0];
14 | const div = Object.assign(document.createElement('div'), {
15 | id: "root",
16 | });
17 | body.appendChild(div);
18 | return div;
19 | }
20 |
21 | export const renderAppContainer = () => {
22 | ReactDOM.render(
23 | <>
24 |
25 |
33 |
34 |
35 |
36 | >, createDOMElement());
37 | }
38 |
39 | document.addEventListener("DOMContentLoaded", () => {
40 | renderAppContainer();
41 | initButtonCheck();
42 | });
43 |
44 | reportWebVitals();
45 |
--------------------------------------------------------------------------------
/src/wallet/abiHelper.js:
--------------------------------------------------------------------------------
1 | import fetch from "node-fetch";
2 | import { API_DB } from "../constants";
3 | import * as _ from "lodash";
4 | /**
5 | * This file will be untimately replaced by Database calls.
6 | */
7 |
8 | var abi = {};
9 |
10 | // TODO: when converting this to db calls, remember to add "async" here and "await" at callers
11 | export const fetchAbiOfContractAt = async (contractAddr, chainId) => {
12 | if (contractAddr in abi) {
13 | console.log("ABI CACHE", contractAddr);
14 | return abi[contractAddr];
15 | }
16 | else if (window.ABI) {
17 | return window.ABI;
18 | }
19 | else {
20 | return await fetch(API_DB + "abi/" + chainId + "/" + contractAddr, {
21 | method: "GET",
22 | })
23 | .then((response) => response.json())
24 | .then(async (response) => {
25 | const dataFromDb = _.get(response, ["Item", "Abi"]);
26 | if (dataFromDb) {
27 | console.log("ABI from data base");
28 | // console.log("ABI", dataFromDb);
29 | abi[contractAddr] = JSON.parse(dataFromDb);
30 | return JSON.parse(dataFromDb);
31 | }
32 | else {
33 | alert("Cannot find correct abi!");
34 | throw new Error("Cannot find abi");
35 | }
36 |
37 | })
38 | .catch((error) => {
39 | console.error(error);
40 | });
41 | }
42 | };
--------------------------------------------------------------------------------
/src/contract_access_object/writerCao.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a collection of functions to write to contract via constructing and submitting a transaction
3 | */
4 |
5 |
6 | import { callFunction } from "./cao";
7 |
8 | /**
9 | * Create an ECOMERCE proxy owned by ownerAddr
10 | * @param {*} ownerAddr
11 | */
12 |
13 | export const setProxyCurrentRound = async (proxyAddr, curRound) => {
14 | return await callFunction(proxyAddr, "setCurrentRound", [curRound], 0, true);
15 | };
16 |
17 | export const setProxySetSupply = async (proxyAddr, tokenId, newSupply) => {
18 | return await callFunction(proxyAddr, "setSupply", [tokenId, newSupply], 0, true);
19 | };
20 |
21 | export const setProxySetMintOn = async (proxyAddr, tokenId, status) => {
22 | return await callFunction(proxyAddr, "setMintOn", [tokenId, status], 0, true);
23 | };
24 |
25 | export const setProxySetSaleInfo = async (proxyAddr, tokenId, price, maxSupply, isAllowlist, merkleTree) => {
26 | return await callFunction(proxyAddr, "setSaleInfo", [tokenId, price, maxSupply, isAllowlist, merkleTree], 0, true);
27 | };
28 |
29 | export const setProxyMint = async (proxyAddr, tokenId, amount, price) => {
30 | // console.log("MINT", tokenId, amount);
31 | return await callFunction(proxyAddr, "mint", [tokenId, amount], price, true);
32 | };
33 |
34 | export const setProxyBurn = async (proxyAddr, tokenId, amount) => {
35 | return await callFunction(proxyAddr, "forgeToken", [tokenId, amount], 0, true);
36 | };
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import { store } from "./app/store";
2 | import '@rainbow-me/rainbowkit/styles.css';
3 | import {
4 | getDefaultWallets,
5 | RainbowKitProvider,
6 | } from '@rainbow-me/rainbowkit';
7 | import { configureChains, createClient, WagmiConfig } from 'wagmi';
8 | import { mainnet, polygon, optimism, arbitrum, goerli } from 'wagmi/chains';
9 | import { infuraProvider } from 'wagmi/providers/infura';
10 | import { publicProvider } from 'wagmi/providers/public';
11 | import { UserModal } from './components/UserModal/UserModal';
12 | import { FunctionCallModal } from "./components/FunctionCallModal/FunctionCallView";
13 | import { SignInModal } from "./components/SignInModal/SignInModal";
14 | const { chains, provider } = configureChains(
15 | [mainnet, polygon, optimism, arbitrum, goerli],
16 | [
17 | infuraProvider({ apiKey: process.env.INFURA_API_KEY }),
18 | publicProvider(),
19 | ]
20 | );
21 |
22 | const { connectors } = getDefaultWallets({
23 | appName: 'My RainbowKit App',
24 | chains
25 | });
26 |
27 | const wagmiClient = createClient({
28 | autoConnect: true,
29 | connectors,
30 | provider
31 | })
32 | function App() {
33 |
34 | return (
35 | <>
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | >
44 | );
45 | }
46 |
47 | export default App;
48 |
--------------------------------------------------------------------------------
/src/divCheck/connectButtonCheck.js:
--------------------------------------------------------------------------------
1 | import { store } from "../app/store";
2 | import { closeUserModal, openUserModal } from "../components/UserModal/UserModalSlice";
3 | import { setButtonText } from "../utils";
4 |
5 | const connectSymbol = "connect-button"
6 |
7 |
8 | export const updateConnectButton = async () => {
9 | console.log("updateConnectButton");
10 | const connectButtons = [
11 | ...document.querySelectorAll(`[${connectSymbol}]`)
12 | ]
13 | if (connectButtons) {
14 | console.log(connectButtons);
15 | connectButtons.forEach((connectButton) => {
16 | // get information from div attribute
17 | connectButton.href = "#"
18 | connectButton.onclick = async () => {
19 | console.log("CLICK the button")
20 | const initialBtnText = connectButton.textContent;
21 | setButtonText(connectButton, "Loading...")
22 | if (store.getState().userModal.userModalOpen) {
23 | store.dispatch(closeUserModal());
24 | }
25 | else {
26 | store.dispatch(openUserModal());
27 | }
28 | setButtonText(connectButton, initialBtnText)
29 | }
30 | })
31 | }
32 | }
33 |
34 | export const updateConnectButtonText = (text) => {
35 | const connectButtons = [
36 | ...document.querySelectorAll(`[${connectSymbol}]`)
37 | ]
38 | if (connectButtons) {
39 | // console.log(connectButtons);
40 | connectButtons.forEach((connectButton) => {
41 | // get information from div attribute
42 | setButtonText(connectButton, text)
43 | })
44 | }
45 | }
--------------------------------------------------------------------------------
/src/contract_access_object/cao.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Contract Access Object(CAO)
3 | */
4 |
5 | import { fetchContractObjByAddr } from "../wallet/wallet";
6 | import { assert } from "../wallet/web3Helper";
7 | import { ethers } from "ethers";
8 |
9 | export const GAS_INCREASE = 116;
10 |
11 | export const callViewFunction = async (contractAddr, methodName, args) => {
12 | const contractObj = fetchContractObjAt(contractAddr);
13 | console.log("callViewFunction", methodName);
14 | return getFunctionSignature(contractObj, methodName, args);
15 | };
16 |
17 | const increaseGasLimit = (estimatedGasLimit) => {
18 | return estimatedGasLimit.mul(GAS_INCREASE).div(100)
19 | }
20 |
21 | /**
22 | * This is for non-view function call only. For view function call, use callViewFunction() instead.
23 | */
24 | export const callFunction = async (
25 | contractAddr,
26 | methodName,
27 | args,
28 | value = 0,
29 | requireGasOptimize = true
30 | ) => {
31 | const contractObj = await fetchContractObjAt(contractAddr);
32 |
33 | assert(contractObj, `contract obj is not defined: ${contractObj}`);
34 | const options = { value: ethers.utils.parseUnits(value.toString(), "wei") };
35 |
36 | if (requireGasOptimize) {
37 | const estimation = (await contractObj.estimateGas[methodName](...args, options));
38 | const optionsWithGas = {
39 | ...options,
40 | gasLimit: increaseGasLimit(estimation),
41 | }
42 | return await contractObj[methodName](...args, optionsWithGas);
43 | } else {
44 | return await contractObj[methodName](...args, options);
45 | }
46 | };
47 |
48 | const getFunctionSignature = async (contractObj, functionName, args) => {
49 | if (args === undefined) {
50 | args = [];
51 | }
52 | const res = await contractObj[functionName](...args);
53 | return res;
54 | };
55 |
56 | const fetchContractObjAt = (contractAddr) => {
57 | return fetchContractObjByAddr(contractAddr);
58 | };
59 |
--------------------------------------------------------------------------------
/craco.config.js:
--------------------------------------------------------------------------------
1 | const rewireBabelLoader = require("craco-babel-loader");
2 | const { realpathSync } = require("fs");
3 | const { resolve } = require("path");
4 | const Dotenv = require("dotenv-webpack");
5 |
6 | function forceAbsolutePackage(relativePath) {
7 | const appDirectory = realpathSync(process.cwd());
8 | return resolve(appDirectory, relativePath);
9 | }
10 |
11 | module.exports = {
12 | babel: {
13 | plugins: [["@babel/plugin-proposal-decorators", { legacy: true }]],
14 | },
15 | plugins: [
16 | //This is a craco plugin: https://github.com/sharegate/craco/blob/master/packages/craco/README.md#configuration-overview
17 | {
18 | plugin: rewireBabelLoader,
19 | options: {
20 | includes: [
21 | // On force un absolute path car c'est requis par babel-loader
22 | forceAbsolutePackage("node_modules/@wagmi/core/dist"),
23 | forceAbsolutePackage("node_modules/wagmi/dist"),
24 | ],
25 | },
26 | },
27 | ],
28 | webpack: {
29 | alias: {},
30 | configure: (webpackConfig, { env, paths }) => {
31 | webpackConfig.plugins.push(
32 | new Dotenv({ systemvars: true, path: "./.env" })
33 | );
34 | // console.log("webpackConfig", env);
35 | const isEnvProduction = env === "production";
36 | const isEnvDevelopment = env === "development";
37 | webpackConfig.output.libraryTarget = "umd";
38 | webpackConfig.output.library = "NFTComponents";
39 |
40 | webpackConfig.output.publicPath = "";
41 |
42 | webpackConfig.output.filename = isEnvProduction
43 | ? "[name].js"
44 | : isEnvDevelopment && "bundle.js";
45 | // Turn off chunking
46 | webpackConfig.optimization = {};
47 |
48 | const miniCssPlugin = webpackConfig.plugins.find(
49 | ({ constructor }) => constructor.name === "MiniCssExtractPlugin"
50 | );
51 | if (miniCssPlugin) {
52 | miniCssPlugin.options.filename = "[name].css";
53 | miniCssPlugin.options.chunkFilename = "[name].css";
54 | }
55 | return webpackConfig;
56 | },
57 | },
58 | };
59 |
--------------------------------------------------------------------------------
/src/components/UserModal/UserModal.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createTheme } from "@mui/material/styles";
3 | import { ThemeProvider } from "@mui/material";
4 | import Dialog from '@mui/material/Dialog';
5 | import DialogContent from '@mui/material/DialogContent';
6 | import Slide from '@mui/material/Slide';
7 | import { UserSection } from "./UserSection";
8 | import { useDispatch, useSelector } from 'react-redux';
9 | import { closeUserModal } from './UserModalSlice';
10 |
11 | const Transition = React.forwardRef(function Transition(props, ref) {
12 | return ;
13 | });
14 |
15 | const theme = createTheme({
16 | components: {
17 | // Name of the component
18 | MuiDialog: {
19 | styleOverrides: {
20 | // Name of the slot
21 | root: {
22 | // Some CSS
23 | left: 'auto !important',
24 | bottom: 'auto !important',
25 | },
26 | },
27 | },
28 | },
29 | });
30 |
31 |
32 | export const UserModal = () => {
33 | const userModalOpen = useSelector(state => state.userModal.userModalOpen);
34 | const dispatch = useDispatch();
35 | const handleClose = () => {
36 | dispatch(closeUserModal());
37 | };
38 |
39 | return (
40 | <>
41 |
42 |
60 |
61 | >
62 | )
63 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-widget",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@craco/craco": "^6.4.5",
7 | "@emotion/react": "^11.10.4",
8 | "@emotion/styled": "^11.10.4",
9 | "@mui/icons-material": "^5.10.6",
10 | "@mui/material": "^5.10.6",
11 | "@mui/styles": "^5.10.14",
12 | "@rainbow-me/rainbowkit": "^0.8.1",
13 | "@reduxjs/toolkit": "^1.9.0",
14 | "@testing-library/jest-dom": "^5.11.4",
15 | "@testing-library/react": "^11.1.0",
16 | "@testing-library/user-event": "^12.1.10",
17 | "@walletconnect/web3-provider": "^1.8.0",
18 | "craco-babel-loader": "^1.0.4",
19 | "ethers": "^5.7.2",
20 | "keccak256": "^1.0.6",
21 | "merkletreejs": "^0.2.32",
22 | "notistack": "^2.0.8",
23 | "react": "^17.0.2",
24 | "react-dom": "^17.0.2",
25 | "react-icons": "^4.6.0",
26 | "react-redux": "^8.0.5",
27 | "react-scripts": "4.0.3",
28 | "redux": "^4.2.0",
29 | "use-debounce": "^9.0.2",
30 | "wagmi": "0.9.1",
31 | "web-vitals": "^1.0.1",
32 | "web3": "^1.8.0",
33 | "web3modal": "^1.9.9"
34 | },
35 | "scripts": {
36 | "start": "craco start",
37 | "dev": "craco start",
38 | "build": "craco build",
39 | "test": "craco test",
40 | "eject": "react-scripts eject"
41 | },
42 | "eslintConfig": {
43 | "extends": [
44 | "react-app",
45 | "react-app/jest"
46 | ]
47 | },
48 | "browserslist": {
49 | "production": [
50 | ">0.2%",
51 | "not dead",
52 | "not op_mini all"
53 | ],
54 | "development": [
55 | "last 1 chrome version",
56 | "last 1 firefox version",
57 | "last 1 safari version"
58 | ]
59 | },
60 | "devDependencies": {
61 | "@types/jest": "^29.2.4",
62 | "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
63 | "dotenv-webpack": "^8.0.1",
64 | "enzyme": "^3.11.0",
65 | "html-webpack-plugin": "^4.5.2",
66 | "parcel-bundler": "^1.12.5",
67 | "react-test-renderer": "^17.0.2"
68 | },
69 | "jest": {
70 | "transformIgnorePatterns": [
71 | "node_modules/(?!<@rainbow-me>)/"
72 | ],
73 | "transform": {
74 | ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy",
75 | "^.+\\.(js|jsx)?$": "babel-jest"
76 | },
77 | "testMatch": [
78 | "/(tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))"
79 | ]
80 | }
81 | }
--------------------------------------------------------------------------------
/src/components/UserModal/UserModalSlice.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 | import { updateConnectButtonText } from "../../divCheck/connectButtonCheck";
3 | import { isValidAddress } from "../../wallet/utils";
4 | import { formatWalletAddress } from "../../utils";
5 |
6 | const initialState = {
7 | userModalOpen: false,
8 | walletAddress: "",
9 | isInitializedContract: false,
10 | chainId: {},
11 | provider: {},
12 | signer: {},
13 | orderSignData: "",
14 | readFunction: [],
15 | };
16 |
17 | const userModalReducer = createSlice({
18 | name: "userModal",
19 | initialState,
20 | reducers: {
21 | openUserModal: (state) => {
22 | state.userModalOpen = true
23 | },
24 | closeUserModal: (state) => {
25 | state.userModalOpen = false;
26 | },
27 | updateWalletAddress: (state, action) => {
28 | state.walletAddress = action.payload
29 | if (isValidAddress(state.walletAddress)) {
30 | updateConnectButtonText(formatWalletAddress(state.walletAddress));
31 | }
32 | else {
33 | updateConnectButtonText("Connect Wallet");
34 | }
35 | },
36 | updateChainId: (state, action) => {
37 | state.chainId = action.payload
38 | },
39 | updateProvider: (state, action) => {
40 | state.provider = action.payload
41 | },
42 | updateSigner: (state, action) => {
43 | state.signer = action.payload
44 | },
45 | updateOrderSignData: (state, action) => {
46 | state.orderSignData = action.payload
47 | },
48 | updateReadFunction: (state, action) => {
49 | state.readFunction = action.payload
50 | },
51 | appendReadFunction: (state, action) => {
52 | state.readFunction.push(action.payload)
53 | },
54 | updateIsInitializedContract: (state, action) => {
55 | state.isInitializedContract = action.payload
56 | },
57 | },
58 | });
59 |
60 | export const {
61 | openUserModal,
62 | closeUserModal,
63 | updateWalletAddress,
64 | updateChainId,
65 | updateProvider,
66 | updateSigner,
67 | updateOrderSignData,
68 | updateReadFunction,
69 | appendReadFunction,
70 | updateIsInitializedContract,
71 | } = userModalReducer.actions;
72 |
73 | export default userModalReducer.reducer;
74 |
--------------------------------------------------------------------------------
/src/contract_access_object/readerCao.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This is a collection of functions to read from contract, i.e. Contract Access Object
3 | */
4 |
5 | import { callViewFunction } from "./cao";
6 |
7 | /**
8 | * A testing function to make sure we are able to call function on proxy
9 | * @param {*} proxyAddr
10 | */
11 | export const getProxySymbol = async (proxyAddr) => {
12 | const res = await callViewFunction(proxyAddr, "symbol", []);
13 | return res;
14 | };
15 |
16 | export const getProxyMintInfoOfRound = async (proxyAddr, round) => {
17 | const res = await callViewFunction(proxyAddr, "mintInfo", [round]);
18 | return res;
19 | };
20 |
21 | export const getProxyIsMintOn = async (proxyAddr, round) => {
22 | const res = await callViewFunction(proxyAddr, "isMintOn", [round]);
23 | return res;
24 | };
25 |
26 | // export const getProxyCurrentRoundByTokenID = async (proxyAddr, tokenId) => {
27 | // const res = await callViewFunction(proxyAddr, "currentRound", [tokenId]);
28 | // return res;
29 | // };
30 |
31 | export const getProxyIsMintOnByTokenID = async (proxyAddr, tokenId) => {
32 | const res = await callViewFunction(proxyAddr, "isMintOn", [tokenId]);
33 | console.log("MINT", tokenId, res);
34 | return res;
35 | };
36 |
37 | export const getProxyPriceByTokenID = async (proxyAddr, tokenId) => {
38 | const res = await callViewFunction(proxyAddr, "mintPrice", [tokenId]);
39 | return res;
40 | };
41 |
42 | export const getProxyMintedByTokenID = async (proxyAddr, tokenId) => {
43 | const res = await callViewFunction(proxyAddr, "tokenMinted", [tokenId]);
44 | return res;
45 | };
46 |
47 | export const getProxySupplyByTokenID = async (proxyAddr, tokenId) => {
48 | const res = await callViewFunction(proxyAddr, "supplyLimit", [tokenId]);
49 | return res;
50 | };
51 |
52 | export const getProxyBalanceByTokenID = async (proxyAddr, user, tokenId) => {
53 | const res = await callViewFunction(proxyAddr, "balanceOf", [user, tokenId]);
54 | return res;
55 | };
56 |
57 | export const getProxyName = async (proxyAddr) => {
58 | const res = await callViewFunction(proxyAddr, "name", []);
59 | return res;
60 | }
61 |
62 | export const getProxyMinted = async (proxyAddr) => {
63 | const res = await callViewFunction(proxyAddr, "totalSupply", []);
64 | return res;
65 | }
66 |
67 | /**
68 | * Returns proxy specific data.
69 | * TODO: fill XX with meaningful wording, e.g. getProxyPublicMintTime
70 | */
71 | export const getProxyXX = async (proxyAddr) => { };
72 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
25 | React App
26 |
27 |
28 |
29 |
30 |
33 | Name:
34 |
35 | Name
36 |
37 | balance Of self:
38 |
39 | balanceOf
40 |
41 | Total Supply:
42 |
43 | totalSupply
44 |
45 | saleConfig:
46 |
47 | saleConfig
48 |
49 | Mint:
50 |
53 |
56 |
59 | set sale info
60 |
63 |
68 |
69 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/__tests__/__snapshots__/App.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`renders learn react link 1`] = `
4 | LoadedCheerio {
5 | "0":
8 |
11 |
,
12 | "_root": LoadedCheerio {
13 | "0": Document {
14 | "children": Array [
15 |
16 |
17 |