Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Network toggle #5

Merged
merged 6 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading