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

docs: add more comments around the create-fuels template app #2772

Merged
merged 12 commits into from
Jul 19, 2024
Merged
5 changes: 5 additions & 0 deletions .changeset/slow-moles-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-fuels": patch
---

docs: add more comments around the `create-fuels` template app
5 changes: 3 additions & 2 deletions apps/create-fuels-counter-guide/fuels.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ dotenv.config({
path: ['.env.local', '.env'],
});

// If your node is running on a port other than 4000, you can set it here
const fuelCorePort = +(process.env.NEXT_PUBLIC_FUEL_NODE_PORT as string) || 4000;

export default createConfig({
workspace: './sway-programs',
output: './src/sway-api',
workspace: './sway-programs', // Path to your Sway workspace
output: './src/sway-api', // Where your generated types will be saved
fuelCorePort,
providerUrl: NODE_URL,
});
Expand Down
3 changes: 2 additions & 1 deletion apps/create-fuels-counter-guide/src/app/faucet/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useEffect, useState } from "react";
import toast from "react-hot-toast";

export default function Faucet() {
const { faucetWallet } = useFaucet();
const { faucetWallet } = useFaucet(); // Get the faucet wallet instance from the useFaucet hook
const { wallet, refreshWalletBalance } = useActiveWallet();

const [receiverAddress, setReceiverAddress] = useState<string>("");
Expand All @@ -34,6 +34,7 @@ export default function Faucet() {
return toast.error("Amount cannot be empty");
}

// Transfer the specified amount of ETH to the receiver address
const tx = await faucetWallet.transfer(
receiverAddress,
bn.parseUnits(amountToSend.toString()),
Expand Down
5 changes: 4 additions & 1 deletion apps/create-fuels-counter-guide/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { NODE_URL } from "@/lib";
import { ActiveWalletProvider } from "@/hooks/useActiveWallet";

// react-query is a peer dependency of @fuels/react, so we set it up here. See https://docs.fuel.network/docs/wallet/dev/getting-started/#installation-1
arboleya marked this conversation as resolved.
Show resolved Hide resolved
const queryClient = new QueryClient();

interface RootLayoutProps {
Expand All @@ -25,12 +26,13 @@ interface RootLayoutProps {

export default function RootLayout({ children }: RootLayoutProps) {
const [isMounted, setIsMounted] = useState(false);
const providerToUse = useMemo(() => Provider.create(NODE_URL), [NODE_URL]);
const providerToUse = useMemo(() => Provider.create(NODE_URL), [NODE_URL]); // Create a Provider instance. We memoize it to avoid creating a new instance on every render.

useEffect(() => {
setIsMounted(true);
}, []);

// Only render the component if the page has been mounted, and `window` is defined.
if (!isMounted) return null;

return (
Expand All @@ -40,6 +42,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
<QueryClientProvider client={queryClient}>
<FuelProvider
fuelConfig={{
// The list of wallet connectors. You can add or remove connectors from here based on your needs.
connectors: [
new FuelWalletConnector(),
new BurnerWalletConnector({
Expand Down
6 changes: 6 additions & 0 deletions apps/create-fuels-counter-guide/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,11 @@ export default function Home() {
*/
useAsync(async () => {
if (wallet) {
// Create a new instance of the contrac
Dhaiwat10 marked this conversation as resolved.
Show resolved Hide resolved
const testContract = TestContractAbi__factory.connect(contractId, wallet);
setContract(testContract);

// Read the current value of the counter
const { value } = await testContract.functions.get_count().get();
setCounter(value.toNumber());
}
Expand All @@ -50,7 +53,10 @@ export default function Home() {
);
}

// Call the increment_counter function on the contract
const { waitForResult } = await contract.functions.increment_counter(bn(1)).call();

// Wait for the transaction to be mined, and then read the value returned by the contract call
const { value } = await waitForResult();
setCounter(value.toNumber());

Expand Down
7 changes: 7 additions & 0 deletions apps/create-fuels-counter-guide/src/app/predicate/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default function PredicateExample() {
useAsync(async () => {
if (wallet) {
baseAssetId = wallet.provider.getBaseAssetId();
// Initialize a new predicate instance
const predicate = TestPredicateAbi__factory.createInstance(
wallet.provider,
);
Expand Down Expand Up @@ -63,6 +64,7 @@ export default function PredicateExample() {
return toast.error("Wallet not loaded");
}

// Initialize a new predicate instance with the entered pin
const reInitializePredicate = TestPredicateAbi__factory.createInstance(
wallet.provider,
[bn(pin)],
Expand All @@ -72,6 +74,11 @@ export default function PredicateExample() {
return toast.error("Failed to initialize predicate");
}

/*
Try to 'unlock' the predicate and transfer the funds back to the wallet.
If the pin is correct, this transfer transaction will succeed.
If the pin is incorrect, this transaction will fail.
*/
const tx = await reInitializePredicate.transfer(
wallet.address,
amount,
Expand Down
5 changes: 4 additions & 1 deletion apps/create-fuels-counter-guide/src/app/script/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function ScriptExample() {

useAsync(async () => {
if (wallet) {
// Initialize script instance
const script = TestScriptAbi__factory.createInstance(wallet);
setScript(script);
}
Expand All @@ -31,7 +32,9 @@ export default function ScriptExample() {
return toast.error("Script not loaded");
}

const { value } = await script.functions.main(bn(input)).call();
// Call the script with the input value
const { waitForResult } = await script.functions.main(bn(input)).call();
const { value } = await waitForResult();
Dhaiwat10 marked this conversation as resolved.
Show resolved Hide resolved

setResult(value.toString());
} catch (error) {
Expand Down
2 changes: 2 additions & 0 deletions apps/create-fuels-counter-guide/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const Layout = ({ children }: { children: React.ReactNode }) => {
return console.error("Unable to topup wallet because wallet is not set.");
}

// If the current environment is local, transfer 5 ETH to the wallet from the local faucet wallet
if (CURRENT_ENVIRONMENT === "local") {
if (!faucetWallet) {
return toast.error("Faucet wallet not found.");
Expand All @@ -45,6 +46,7 @@ export const Layout = ({ children }: { children: React.ReactNode }) => {
return await refreshWalletBalance?.();
}

// If the current environment is testnet, open the testnet faucet link in a new tab
if (CURRENT_ENVIRONMENT === "testnet") {
return window.open(
`${TESTNET_FAUCET_LINK}?address=${wallet.address.toAddress()}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import { AppWallet } from "@/lib";
/**
* burner -> a burner wallet embedded inside of the template app and stored in local storage
* browser -> a wallet connected via a browser extension like the Fuel Wallet
*
* Whenever a browser wallet is connected, this hook will return an instance of the browser wallet.
* Otherwise, it will return an instance of a local burner wallet.
*/
type WalletTypes = "burner" | "browser";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ interface BrowserWallet extends AppWallet {
network: any;
}

/**
* This hook returns an instance of the browser wallet connected via any of the supported connectors.
**/
export const useBrowserWallet: () => BrowserWallet = () => {
const { wallet } = useWallet();
const [browserWalletBalance, setBrowserWalletBalance] = useState<BN>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import useAsync from "react-use/lib/useAsync";

const BURNER_WALLET_LOCAL_STORAGE_KEY = "create-fuels-burner-wallet-pk";

/**
* This hook returns an instance of a burner wallet that lives in local storage.
*/
export const useBurnerWallet: () => AppWallet = () => {
const [burnerWallet, setBurnerWallet] = useState<WalletUnlocked>();
const [burnerWalletBalance, setBurnerWalletBalance] = useState<BN>();
Expand Down
4 changes: 4 additions & 0 deletions apps/create-fuels-counter-guide/src/hooks/useFaucet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { Provider, Wallet, WalletUnlocked } from "fuels";
import { useState } from "react";
import useAsync from "react-use/lib/useAsync";

/**
* This hook returns an instance of a faucet wallet.
* The value of `FAUCET_PRIVATE_KEY` depends on your chain config.
*/
export const useFaucet = () => {
const [faucetWallet, setFaucetWallet] = useState<WalletUnlocked>();

Expand Down
3 changes: 3 additions & 0 deletions apps/create-fuels-counter-guide/src/lib.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { Account, BN, TESTNET_NETWORK_URL } from 'fuels';

// #region deploying-dapp-to-testnet-lib-current-environment
// The two environments for the dapp are local and testnet.
export const Environments = {
LOCAL: 'local',
TESTNET: 'testnet',
} as const;
type Environment = (typeof Environments)[keyof typeof Environments];

// The current environment is determined by the `NEXT_PUBLIC_DAPP_ENVIRONMENT` environment variable. If it's not set, the default is `local`.
export const CURRENT_ENVIRONMENT: Environment =
(process.env.NEXT_PUBLIC_DAPP_ENVIRONMENT as Environment) || Environments.LOCAL;
// #endregion deploying-dapp-to-testnet-lib-current-environment

// The node URL is determined by the current environment too.
export const NODE_URL =
CURRENT_ENVIRONMENT === Environments.LOCAL
? `http://127.0.0.1:${process.env.NEXT_PUBLIC_FUEL_NODE_PORT || 4000}/v1/graphql`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
contract;

// #region create-fuels-counter-guide-abi
// The abi defines the blueprint for the contract.
abi Counter {
#[storage(read)]
fn get_count() -> u64;
Expand All @@ -13,24 +14,28 @@ abi Counter {
}
// #endregion create-fuels-counter-guide-abi

// The storage variables for the contract. In this case, there is only one variable called `counter` which is initialized to 0.
storage {
counter: u64 = 0,
}

// #region create-fuels-counter-guide-impl
impl Counter for Contract {
// The `get_count` function returns the current value of the counter.
#[storage(read)]
fn get_count() -> u64 {
storage.counter.read()
}

// The `increment_counter` function increments the counter by the given amount.
#[storage(write, read)]
fn increment_counter(amount: u64) -> u64 {
let current = storage.counter.read();
storage.counter.write(current + amount);
storage.counter.read()
}

// The `decrement_counter` function decrements the counter by the given amount.
#[storage(read, write)]
fn decrement_counter(amount: u64) -> u64 {
let current = storage.counter.read();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ configurable {
PIN: u64 = 1337,
}

// This predicate checks if the given pin is correct. If it is, the predicate is 'unlocked' and the transaction is allowed to proceed. Otherwise, it is reverted.
fn main(pin: u64) -> bool {
return PIN == pin;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
script;

// This script simply returns the input value.
fn main(input: u64) -> u64 {
return input;
}
5 changes: 3 additions & 2 deletions templates/nextjs/fuels.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ dotenv.config({
path: ['.env.local', '.env'],
});

// If your node is running on a port other than 4000, you can set it here
const fuelCorePort = +(process.env.NEXT_PUBLIC_FUEL_NODE_PORT as string) || 4000;

export default createConfig({
workspace: './sway-programs',
output: './src/sway-api',
workspace: './sway-programs', // Path to your Sway workspace
output: './src/sway-api', // Where your generated types will be saved
fuelCorePort,
providerUrl: NODE_URL,
forcPath: 'fuels-forc',
Expand Down
3 changes: 2 additions & 1 deletion templates/nextjs/src/app/faucet/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useEffect, useState } from "react";
import toast from "react-hot-toast";

export default function Faucet() {
const { faucetWallet } = useFaucet();
const { faucetWallet } = useFaucet(); // Get the faucet wallet instance from the useFaucet hook
const { wallet, refreshWalletBalance } = useActiveWallet();

const [receiverAddress, setReceiverAddress] = useState<string>("");
Expand All @@ -34,6 +34,7 @@ export default function Faucet() {
return toast.error("Amount cannot be empty");
}

// Transfer the specified amount of ETH to the receiver address
const tx = await faucetWallet.transfer(
receiverAddress,
bn.parseUnits(amountToSend.toString()),
Expand Down
5 changes: 4 additions & 1 deletion templates/nextjs/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { NODE_URL } from "@/lib";
import { ActiveWalletProvider } from "@/hooks/useActiveWallet";

// react-query is a peer dependency of @fuels/react, so we set it up here. See https://docs.fuel.network/docs/wallet/dev/getting-started/#installation-1
const queryClient = new QueryClient();

interface RootLayoutProps {
Expand All @@ -25,12 +26,13 @@ interface RootLayoutProps {

export default function RootLayout({ children }: RootLayoutProps) {
const [isMounted, setIsMounted] = useState(false);
const providerToUse = useMemo(() => Provider.create(NODE_URL), [NODE_URL]);
const providerToUse = useMemo(() => Provider.create(NODE_URL), [NODE_URL]); // Create a Provider instance. We memoize it to avoid creating a new instance on every render.

useEffect(() => {
setIsMounted(true);
}, []);

// Only render the component if the page has been mounted, and `window` is defined.
if (!isMounted) return null;

return (
Expand All @@ -40,6 +42,7 @@ export default function RootLayout({ children }: RootLayoutProps) {
<QueryClientProvider client={queryClient}>
<FuelProvider
fuelConfig={{
// The list of wallet connectors. You can add or remove connectors from here based on your needs.
connectors: [
new FuelWalletConnector(),
new BurnerWalletConnector({
Expand Down
5 changes: 5 additions & 0 deletions templates/nextjs/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ export default function Home() {
*/
useAsync(async () => {
if (wallet) {
// Create a new instance of the contract
const testContract = TestContractAbi__factory.connect(contractId, wallet);
setContract(testContract);

// Read the current value of the counter
const { value } = await testContract.functions.get_count().get();
setCounter(value.toNumber());
}
Expand All @@ -48,10 +51,12 @@ export default function Home() {
);
}

// Call the increment_counter function on the contract
const { waitForResult } = await contract.functions
.increment_counter(bn(1))
.call();

// Wait for the transaction to be mined, and then read the value returned by the contract call
const { value } = await waitForResult();

setCounter(value.toNumber());
Expand Down
7 changes: 7 additions & 0 deletions templates/nextjs/src/app/predicate/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export default function PredicateExample() {
useAsync(async () => {
if (wallet) {
baseAssetId = wallet.provider.getBaseAssetId();
// Initialize a new predicate instance
const predicate = TestPredicateAbi__factory.createInstance(
wallet.provider,
);
Expand Down Expand Up @@ -63,6 +64,7 @@ export default function PredicateExample() {
return toast.error("Wallet not loaded");
}

// Initialize a new predicate instance with the entered pin
const reInitializePredicate = TestPredicateAbi__factory.createInstance(
wallet.provider,
[bn(pin)],
Expand All @@ -72,6 +74,11 @@ export default function PredicateExample() {
return toast.error("Failed to initialize predicate");
}

/*
Try to 'unlock' the predicate and transfer the funds back to the wallet.
If the pin is correct, this transfer transaction will succeed.
If the pin is incorrect, this transaction will fail.
*/
const tx = await reInitializePredicate.transfer(
wallet.address,
amount,
Expand Down
2 changes: 2 additions & 0 deletions templates/nextjs/src/app/script/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default function ScriptExample() {

useAsync(async () => {
if (wallet) {
// Initialize script instance
const script = TestScriptAbi__factory.createInstance(wallet);
setScript(script);
}
Expand All @@ -31,6 +32,7 @@ export default function ScriptExample() {
return toast.error("Script not loaded");
}

// Call the script with the input value
const { waitForResult } = await script.functions.main(bn(input)).call();
const { value } = await waitForResult();

Expand Down
Loading
Loading