create-stylus 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/issue_template.md +7 -0
- package/.github/pull_request_template.md +11 -0
- package/.github/workflows/release-alpha.yml +32 -0
- package/.github/workflows/release-manual.yml +26 -0
- package/.yarnrc.yml +1 -0
- package/CONTRIBUTING.md +42 -0
- package/README.md +66 -0
- package/bin/create-dapp-ss.js +4 -0
- package/package.json +46 -0
- package/rollup.config.js +22 -0
- package/src/cli.ts +14 -0
- package/src/extensions.json +14 -0
- package/src/main.ts +72 -0
- package/src/tasks/copy-extension-file.ts +227 -0
- package/src/tasks/copy-template-files.ts +252 -0
- package/src/tasks/create-first-git-commit.ts +35 -0
- package/src/tasks/create-project-directory.ts +34 -0
- package/src/tasks/index.ts +5 -0
- package/src/tasks/install-packages.ts +15 -0
- package/src/tasks/prettier-format.ts +17 -0
- package/src/types.ts +31 -0
- package/src/utils/consts.ts +1 -0
- package/src/utils/find-files-recursively.ts +19 -0
- package/src/utils/link.ts +44 -0
- package/src/utils/load-extensions.ts +10 -0
- package/src/utils/merge-package-json.ts +33 -0
- package/src/utils/parse-arguments-into-options.ts +38 -0
- package/src/utils/prompt-for-missing-options.ts +53 -0
- package/src/utils/render-intro-message.ts +11 -0
- package/src/utils/render-outro-message.ts +34 -0
- package/templates/base/.github/ISSUE_TEMPLATE/bug_report.yml +58 -0
- package/templates/base/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/templates/base/.github/pull_request_template.md +16 -0
- package/templates/base/.github/workflows/lint.yaml +300 -0
- package/templates/base/.gitignore.template.mjs +19 -0
- package/templates/base/.gitmodules +0 -0
- package/templates/base/.husky/pre-commit +4 -0
- package/templates/base/.lintstagedrc.js +21 -0
- package/templates/base/.vscode/settings.json +7 -0
- package/templates/base/.yarn/plugins/@yarnpkg/plugin-typescript.cjs +9 -0
- package/templates/base/.yarn/releases/yarn-3.2.3.cjs +783 -0
- package/templates/base/.yarnrc.yml +11 -0
- package/templates/base/CONTRIBUTING.md +86 -0
- package/templates/base/LICENCE +21 -0
- package/templates/base/dist/cli.js +683 -0
- package/templates/base/dist/cli.js.map +1 -0
- package/templates/base/nitro-devnode/LICENSE +201 -0
- package/templates/base/nitro-devnode/README.md +70 -0
- package/templates/base/nitro-devnode/run-dev-node.sh +132 -0
- package/templates/base/nitro-devnode/start-chain-with-cors.sh +150 -0
- package/templates/base/nitro-devnode/stylus-deployer-bytecode.txt +1 -0
- package/templates/base/nitro-devnode/stylus-dev/Dockerfile +10 -0
- package/templates/base/package.json +44 -0
- package/templates/base/packages/nextjs/.env.example +13 -0
- package/templates/base/packages/nextjs/.eslintignore +11 -0
- package/templates/base/packages/nextjs/.eslintrc.json +15 -0
- package/templates/base/packages/nextjs/.gitignore.template.mjs +42 -0
- package/templates/base/packages/nextjs/.prettierrc.js +9 -0
- package/templates/base/packages/nextjs/.prettierrc.json +8 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressCodeTab.tsx +27 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressComponent.tsx +36 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressLogsTab.tsx +21 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/AddressStorageTab.tsx +61 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/BackButton.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/ContractTabs.tsx +102 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/PaginationButton.tsx +39 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/SearchBar.tsx +49 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionHash.tsx +28 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/TransactionsTable.tsx +71 -0
- package/templates/base/packages/nextjs/app/blockexplorer/_components/index.tsx +7 -0
- package/templates/base/packages/nextjs/app/blockexplorer/address/[address]/page.tsx +101 -0
- package/templates/base/packages/nextjs/app/blockexplorer/layout.tsx +12 -0
- package/templates/base/packages/nextjs/app/blockexplorer/page.tsx +83 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/[txHash]/page.tsx +23 -0
- package/templates/base/packages/nextjs/app/blockexplorer/transaction/_components/TransactionComp.tsx +152 -0
- package/templates/base/packages/nextjs/app/debug/_components/DebugContracts.tsx +73 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractInput.tsx +84 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractReadMethods.tsx +43 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractUI.tsx +164 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractVariables.tsx +50 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ContractWriteMethods.tsx +49 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/DisplayVariable.tsx +85 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/InheritanceTooltip.tsx +14 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx +102 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/Tuple.tsx +44 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TupleArray.tsx +142 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/TxReceipt.tsx +42 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/WriteOnlyFunctionForm.tsx +144 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/index.tsx +8 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsContract.tsx +166 -0
- package/templates/base/packages/nextjs/app/debug/_components/contract/utilsDisplay.tsx +114 -0
- package/templates/base/packages/nextjs/app/debug/page.tsx +14 -0
- package/templates/base/packages/nextjs/app/layout.tsx +67 -0
- package/templates/base/packages/nextjs/app/not-found.tsx +16 -0
- package/templates/base/packages/nextjs/app/page.tsx +94 -0
- package/templates/base/packages/nextjs/components/Background.tsx +37 -0
- package/templates/base/packages/nextjs/components/Card.tsx +40 -0
- package/templates/base/packages/nextjs/components/Footer.tsx +93 -0
- package/templates/base/packages/nextjs/components/Header.tsx +114 -0
- package/templates/base/packages/nextjs/components/ScaffoldEthAppWithProviders.tsx +77 -0
- package/templates/base/packages/nextjs/components/SwitchTheme.tsx +41 -0
- package/templates/base/packages/nextjs/components/ThemeProvider.tsx +13 -0
- package/templates/base/packages/nextjs/components/assets/BuidlGuidlLogo.tsx +18 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/Address.tsx +187 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressCopyIcon.tsx +23 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Address/AddressLinkWrapper.tsx +29 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Balance.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/BlockieAvatar.tsx +17 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Faucet.tsx +131 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/FaucetButton.tsx +75 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx +120 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/Bytes32Input.tsx +31 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/BytesInput.tsx +28 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/EtherInput.tsx +128 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx +66 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/IntegerInput.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/index.ts +9 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/Input/utils.ts +109 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressInfoDropdown.tsx +121 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/AddressQRCodeModal.tsx +33 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/BurnerWalletModal.tsx +63 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/NetworkOptions.tsx +48 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/WrongNetworkDropdown.tsx +32 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/RainbowKitCustomConnectButton/index.tsx +89 -0
- package/templates/base/packages/nextjs/components/scaffold-eth/index.tsx +7 -0
- package/templates/base/packages/nextjs/contracts/deployedContracts.ts +9 -0
- package/templates/base/packages/nextjs/contracts/externalContracts.ts +16 -0
- package/templates/base/packages/nextjs/eslint.config.mjs +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/index.ts +17 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useAnimationConfig.ts +20 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useContractLogs.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useCopyToClipboard.ts +19 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDeployedContractInfo.ts +86 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useDisplayUsdMode.ts +21 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useFetchBlocks.ts +133 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useInitializeNativeCurrencyPrice.ts +32 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNativeCurrencyPrice.ts +34 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useNetworkColor.ts +22 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useOutsideClick.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldContract.ts +65 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldEventHistory.ts +213 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldReadContract.ts +80 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWatchContractEvent.ts +40 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useScaffoldWriteContract.ts +191 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useSelectedNetwork.ts +18 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTargetNetwork.ts +23 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useTransactor.tsx +114 -0
- package/templates/base/packages/nextjs/hooks/scaffold-eth/useWatchBalance.ts +21 -0
- package/templates/base/packages/nextjs/icons/CompassIcon.tsx +39 -0
- package/templates/base/packages/nextjs/icons/DarkBugAntIcon.tsx +30 -0
- package/templates/base/packages/nextjs/icons/LightBugAntIcon.tsx +52 -0
- package/templates/base/packages/nextjs/next-env.d.ts +5 -0
- package/templates/base/packages/nextjs/next.config.js +19 -0
- package/templates/base/packages/nextjs/package.json +58 -0
- package/templates/base/packages/nextjs/postcss.config.js +6 -0
- package/templates/base/packages/nextjs/public/debug-image.png +0 -0
- package/templates/base/packages/nextjs/public/favicon.png +0 -0
- package/templates/base/packages/nextjs/public/logo.svg +8 -0
- package/templates/base/packages/nextjs/public/manifest.json +5 -0
- package/templates/base/packages/nextjs/public/thumbnail.jpg +0 -0
- package/templates/base/packages/nextjs/react-copy-to-clipboard.d.ts +44 -0
- package/templates/base/packages/nextjs/scaffold.config.ts +56 -0
- package/templates/base/packages/nextjs/services/store/store.ts +39 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConfig.tsx +44 -0
- package/templates/base/packages/nextjs/services/web3/wagmiConnectors.tsx +51 -0
- package/templates/base/packages/nextjs/styles/globals.css +80 -0
- package/templates/base/packages/nextjs/tailwind.config.js +97 -0
- package/templates/base/packages/nextjs/tsconfig.json +28 -0
- package/templates/base/packages/nextjs/types/abitype/abi.d.ts +16 -0
- package/templates/base/packages/nextjs/types/utils.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/block.ts +17 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/common.ts +8 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contract.ts +352 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/contractsData.ts +11 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/decodeTxData.ts +65 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/fetchPriceFromUniswap.ts +72 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getMetadata.ts +50 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/getParsedError.ts +35 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/index.ts +6 -0
- package/templates/base/packages/nextjs/utils/scaffold-eth/notification.tsx +90 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/burner.ts +59 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/chain.ts +42 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/index.ts +3 -0
- package/templates/base/packages/nextjs/utils/scaffold-stylus/networks.ts +94 -0
- package/templates/base/packages/nextjs/vercel.json +3 -0
- package/templates/base/packages/stylus/.env.example +16 -0
- package/templates/base/packages/stylus/.eslintrc.js +23 -0
- package/templates/base/packages/stylus/.gitignore.template.mjs +7 -0
- package/templates/base/packages/stylus/jest.config.js +15 -0
- package/templates/base/packages/stylus/package.json +48 -0
- package/templates/base/packages/stylus/scripts/deploy.ts +46 -0
- package/templates/base/packages/stylus/scripts/deploy_contract.ts +84 -0
- package/templates/base/packages/stylus/scripts/deploy_wrapper.ts +39 -0
- package/templates/base/packages/stylus/scripts/export_abi.ts +87 -0
- package/templates/base/packages/stylus/scripts/index.ts +0 -0
- package/templates/base/packages/stylus/scripts/new_module.sh +35 -0
- package/templates/base/packages/stylus/scripts/test_network.ts +31 -0
- package/templates/base/packages/stylus/scripts/utils/command.ts +152 -0
- package/templates/base/packages/stylus/scripts/utils/contract.ts +228 -0
- package/templates/base/packages/stylus/scripts/utils/deployment.ts +260 -0
- package/templates/base/packages/stylus/scripts/utils/index.ts +6 -0
- package/templates/base/packages/stylus/scripts/utils/network.ts +132 -0
- package/templates/base/packages/stylus/scripts/utils/type.ts +51 -0
- package/templates/base/packages/stylus/scripts/utils.ts +3 -0
- package/templates/base/packages/stylus/tsconfig.json +41 -0
- package/templates/base/packages/stylus/your-contract/.cargo/config.toml +18 -0
- package/templates/base/packages/stylus/your-contract/Cargo.lock +5761 -0
- package/templates/base/packages/stylus/your-contract/Cargo.toml +48 -0
- package/templates/base/packages/stylus/your-contract/examples/counter.rs +78 -0
- package/templates/base/packages/stylus/your-contract/header.png +0 -0
- package/templates/base/packages/stylus/your-contract/licenses/Apache-2.0 +201 -0
- package/templates/base/packages/stylus/your-contract/licenses/COPYRIGHT.md +5 -0
- package/templates/base/packages/stylus/your-contract/licenses/DCO.txt +34 -0
- package/templates/base/packages/stylus/your-contract/licenses/MIT +21 -0
- package/templates/base/packages/stylus/your-contract/rust-toolchain.toml +2 -0
- package/templates/base/packages/stylus/your-contract/src/lib.rs +241 -0
- package/templates/base/packages/stylus/your-contract/src/main.rs +10 -0
- package/templates/base/readme.md +352 -0
- package/templates/base/yarn.lock +17859 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// @refresh reset
|
|
4
|
+
import { useReducer } from "react";
|
|
5
|
+
import { ContractReadMethods } from "./ContractReadMethods";
|
|
6
|
+
import { ContractVariables } from "./ContractVariables";
|
|
7
|
+
import { ContractWriteMethods } from "./ContractWriteMethods";
|
|
8
|
+
import { Address, Balance } from "~~/components/scaffold-eth";
|
|
9
|
+
import { useDeployedContractInfo, useNetworkColor } from "~~/hooks/scaffold-eth";
|
|
10
|
+
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
|
|
11
|
+
import { ContractName } from "~~/utils/scaffold-eth/contract";
|
|
12
|
+
|
|
13
|
+
type ContractUIProps = {
|
|
14
|
+
contractName: ContractName;
|
|
15
|
+
className?: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* UI component to interface with deployed contracts.
|
|
20
|
+
**/
|
|
21
|
+
export const ContractUI = ({ contractName, className = "" }: ContractUIProps) => {
|
|
22
|
+
const [refreshDisplayVariables, triggerRefreshDisplayVariables] = useReducer(value => !value, false);
|
|
23
|
+
const { targetNetwork } = useTargetNetwork();
|
|
24
|
+
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo({ contractName });
|
|
25
|
+
const networkColor = useNetworkColor();
|
|
26
|
+
|
|
27
|
+
if (deployedContractLoading) {
|
|
28
|
+
return (
|
|
29
|
+
<div className="mt-14">
|
|
30
|
+
<span className="loading loading-spinner loading-lg"></span>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!deployedContractData) {
|
|
36
|
+
return (
|
|
37
|
+
<p className="text-3xl mt-14">
|
|
38
|
+
{`No contract found by the name of "${contractName}" on chain "${targetNetwork.name}"!`}
|
|
39
|
+
</p>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className={`grid grid-cols-1 lg:grid-cols-6 px-6 lg:px-10 lg:gap-12 w-full max-w-7xl my-0 ${className}`}>
|
|
45
|
+
<div className="col-span-5 grid grid-cols-1 lg:grid-cols-3 gap-8 lg:gap-10">
|
|
46
|
+
<div className="col-span-1 flex flex-col">
|
|
47
|
+
<div className="gradient-border shadow-md shadow-secondary rounded-xl px-6 lg:px-8 mb-6 space-y-1 py-4">
|
|
48
|
+
<div className="flex">
|
|
49
|
+
<div className="flex flex-col gap-1">
|
|
50
|
+
<span className="font-bold">{contractName}</span>
|
|
51
|
+
<Address address={deployedContractData.address} onlyEnsOrAddress />
|
|
52
|
+
<div className="flex gap-1 items-center">
|
|
53
|
+
<span className="font-bold text-sm">Balance:</span>
|
|
54
|
+
<Balance address={deployedContractData.address} className="px-0 h-1.5 min-h-[0.375rem]" />
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
{targetNetwork && (
|
|
59
|
+
<p className="my-0 text-sm">
|
|
60
|
+
<span className="font-bold">Network</span>:{" "}
|
|
61
|
+
<span style={{ color: networkColor }}>{targetNetwork.name}</span>
|
|
62
|
+
</p>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
<div className="gradient-border rounded-xl px-6 lg:px-8 py-4 shadow-lg shadow-base-300">
|
|
66
|
+
<ContractVariables
|
|
67
|
+
refreshDisplayVariables={refreshDisplayVariables}
|
|
68
|
+
deployedContractData={deployedContractData}
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
<div className="col-span-1 lg:col-span-2 flex flex-col gap-6">
|
|
73
|
+
<div className="z-10">
|
|
74
|
+
<div
|
|
75
|
+
className="flex flex-col gap-4"
|
|
76
|
+
//className="relative mt-10"
|
|
77
|
+
>
|
|
78
|
+
{/* Read Tab */}
|
|
79
|
+
{/*<div className="absolute -top-8 left-0 flex items-center z-20">*/}
|
|
80
|
+
<div className="relative inline-block w-[23%]">
|
|
81
|
+
{/* Botón con clip-path */}
|
|
82
|
+
<div
|
|
83
|
+
className="text-white px-8 py-2 text-xl font-medium border-2 relative z-10"
|
|
84
|
+
style={{
|
|
85
|
+
backgroundColor: "#630c3a",
|
|
86
|
+
borderColor: "#E3066E",
|
|
87
|
+
clipPath: "polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%)",
|
|
88
|
+
}}
|
|
89
|
+
>
|
|
90
|
+
Read
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
{/* Línea diagonal del corte */}
|
|
94
|
+
<div
|
|
95
|
+
className="absolute z-20"
|
|
96
|
+
style={{
|
|
97
|
+
top: "20px", // deja espacio para el border superior
|
|
98
|
+
right: "-1px", // deja espacio para el border derecho
|
|
99
|
+
width: "28.28px", // 20 * sqrt(2)
|
|
100
|
+
height: "2px", // igual al grosor del borde
|
|
101
|
+
backgroundColor: "#E3066E",
|
|
102
|
+
transform: "rotate(45deg)",
|
|
103
|
+
transformOrigin: "top right",
|
|
104
|
+
}}
|
|
105
|
+
/>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
{/*</div> */}
|
|
109
|
+
{/* Gradient Container */}
|
|
110
|
+
<div className="rounded-lg gradient-border min-h-[80px] flex items-center px-4 py-8 shadow-xl">
|
|
111
|
+
<ContractReadMethods deployedContractData={deployedContractData} />
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
<div className="z-10">
|
|
116
|
+
<div
|
|
117
|
+
className="flex flex-col gap-4"
|
|
118
|
+
//className="relative mt-10"
|
|
119
|
+
>
|
|
120
|
+
{/* Read Tab */}
|
|
121
|
+
{/*<div className="absolute -top-8 left-0 flex items-center z-20">*/}
|
|
122
|
+
<div className="relative inline-block w-[23%]">
|
|
123
|
+
{/* Botón con clip-path */}
|
|
124
|
+
<div
|
|
125
|
+
className="text-white px-8 py-2 text-xl font-medium border-2 relative z-10"
|
|
126
|
+
style={{
|
|
127
|
+
backgroundColor: "#630c3a",
|
|
128
|
+
borderColor: "#E3066E",
|
|
129
|
+
clipPath: "polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%)",
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
132
|
+
Write
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
{/* Línea diagonal del corte */}
|
|
136
|
+
<div
|
|
137
|
+
className="absolute z-20"
|
|
138
|
+
style={{
|
|
139
|
+
top: "20px", // deja espacio para el border superior
|
|
140
|
+
right: "-1px", // deja espacio para el border derecho
|
|
141
|
+
width: "28.28px", // 20 * sqrt(2)
|
|
142
|
+
height: "2px", // igual al grosor del borde
|
|
143
|
+
backgroundColor: "#E3066E",
|
|
144
|
+
transform: "rotate(45deg)",
|
|
145
|
+
transformOrigin: "top right",
|
|
146
|
+
}}
|
|
147
|
+
/>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
{/*</div> */}
|
|
151
|
+
{/* Gradient Container */}
|
|
152
|
+
<div className="gradient-border rounded-lg min-h-[80px] flex flex-col px-6 py-6 shadow-xl">
|
|
153
|
+
<ContractWriteMethods
|
|
154
|
+
deployedContractData={deployedContractData}
|
|
155
|
+
onChange={triggerRefreshDisplayVariables}
|
|
156
|
+
/>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
);
|
|
164
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DisplayVariable } from "./DisplayVariable";
|
|
2
|
+
import { Abi, AbiFunction } from "abitype";
|
|
3
|
+
import { Contract, ContractName, GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract";
|
|
4
|
+
|
|
5
|
+
export const ContractVariables = ({
|
|
6
|
+
refreshDisplayVariables,
|
|
7
|
+
deployedContractData,
|
|
8
|
+
}: {
|
|
9
|
+
refreshDisplayVariables: boolean;
|
|
10
|
+
deployedContractData: Contract<ContractName>;
|
|
11
|
+
}) => {
|
|
12
|
+
if (!deployedContractData) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const functionsToDisplay = (
|
|
17
|
+
(deployedContractData.abi as Abi).filter(part => part.type === "function") as AbiFunction[]
|
|
18
|
+
)
|
|
19
|
+
.filter(fn => {
|
|
20
|
+
const isQueryableWithNoParams =
|
|
21
|
+
(fn.stateMutability === "view" || fn.stateMutability === "pure") && fn.inputs.length === 0;
|
|
22
|
+
return isQueryableWithNoParams;
|
|
23
|
+
})
|
|
24
|
+
.map(fn => {
|
|
25
|
+
return {
|
|
26
|
+
fn,
|
|
27
|
+
inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name],
|
|
28
|
+
};
|
|
29
|
+
})
|
|
30
|
+
.sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1));
|
|
31
|
+
|
|
32
|
+
if (!functionsToDisplay.length) {
|
|
33
|
+
return <>No contract variables</>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
{functionsToDisplay.map(({ fn, inheritedFrom }) => (
|
|
39
|
+
<DisplayVariable
|
|
40
|
+
abi={deployedContractData.abi as Abi}
|
|
41
|
+
abiFunction={fn}
|
|
42
|
+
contractAddress={deployedContractData.address}
|
|
43
|
+
key={fn.name}
|
|
44
|
+
refreshDisplayVariables={refreshDisplayVariables}
|
|
45
|
+
inheritedFrom={inheritedFrom}
|
|
46
|
+
/>
|
|
47
|
+
))}
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
};
|
package/templates/base/packages/nextjs/app/debug/_components/contract/ContractWriteMethods.tsx
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Abi, AbiFunction } from "abitype";
|
|
2
|
+
import { WriteOnlyFunctionForm } from "~~/app/debug/_components/contract";
|
|
3
|
+
import { Contract, ContractName, GenericContract, InheritedFunctions } from "~~/utils/scaffold-eth/contract";
|
|
4
|
+
|
|
5
|
+
export const ContractWriteMethods = ({
|
|
6
|
+
onChange,
|
|
7
|
+
deployedContractData,
|
|
8
|
+
}: {
|
|
9
|
+
onChange: () => void;
|
|
10
|
+
deployedContractData: Contract<ContractName>;
|
|
11
|
+
}) => {
|
|
12
|
+
if (!deployedContractData) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const functionsToDisplay = (
|
|
17
|
+
(deployedContractData.abi as Abi).filter(part => part.type === "function") as AbiFunction[]
|
|
18
|
+
)
|
|
19
|
+
.filter(fn => {
|
|
20
|
+
const isWriteableFunction = fn.stateMutability !== "view" && fn.stateMutability !== "pure";
|
|
21
|
+
return isWriteableFunction;
|
|
22
|
+
})
|
|
23
|
+
.map(fn => {
|
|
24
|
+
return {
|
|
25
|
+
fn,
|
|
26
|
+
inheritedFrom: ((deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name],
|
|
27
|
+
};
|
|
28
|
+
})
|
|
29
|
+
.sort((a, b) => (b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1));
|
|
30
|
+
|
|
31
|
+
if (!functionsToDisplay.length) {
|
|
32
|
+
return <>No write methods</>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
{functionsToDisplay.map(({ fn, inheritedFrom }, idx) => (
|
|
38
|
+
<WriteOnlyFunctionForm
|
|
39
|
+
abi={deployedContractData.abi as Abi}
|
|
40
|
+
key={`${fn.name}-${idx}}`}
|
|
41
|
+
abiFunction={fn}
|
|
42
|
+
onChange={onChange}
|
|
43
|
+
contractAddress={deployedContractData.address}
|
|
44
|
+
inheritedFrom={inheritedFrom}
|
|
45
|
+
/>
|
|
46
|
+
))}
|
|
47
|
+
</>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect } from "react";
|
|
4
|
+
import { InheritanceTooltip } from "./InheritanceTooltip";
|
|
5
|
+
import { displayTxResult } from "./utilsDisplay";
|
|
6
|
+
import { Abi, AbiFunction } from "abitype";
|
|
7
|
+
import { Address } from "viem";
|
|
8
|
+
import { useReadContract } from "wagmi";
|
|
9
|
+
import { ArrowPathIcon } from "@heroicons/react/24/outline";
|
|
10
|
+
import { useAnimationConfig } from "~~/hooks/scaffold-eth";
|
|
11
|
+
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
|
|
12
|
+
import { getParsedError, notification } from "~~/utils/scaffold-eth";
|
|
13
|
+
|
|
14
|
+
type DisplayVariableProps = {
|
|
15
|
+
contractAddress: Address;
|
|
16
|
+
abiFunction: AbiFunction;
|
|
17
|
+
refreshDisplayVariables: boolean;
|
|
18
|
+
inheritedFrom?: string;
|
|
19
|
+
abi: Abi;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const DisplayVariable = ({
|
|
23
|
+
contractAddress,
|
|
24
|
+
abiFunction,
|
|
25
|
+
refreshDisplayVariables,
|
|
26
|
+
abi,
|
|
27
|
+
inheritedFrom,
|
|
28
|
+
}: DisplayVariableProps) => {
|
|
29
|
+
const { targetNetwork } = useTargetNetwork();
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
data: result,
|
|
33
|
+
isFetching,
|
|
34
|
+
refetch,
|
|
35
|
+
error,
|
|
36
|
+
} = useReadContract({
|
|
37
|
+
address: contractAddress,
|
|
38
|
+
functionName: abiFunction.name,
|
|
39
|
+
abi: abi,
|
|
40
|
+
chainId: targetNetwork.id,
|
|
41
|
+
query: {
|
|
42
|
+
retry: false,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const { showAnimation } = useAnimationConfig(result);
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
refetch();
|
|
50
|
+
}, [refetch, refreshDisplayVariables]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (error) {
|
|
54
|
+
const parsedError = getParsedError(error);
|
|
55
|
+
notification.error(parsedError);
|
|
56
|
+
}
|
|
57
|
+
}, [error]);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div className="space-y-1 pb-2">
|
|
61
|
+
<div className="flex items-center">
|
|
62
|
+
<h3 className="font-medium text-lg mb-0 break-all">{abiFunction.name}</h3>
|
|
63
|
+
<button className="btn btn-ghost btn-xs" onClick={async () => await refetch()}>
|
|
64
|
+
{isFetching ? (
|
|
65
|
+
<span className="loading loading-spinner loading-xs"></span>
|
|
66
|
+
) : (
|
|
67
|
+
<ArrowPathIcon className="h-3 w-3 cursor-pointer" aria-hidden="true" />
|
|
68
|
+
)}
|
|
69
|
+
</button>
|
|
70
|
+
<InheritanceTooltip inheritedFrom={inheritedFrom} />
|
|
71
|
+
</div>
|
|
72
|
+
<div className="font-medium flex flex-col items-start">
|
|
73
|
+
<div>
|
|
74
|
+
<div
|
|
75
|
+
className={`break-all block transition bg-transparent ${
|
|
76
|
+
showAnimation ? "bg-warning rounded-sm animate-pulse-fast" : ""
|
|
77
|
+
}`}
|
|
78
|
+
>
|
|
79
|
+
{displayTxResult(result)}
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { InformationCircleIcon } from "@heroicons/react/20/solid";
|
|
2
|
+
|
|
3
|
+
export const InheritanceTooltip = ({ inheritedFrom }: { inheritedFrom?: string }) => (
|
|
4
|
+
<>
|
|
5
|
+
{inheritedFrom && (
|
|
6
|
+
<span
|
|
7
|
+
className="tooltip tooltip-top tooltip-accent px-2 md:break-normal"
|
|
8
|
+
data-tip={`Inherited from: ${inheritedFrom}`}
|
|
9
|
+
>
|
|
10
|
+
<InformationCircleIcon className="h-4 w-4" aria-hidden="true" />
|
|
11
|
+
</span>
|
|
12
|
+
)}
|
|
13
|
+
</>
|
|
14
|
+
);
|
package/templates/base/packages/nextjs/app/debug/_components/contract/ReadOnlyFunctionForm.tsx
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { InheritanceTooltip } from "./InheritanceTooltip";
|
|
5
|
+
import { Abi, AbiFunction } from "abitype";
|
|
6
|
+
import { Address } from "viem";
|
|
7
|
+
import { useReadContract } from "wagmi";
|
|
8
|
+
import {
|
|
9
|
+
ContractInput,
|
|
10
|
+
displayTxResult,
|
|
11
|
+
getFunctionInputKey,
|
|
12
|
+
getInitialFormState,
|
|
13
|
+
getParsedContractFunctionArgs,
|
|
14
|
+
transformAbiFunction,
|
|
15
|
+
} from "~~/app/debug/_components/contract";
|
|
16
|
+
import { useTargetNetwork } from "~~/hooks/scaffold-eth/useTargetNetwork";
|
|
17
|
+
import { getParsedError, notification } from "~~/utils/scaffold-eth";
|
|
18
|
+
|
|
19
|
+
type ReadOnlyFunctionFormProps = {
|
|
20
|
+
contractAddress: Address;
|
|
21
|
+
abiFunction: AbiFunction;
|
|
22
|
+
inheritedFrom?: string;
|
|
23
|
+
abi: Abi;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const ReadOnlyFunctionForm = ({
|
|
27
|
+
contractAddress,
|
|
28
|
+
abiFunction,
|
|
29
|
+
inheritedFrom,
|
|
30
|
+
abi,
|
|
31
|
+
}: ReadOnlyFunctionFormProps) => {
|
|
32
|
+
const [form, setForm] = useState<Record<string, any>>(() => getInitialFormState(abiFunction));
|
|
33
|
+
const [result, setResult] = useState<unknown>();
|
|
34
|
+
const { targetNetwork } = useTargetNetwork();
|
|
35
|
+
|
|
36
|
+
const { isFetching, refetch, error } = useReadContract({
|
|
37
|
+
address: contractAddress,
|
|
38
|
+
functionName: abiFunction.name,
|
|
39
|
+
abi: abi,
|
|
40
|
+
args: getParsedContractFunctionArgs(form),
|
|
41
|
+
chainId: targetNetwork.id,
|
|
42
|
+
query: {
|
|
43
|
+
enabled: false,
|
|
44
|
+
retry: false,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (error) {
|
|
50
|
+
const parsedError = getParsedError(error);
|
|
51
|
+
notification.error(parsedError);
|
|
52
|
+
}
|
|
53
|
+
}, [error]);
|
|
54
|
+
|
|
55
|
+
const transformedFunction = transformAbiFunction(abiFunction);
|
|
56
|
+
const inputElements = transformedFunction.inputs.map((input, inputIndex) => {
|
|
57
|
+
const key = getFunctionInputKey(abiFunction.name, input, inputIndex);
|
|
58
|
+
return (
|
|
59
|
+
<ContractInput
|
|
60
|
+
key={key}
|
|
61
|
+
setForm={updatedFormValue => {
|
|
62
|
+
setResult(undefined);
|
|
63
|
+
setForm(updatedFormValue);
|
|
64
|
+
}}
|
|
65
|
+
form={form}
|
|
66
|
+
stateObjectKey={key}
|
|
67
|
+
paramType={input}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<div className="flex flex-col gap-3 py-5 first:pt-0 last:pb-1">
|
|
74
|
+
<p className="font-medium my-0 break-words">
|
|
75
|
+
{abiFunction.name}
|
|
76
|
+
<InheritanceTooltip inheritedFrom={inheritedFrom} />
|
|
77
|
+
</p>
|
|
78
|
+
{inputElements}
|
|
79
|
+
<div className="flex flex-col md:flex-row justify-between gap-2 flex-wrap">
|
|
80
|
+
<div className="grow w-full md:max-w-[80%]">
|
|
81
|
+
{result !== null && result !== undefined && (
|
|
82
|
+
<div className="bg-secondary rounded-3xl text-sm px-4 py-1.5 break-words overflow-auto">
|
|
83
|
+
<p className="font-bold m-0 mb-1">Result:</p>
|
|
84
|
+
<pre className="whitespace-pre-wrap break-words">{displayTxResult(result, "sm")}</pre>
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
87
|
+
</div>
|
|
88
|
+
<button
|
|
89
|
+
className="btn btn-secondary btn-sm self-end md:self-start"
|
|
90
|
+
onClick={async () => {
|
|
91
|
+
const { data } = await refetch();
|
|
92
|
+
setResult(data);
|
|
93
|
+
}}
|
|
94
|
+
disabled={isFetching}
|
|
95
|
+
>
|
|
96
|
+
{isFetching && <span className="loading loading-spinner loading-xs"></span>}
|
|
97
|
+
Read 📡
|
|
98
|
+
</button>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
|
2
|
+
import { ContractInput } from "./ContractInput";
|
|
3
|
+
import { getFunctionInputKey, getInitialTupleFormState } from "./utilsContract";
|
|
4
|
+
import { replacer } from "~~/utils/scaffold-eth/common";
|
|
5
|
+
import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";
|
|
6
|
+
|
|
7
|
+
type TupleProps = {
|
|
8
|
+
abiTupleParameter: AbiParameterTuple;
|
|
9
|
+
setParentForm: Dispatch<SetStateAction<Record<string, any>>>;
|
|
10
|
+
parentStateObjectKey: string;
|
|
11
|
+
parentForm: Record<string, any> | undefined;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const Tuple = ({ abiTupleParameter, setParentForm, parentStateObjectKey }: TupleProps) => {
|
|
15
|
+
const [form, setForm] = useState<Record<string, any>>(() => getInitialTupleFormState(abiTupleParameter));
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const values = Object.values(form);
|
|
19
|
+
const argsStruct: Record<string, any> = {};
|
|
20
|
+
abiTupleParameter.components.forEach((component, componentIndex) => {
|
|
21
|
+
argsStruct[component.name || `input_${componentIndex}_`] = values[componentIndex];
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
setParentForm(parentForm => ({ ...parentForm, [parentStateObjectKey]: JSON.stringify(argsStruct, replacer) }));
|
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
|
+
}, [JSON.stringify(form, replacer)]);
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div>
|
|
30
|
+
<div tabIndex={0} className="collapse collapse-arrow bg-base-200 pl-4 py-1.5 border-2 border-secondary">
|
|
31
|
+
<input type="checkbox" className="min-h-fit! peer" />
|
|
32
|
+
<div className="collapse-title after:top-3.5! p-0 min-h-fit! peer-checked:mb-2 text-primary-content/50">
|
|
33
|
+
<p className="m-0 p-0 text-[1rem]">{abiTupleParameter.internalType}</p>
|
|
34
|
+
</div>
|
|
35
|
+
<div className="ml-3 flex-col space-y-4 border-secondary/80 border-l-2 pl-4 collapse-content">
|
|
36
|
+
{abiTupleParameter?.components?.map((param, index) => {
|
|
37
|
+
const key = getFunctionInputKey(abiTupleParameter.name || "tuple", param, index);
|
|
38
|
+
return <ContractInput setForm={setForm} form={form} key={key} stateObjectKey={key} paramType={param} />;
|
|
39
|
+
})}
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
|
2
|
+
import { ContractInput } from "./ContractInput";
|
|
3
|
+
import { getFunctionInputKey, getInitialTupleArrayFormState } from "./utilsContract";
|
|
4
|
+
import { replacer } from "~~/utils/scaffold-eth/common";
|
|
5
|
+
import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";
|
|
6
|
+
|
|
7
|
+
type TupleArrayProps = {
|
|
8
|
+
abiTupleParameter: AbiParameterTuple & { isVirtual?: true };
|
|
9
|
+
setParentForm: Dispatch<SetStateAction<Record<string, any>>>;
|
|
10
|
+
parentStateObjectKey: string;
|
|
11
|
+
parentForm: Record<string, any> | undefined;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const TupleArray = ({ abiTupleParameter, setParentForm, parentStateObjectKey }: TupleArrayProps) => {
|
|
15
|
+
const [form, setForm] = useState<Record<string, any>>(() => getInitialTupleArrayFormState(abiTupleParameter));
|
|
16
|
+
const [additionalInputs, setAdditionalInputs] = useState<Array<typeof abiTupleParameter.components>>([
|
|
17
|
+
abiTupleParameter.components,
|
|
18
|
+
]);
|
|
19
|
+
|
|
20
|
+
const depth = (abiTupleParameter.type.match(/\[\]/g) || []).length;
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
// Extract and group fields based on index prefix
|
|
24
|
+
const groupedFields = Object.keys(form).reduce(
|
|
25
|
+
(acc, key) => {
|
|
26
|
+
const [indexPrefix, ...restArray] = key.split("_");
|
|
27
|
+
const componentName = restArray.join("_");
|
|
28
|
+
if (!acc[indexPrefix]) {
|
|
29
|
+
acc[indexPrefix] = {};
|
|
30
|
+
}
|
|
31
|
+
acc[indexPrefix][componentName] = form[key];
|
|
32
|
+
return acc;
|
|
33
|
+
},
|
|
34
|
+
{} as Record<string, Record<string, any>>,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
let argsArray: Array<Record<string, any>> = [];
|
|
38
|
+
|
|
39
|
+
Object.keys(groupedFields).forEach(key => {
|
|
40
|
+
const currentKeyValues = Object.values(groupedFields[key]);
|
|
41
|
+
|
|
42
|
+
const argsStruct: Record<string, any> = {};
|
|
43
|
+
abiTupleParameter.components.forEach((component, componentIndex) => {
|
|
44
|
+
argsStruct[component.name || `input_${componentIndex}_`] = currentKeyValues[componentIndex];
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
argsArray.push(argsStruct);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
if (depth > 1) {
|
|
51
|
+
argsArray = argsArray.map(args => {
|
|
52
|
+
return args[abiTupleParameter.components[0].name || "tuple"];
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
setParentForm(parentForm => {
|
|
57
|
+
return { ...parentForm, [parentStateObjectKey]: JSON.stringify(argsArray, replacer) };
|
|
58
|
+
});
|
|
59
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
|
+
}, [JSON.stringify(form, replacer)]);
|
|
61
|
+
|
|
62
|
+
const addInput = () => {
|
|
63
|
+
setAdditionalInputs(previousValue => {
|
|
64
|
+
const newAdditionalInputs = [...previousValue, abiTupleParameter.components];
|
|
65
|
+
|
|
66
|
+
// Add the new inputs to the form
|
|
67
|
+
setForm(form => {
|
|
68
|
+
const newForm = { ...form };
|
|
69
|
+
abiTupleParameter.components.forEach((component, componentIndex) => {
|
|
70
|
+
const key = getFunctionInputKey(
|
|
71
|
+
`${newAdditionalInputs.length - 1}_${abiTupleParameter.name || "tuple"}`,
|
|
72
|
+
component,
|
|
73
|
+
componentIndex,
|
|
74
|
+
);
|
|
75
|
+
newForm[key] = "";
|
|
76
|
+
});
|
|
77
|
+
return newForm;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return newAdditionalInputs;
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const removeInput = () => {
|
|
85
|
+
// Remove the last inputs from the form
|
|
86
|
+
setForm(form => {
|
|
87
|
+
const newForm = { ...form };
|
|
88
|
+
abiTupleParameter.components.forEach((component, componentIndex) => {
|
|
89
|
+
const key = getFunctionInputKey(
|
|
90
|
+
`${additionalInputs.length - 1}_${abiTupleParameter.name || "tuple"}`,
|
|
91
|
+
component,
|
|
92
|
+
componentIndex,
|
|
93
|
+
);
|
|
94
|
+
delete newForm[key];
|
|
95
|
+
});
|
|
96
|
+
return newForm;
|
|
97
|
+
});
|
|
98
|
+
setAdditionalInputs(inputs => inputs.slice(0, -1));
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div>
|
|
103
|
+
<div className="collapse collapse-arrow bg-base-200 pl-4 py-1.5 border-2 border-secondary">
|
|
104
|
+
<input type="checkbox" className="min-h-fit! peer" />
|
|
105
|
+
<div className="collapse-title after:top-3.5! p-0 min-h-fit! peer-checked:mb-1 text-primary-content/50">
|
|
106
|
+
<p className="m-0 text-[1rem]">{abiTupleParameter.internalType}</p>
|
|
107
|
+
</div>
|
|
108
|
+
<div className="ml-3 flex-col space-y-2 border-secondary/70 border-l-2 pl-4 collapse-content">
|
|
109
|
+
{additionalInputs.map((additionalInput, additionalIndex) => (
|
|
110
|
+
<div key={additionalIndex} className="space-y-1">
|
|
111
|
+
<span className="badge bg-base-300 badge-sm">
|
|
112
|
+
{depth > 1 ? `${additionalIndex}` : `tuple[${additionalIndex}]`}
|
|
113
|
+
</span>
|
|
114
|
+
<div className="space-y-4">
|
|
115
|
+
{additionalInput.map((param, index) => {
|
|
116
|
+
const key = getFunctionInputKey(
|
|
117
|
+
`${additionalIndex}_${abiTupleParameter.name || "tuple"}`,
|
|
118
|
+
param,
|
|
119
|
+
index,
|
|
120
|
+
);
|
|
121
|
+
return (
|
|
122
|
+
<ContractInput setForm={setForm} form={form} key={key} stateObjectKey={key} paramType={param} />
|
|
123
|
+
);
|
|
124
|
+
})}
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
))}
|
|
128
|
+
<div className="flex space-x-2">
|
|
129
|
+
<button className="btn btn-sm btn-secondary" onClick={addInput}>
|
|
130
|
+
+
|
|
131
|
+
</button>
|
|
132
|
+
{additionalInputs.length > 0 && (
|
|
133
|
+
<button className="btn btn-sm btn-secondary" onClick={removeInput}>
|
|
134
|
+
-
|
|
135
|
+
</button>
|
|
136
|
+
)}
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
};
|