Skip to content

Commit

Permalink
Merge pull request #5 from arjanjohan/network-toggle
Browse files Browse the repository at this point in the history
Network toggle
  • Loading branch information
arjanjohan authored Jul 9, 2024
2 parents aaa7f79 + 6ef3857 commit 3b9040b
Show file tree
Hide file tree
Showing 72 changed files with 1,133 additions and 1,373 deletions.
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
⚙️ Built using NextJS, Tailwind and Typescript.

-**Contract Hot Reload**: Your frontend auto-adapts to your smart contract as you edit it.
- 🪝 **[Custom hooks](https://docs.scaffoldeth.io/hooks/)**: Collection of React hooks to simplify interactions with smart contracts.
- 🪝 **[Custom hooks](https://docs.scaffoldeth.io/hooks/)**: Collection of React hooks to simplify interactions with Move modules .
- 🧱 [**Components**](https://docs.scaffoldeth.io/components/): Collection of common web3 components to quickly build your frontend.
- 🔐 **Integration with Wallet Providers**: Connect your Petra Wallet and interact with the Aptos or Movement M1 network.

Expand All @@ -36,7 +36,7 @@ cd scaffold-move
yarn install
```

2. ~~Run a local network in the first terminal:~~
2. ~~Run a local network in the first terminal:~~

<!-- ```
yarn chain
Expand All @@ -58,7 +58,7 @@ This command overwrites `packages/move/.aptos/config.yaml` with a new Aptos acco
yarn deploy
```

This command deploys a test smart contract to the local network. The contract is located in `packages/hardhat/contracts` and can be modified to suit your needs. The `yarn deploy` command uses `movement aptos move publish` to publish the contract to the network. After this is executes the script located in `scripts/loadContracts.js` to make the new contracts available in the nextjs frontend.
This command deploys the move modules to the selected network. The contract is located in `packages/move/sources` and can be modified to suit your needs. The `yarn deploy` command uses `movement aptos move publish` to publish the modules to the network. After this is executes the script located in `scripts/loadContracts.js` to make the new contracts available in the nextjs frontend.

5. On a third terminal, start your NextJS app:

Expand All @@ -78,13 +78,11 @@ Visit your app on: `http://localhost:3000`. You can interact with your smart con

For this hackathon I kept the scope small due to the time constraints. I build only the most essential and useful features, so that developers can start using Scaffold Move right away. However, there is much more that I want to add to this project after the hackathon. If you have any ideas or suggestions, please reach out and I will add it to this list.

- Wallet button component
- Fix QR code
- Add network switch
- Styling of connect button
- Store Aptos/Movement network data in scaffold-config

- Debug page
- Msg for no result on view methods
- Msg for no result on view methods + error msg
- Styling for resources tab
- Group contracts under address in list
- Fix colors for dark mode
- Ensure export default deployedContracts satisfies GenericContractsDeclaration
- Add block explorer page
Expand All @@ -94,6 +92,8 @@ For this hackathon I kept the scope small due to the time constraints. I build o
<!-- - [Presentation video]()
- [Presentation slides]() -->
- [Website](https://scaffold-move-chi.vercel.app/)
- [Dorahacks](https://dorahacks.io/buidl/13953)
- [Github](https://github.com/arjanjohan/scaffold-move)

## Team

Expand Down
4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,5 @@
},
"engines": {
"node": ">=18.17.0"
},
"dependencies": {
"aptos": "^1.21.0",
"js-yaml": "^4.1.0"
}
}
45 changes: 18 additions & 27 deletions packages/nextjs/app/bio/page.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
"use client";

import { useState } from "react";
import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
import { InputTransactionData, useWallet } from "@aptos-labs/wallet-adapter-react";
import type { NextPage } from "next";
import { InputBase } from "~~/components/scaffold-eth";
import deployedModules from "~~/contracts/deployedModules";
import useSubmitTransaction from "~~/hooks/scaffold-move/useSubmitTransaction";
import { useGetAccountModules } from "~~/hooks/scaffold-move/useGetAccountModules";
import { aptosClient } from "~~/utils/scaffold-move/aptosClient";

// TODO: move this somewhere global
const aptosConfig = new AptosConfig({
network: Network.CUSTOM,
fullnode: "https://aptos.devnet.m1.movementlabs.xyz",
indexer: "https://indexer.devnet.m1.movementlabs.xyz/",
faucet: "https://faucet2.movementlabs.xyz",
});
const aptos = new Aptos(aptosConfig);
const aptos = aptosClient("m1_devnet");

const ONCHAIN_BIO = deployedModules.devnet.onchain_bio.abi;

Expand All @@ -30,34 +22,25 @@ const OnchainBio: NextPage = () => {
const [currentName, setCurrentName] = useState(null);
const [currentBio, setCurrentBio] = useState(null);

const {data, isLoading, error} = useGetAccountModules(ONCHAIN_BIO.address);
console.log("useGetAccountModules", data, "isLoading", isLoading, "error", error);


const {submitTransaction, transactionResponse, transactionInProcess} =
useSubmitTransaction();
const { submitTransaction, transactionResponse, transactionInProcess } = useSubmitTransaction();

const fetchBio = async () => {
if (!account) {
console.log("No account");
return [];
}
try {

const resourceName = "Bio";
const bioResource = await aptos.getAccountResource({
accountAddress: account?.address,
resourceType: `${ONCHAIN_BIO.address}::${ONCHAIN_BIO.name}::${resourceName}`,
});
setAccountHasBio(true);
if (bioResource) {
console.log("Name:", bioResource.name, "Bio:", bioResource.bio);
setCurrentName(bioResource.name);
setCurrentBio(bioResource.bio);
} else {
setCurrentName(null);
setCurrentBio(null);
console.log("no bio");
}
} catch (e: any) {
setAccountHasBio(false);
Expand Down Expand Up @@ -115,6 +98,7 @@ const OnchainBio: NextPage = () => {
</div>
<button
className="btn btn-secondary mt-2"
disabled={!account}
onClick={async () => {
try {
await registerBio();
Expand All @@ -131,6 +115,7 @@ const OnchainBio: NextPage = () => {
<div className="flex flex-col items-center space-y-4 bg-base-100 shadow-lg shadow-secondary border-8 border-secondary rounded-xl p-6 mt-8 w-full max-w-lg">
<button
className="btn btn-secondary mt-2"
disabled={!account}
onClick={async () => {
try {
await fetchBio();
Expand All @@ -141,14 +126,20 @@ const OnchainBio: NextPage = () => {
>
Fetch Bio
</button>
</div>

{accountHasBio && !transactionInProcess && (
<div>
<div>{currentName}</div>
<div>{currentBio}</div>
</div>
)}
{accountHasBio && !transactionInProcess && (
<div className="space-y-4 w-full max-w-lg">
<div className="flex items-center">
<span className="text-xs font-medium mr-2 leading-none">Name:</span>
</div>
<div className="w-full flex flex-col space-y-2">{currentName}</div>
<div className="flex items-center">
<span className="text-xs font-medium mr-2 leading-none">Bio:</span>
</div>
<div className="w-full flex flex-col space-y-2">{currentBio}</div>
</div>
)}
</div>
</div>
</>
);
Expand Down
11 changes: 5 additions & 6 deletions packages/nextjs/app/debug/_components/DebugContracts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import { useEffect } from "react";
import { useLocalStorage } from "usehooks-ts";
import { BarsArrowUpIcon } from "@heroicons/react/20/solid";
import { ContractUI } from "~~/app/debug/_components/contract";
import { ContractName } from "~~/utils/scaffold-eth/contract";
import { ContractName } from "~~/utils/scaffold-move/contract";
import { getAllContracts } from "~~/utils/scaffold-move/contractsData";

const contractsData = getAllContracts();
const contractNames = Object.keys(contractsData) as ContractName[];

export function DebugContracts() {

const selectedContractStorageKey = "scaffoldEth2.selectedContract";

const [selectedContract, setSelectedContract] = useLocalStorage<ContractName>(
Expand Down Expand Up @@ -41,11 +40,11 @@ export function DebugContracts() {
? "bg-base-300 hover:bg-base-300 no-animation"
: "bg-base-100 hover:bg-secondary"
}`}
key={contractName}
key={contractName as string}
onClick={() => setSelectedContract(contractName)}
>
{contractName}
{contractsData[contractName].external && (
{contractName as string}
{contractsData[contractName as string].external && (
<span className="tooltip tooltip-top tooltip-accent" data-tip="External contract">
<BarsArrowUpIcon className="h-4 w-4 cursor-pointer" />
</span>
Expand All @@ -56,7 +55,7 @@ export function DebugContracts() {
)}
{contractNames.map(contractName => (
<ContractUI
key={contractName}
key={contractName as string}
contractName={contractName}
className={contractName === selectedContract ? "" : "hidden"}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
IntegerInput,
IntegerVariant,
} from "~~/components/scaffold-eth";
import { AbiParameterTuple } from "~~/utils/scaffold-eth/contract";
import { AbiParameterTuple } from "~~/utils/scaffold-move/contract";

type ContractInputProps = {
setForm: Dispatch<SetStateAction<Record<string, any>>>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,24 @@
import { FunctionForm } from "~~/app/debug/_components/contract";
import { Contract, ContractName } from "~~/utils/scaffold-move/contract";
import { Types } from "aptos";

export const ContractReadMethods = ({
deployedContractData
}: {
deployedContractData: Contract<ContractName>
}) => {
export const ContractReadMethods = ({ deployedContractData }: { deployedContractData: Contract<ContractName> }) => {
if (!deployedContractData || deployedContractData.abi === undefined) {
return null;
}

const functionsToDisplay = deployedContractData.abi.exposed_functions.filter((fn) =>
fn.is_view,
);
const functionsToDisplay = deployedContractData.abi.exposed_functions.filter((fn: Types.MoveFunction) => fn.is_view);

if (!functionsToDisplay.length) {
return <>No view functions</>;
}

return (
<>

{functionsToDisplay.map((fn, index) => (
{functionsToDisplay.map((fn: Types.MoveFunction, index: number) => (
<div key={index}>
<FunctionForm
key={index}
module={deployedContractData.abi!}
fn={fn}
write={false}
/></div>
<FunctionForm key={index} module={deployedContractData.abi!} fn={fn} write={false} />
</div>
))}
</>
);
Expand Down
31 changes: 12 additions & 19 deletions packages/nextjs/app/debug/_components/contract/ContractUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@

// @refresh reset
import { ContractReadMethods } from "./ContractReadMethods";
import { ModuleResources } from "./ModuleResources";
import { ContractVariables } from "./ContractVariables";
import { ContractWriteMethods } from "./ContractWriteMethods";
import { Address, Balance} from "~~/components/scaffold-move";

import { ModuleResources } from "./ModuleResources";
import { Address, Balance } from "~~/components/scaffold-move";
import { useDeployedContractInfo } from "~~/hooks/scaffold-move";
import { ContractName } from "~~/utils/scaffold-eth/contract";
import { useTargetNetwork } from "~~/hooks/scaffold-move/useTargetNetwork";
import { ContractName } from "~~/utils/scaffold-move/contract";

type ContractUIProps = {
contractName: ContractName;
Expand All @@ -19,8 +18,7 @@ type ContractUIProps = {
* UI component to interface with deployed contracts.
**/
export const ContractUI = ({ contractName, className = "" }: ContractUIProps) => {
// const { targetNetwork } = useTargetNetwork();
const targetNetwork = "devnet"
const { targetNetwork } = useTargetNetwork();
const { data: deployedContractData, isLoading: deployedContractLoading } = useDeployedContractInfo(contractName);

if (deployedContractLoading) {
Expand All @@ -33,7 +31,7 @@ export const ContractUI = ({ contractName, className = "" }: ContractUIProps) =>
if (!deployedContractData || !deployedContractData.abi) {
return (
<p className="text-3xl mt-14">
{`No contract found by the name of "${contractName}" on chain "${targetNetwork}"!`}
{`No contract found by the name of "${String(contractName)}" on chain "${targetNetwork}"!`}
</p>
);
}
Expand All @@ -45,22 +43,20 @@ export const ContractUI = ({ contractName, className = "" }: ContractUIProps) =>
<div className="bg-base-100 border-base-300 border shadow-md shadow-secondary rounded-3xl px-6 lg:px-8 mb-6 space-y-1 py-4">
<div className="flex">
<div className="flex flex-col gap-1">
<span className="font-bold">{contractName}</span>
<span className="font-bold">{String(contractName)}</span>
<Address address={deployedContractData.abi.address} />
<div className="flex gap-1 items-center">
<span className="font-bold text-sm">Balance:</span>
<Balance address={deployedContractData.abi.address}/>
<Balance address={deployedContractData.abi.address} />
</div>
</div>
</div>
{targetNetwork && (
<p className="my-0 text-sm">
<span className="font-bold">Network</span>:{" "}
<span >{targetNetwork}</span>
<span className="font-bold">Network</span>: <span>{String(targetNetwork.name)}</span>
</p>
)}
</div>

</div>
<div className="col-span-1 lg:col-span-2 flex flex-col gap-6">
<div className="z-10">
Expand All @@ -83,9 +79,7 @@ export const ContractUI = ({ contractName, className = "" }: ContractUIProps) =>
</div>
</div>
<div className="p-5 divide-y divide-base-300">
<ContractWriteMethods
deployedContractData={deployedContractData}
/>
<ContractWriteMethods deployedContractData={deployedContractData} />
</div>
</div>
</div>
Expand All @@ -97,9 +91,8 @@ export const ContractUI = ({ contractName, className = "" }: ContractUIProps) =>
</div>
</div>
<div className="p-5 divide-y divide-base-300">
<ModuleResources
deployedContractData={deployedContractData}
/>
I disabled the Resources tab due to errors in the Vercel deployment, run the project locally to see it in action.
{/* <ModuleResources deployedContractData={deployedContractData} /> */}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
import { FunctionForm } from "~~/app/debug/_components/contract";
import { Contract, ContractName } from "~~/utils/scaffold-move/contract";
import { Types } from "aptos";

export const ContractWriteMethods = ({
deployedContractData,
}: {
deployedContractData: Contract<ContractName>;
}) => {
export const ContractWriteMethods = ({ deployedContractData }: { deployedContractData: Contract<ContractName> }) => {
if (!deployedContractData || deployedContractData.abi === undefined) {
return null;
}

const functionsToDisplay = deployedContractData.abi.exposed_functions.filter((fn) =>
fn.is_entry,
);
const functionsToDisplay = deployedContractData.abi.exposed_functions.filter((fn : Types.MoveFunction) => fn.is_entry);

if (!functionsToDisplay.length) {
return <>No write functions</>;
}

return (
<>
{functionsToDisplay.map((fn, index) => (
{functionsToDisplay.map((fn: Types.MoveFunction, index: number) => (
<div key={index}>
<FunctionForm
key={index}
module={deployedContractData.abi!}
fn={fn}
write={true}
/></div>
<FunctionForm key={index} module={deployedContractData.abi!} fn={fn} write={true} />
</div>
))}
</>
);
Expand Down
Loading

0 comments on commit 3b9040b

Please sign in to comment.