summary refs log tree commit diff stats
path: root/client/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/components')
-rw-r--r--client/src/components/ConnectWallet.tsx137
-rw-r--r--client/src/components/DisconnectWallet.tsx50
-rw-r--r--client/src/components/Records.tsx49
-rw-r--r--client/src/components/Transfers.tsx70
4 files changed, 306 insertions, 0 deletions
diff --git a/client/src/components/ConnectWallet.tsx b/client/src/components/ConnectWallet.tsx
new file mode 100644
index 0000000..3a293c0
--- /dev/null
+++ b/client/src/components/ConnectWallet.tsx
@@ -0,0 +1,137 @@
+import React, { Dispatch, SetStateAction, useState, useEffect } from "react";
+import { TezosToolkit } from "@taquito/taquito";
+import { BeaconWallet } from "@taquito/beacon-wallet";
+import {
+  NetworkType,
+  BeaconEvent,
+  defaultEventCallbacks
+} from "@airgap/beacon-sdk";
+import TransportU2F from "@ledgerhq/hw-transport-u2f";
+import { LedgerSigner } from "@taquito/ledger-signer";
+
+type ButtonProps = {
+  Tezos: TezosToolkit;
+  setContract: Dispatch<SetStateAction<any>>;
+  setWallet: Dispatch<SetStateAction<any>>;
+  setUserAddress: Dispatch<SetStateAction<string>>;
+  setUserBalance: Dispatch<SetStateAction<number>>;
+  setStorage: Dispatch<SetStateAction<number>>;
+  contractAddress: string;
+  setBeaconConnection: Dispatch<SetStateAction<boolean>>;
+  setPublicToken: Dispatch<SetStateAction<string | null>>;
+  wallet: BeaconWallet;
+};
+
+const ConnectButton = ({
+  Tezos,
+  setContract,
+  setWallet,
+  setUserAddress,
+  setUserBalance,
+  setStorage,
+  contractAddress,
+  setBeaconConnection,
+  setPublicToken,
+  wallet
+}: ButtonProps): JSX.Element => {
+  const [loadingNano, setLoadingNano] = useState<boolean>(false);
+
+  const setup = async (userAddress: string): Promise<void> => {
+    setUserAddress(userAddress);
+    // updates balance
+    const balance = await Tezos.tz.getBalance(userAddress);
+    setUserBalance(balance.toNumber());
+    // creates contract instance
+    const contract = await Tezos.wallet.at(contractAddress);
+    const storage: any = await contract.storage();
+    setContract(contract);
+    setStorage(storage);
+  };
+
+  const connectWallet = async (): Promise<void> => {
+    try {
+      await wallet.requestPermissions({
+        network: {
+          type: NetworkType.GRANADANET,
+          rpcUrl: "https://api.tez.ie/rpc/granadanet"
+        }
+      });
+      // gets user's address
+      const userAddress = await wallet.getPKH();
+      await setup(userAddress);
+      setBeaconConnection(true);
+    } catch (error) {
+      console.log(error);
+    }
+  };
+
+  const connectNano = async (): Promise<void> => {
+    try {
+      setLoadingNano(true);
+      const transport = await TransportU2F.create();
+      const ledgerSigner = new LedgerSigner(transport, "44'/1729'/0'/0'", true);
+
+      Tezos.setSignerProvider(ledgerSigner);
+
+      //Get the public key and the public key hash from the Ledger
+      const userAddress = await Tezos.signer.publicKeyHash();
+      await setup(userAddress);
+    } catch (error) {
+      console.log("Error!", error);
+      setLoadingNano(false);
+    }
+  };
+
+  useEffect(() => {
+    (async () => {
+      // creates a wallet instance
+      const wallet = new BeaconWallet({
+        name: "Taquito Boilerplate",
+        preferredNetwork: NetworkType.GRANADANET,
+        disableDefaultEvents: true, // Disable all events / UI. This also disables the pairing alert.
+        eventHandlers: {
+          // To keep the pairing alert, we have to add the following default event handlers back
+          [BeaconEvent.PAIR_INIT]: {
+            handler: defaultEventCallbacks.PAIR_INIT
+          },
+          [BeaconEvent.PAIR_SUCCESS]: {
+            handler: data => setPublicToken(data.publicKey)
+          }
+        }
+      });
+      Tezos.setWalletProvider(wallet);
+      setWallet(wallet);
+      // checks if wallet was connected before
+      const activeAccount = await wallet.client.getActiveAccount();
+      if (activeAccount) {
+        const userAddress = await wallet.getPKH();
+        await setup(userAddress);
+        setBeaconConnection(true);
+      }
+    })();
+  }, []);
+
+  return (
+    <div className="buttons">
+      <button className="button" onClick={connectWallet}>
+        <span>
+          <i className="fas fa-wallet"></i>&nbsp; Connect with wallet
+        </span>
+      </button>
+      <button className="button" disabled={loadingNano} onClick={connectNano}>
+        {loadingNano ? (
+          <span>
+            <i className="fas fa-spinner fa-spin"></i>&nbsp; Loading, please
+            wait
+          </span>
+        ) : (
+          <span>
+            <i className="fab fa-usb"></i>&nbsp; Connect with Ledger Nano
+          </span>
+        )}
+      </button>
+    </div>
+  );
+};
+
+export default ConnectButton;
diff --git a/client/src/components/DisconnectWallet.tsx b/client/src/components/DisconnectWallet.tsx
new file mode 100644
index 0000000..45e6643
--- /dev/null
+++ b/client/src/components/DisconnectWallet.tsx
@@ -0,0 +1,50 @@
+import React, { Dispatch, SetStateAction } from "react";
+import { BeaconWallet } from "@taquito/beacon-wallet";
+import { TezosToolkit } from "@taquito/taquito";
+
+interface ButtonProps {
+  wallet: BeaconWallet | null;
+  setPublicToken: Dispatch<SetStateAction<string | null>>;
+  setUserAddress: Dispatch<SetStateAction<string>>;
+  setUserBalance: Dispatch<SetStateAction<number>>;
+  setWallet: Dispatch<SetStateAction<any>>;
+  setTezos: Dispatch<SetStateAction<TezosToolkit>>;
+  setBeaconConnection: Dispatch<SetStateAction<boolean>>;
+}
+
+const DisconnectButton = ({
+  wallet,
+  setPublicToken,
+  setUserAddress,
+  setUserBalance,
+  setWallet,
+  setTezos,
+  setBeaconConnection
+}: ButtonProps): JSX.Element => {
+  const disconnectWallet = async (): Promise<void> => {
+    //window.localStorage.clear();
+    setUserAddress("");
+    setUserBalance(0);
+    setWallet(null);
+    const tezosTK = new TezosToolkit("https://api.tez.ie/rpc/granadanet");
+    setTezos(tezosTK);
+    setBeaconConnection(false);
+    setPublicToken(null);
+    console.log("disconnecting wallet");
+    if (wallet) {
+      await wallet.client.removeAllAccounts();
+      await wallet.client.removeAllPeers();
+      await wallet.client.destroy();
+    }
+  };
+
+  return (
+    <div className="buttons">
+      <button className="button" onClick={disconnectWallet}>
+        <i className="fas fa-times"></i>&nbsp; Disconnect wallet
+      </button>
+    </div>
+  );
+};
+
+export default DisconnectButton;
diff --git a/client/src/components/Records.tsx b/client/src/components/Records.tsx
new file mode 100644
index 0000000..eec867d
--- /dev/null
+++ b/client/src/components/Records.tsx
@@ -0,0 +1,49 @@
+import React, { useState, Dispatch, SetStateAction } from "react";
+import { ContractMethod, TezosToolkit, WalletContract } from "@taquito/taquito";
+
+interface RecordsProps {
+  contract: WalletContract | any;
+  setUserBalance: Dispatch<SetStateAction<any>>;
+  Tezos: TezosToolkit;
+  userAddress: string;
+  setStorage: Dispatch<SetStateAction<number>>;
+}
+
+const Records = ({ contract, setUserBalance, Tezos, userAddress, setStorage }: RecordsProps) => {
+  const [loadingIncrement, setLoadingIncrement] = useState<boolean>(false);
+  const [loadingDecrement, setLoadingDecrement] = useState<boolean>(false);
+
+  const addRecord = async (): Promise<void> => {
+    setLoadingIncrement(true);
+    try {
+      const op = await contract.methods.default("tesds").send();
+      await op.confirmation();
+      const newStorage: any = await contract.storage();
+      if (newStorage) setStorage(newStorage);
+      setUserBalance(await Tezos.tz.getBalance(userAddress));
+    } catch (error) {
+      console.log(error);
+    } finally {
+      setLoadingIncrement(false);
+    }
+  };
+
+  if (!contract && !userAddress) return <div>&nbsp;</div>;
+  return (
+    <div className="buttons">
+      <button className="button" disabled={loadingIncrement} onClick={addRecord}>
+        {loadingIncrement ? (
+          <span>
+            <i className="fas fa-spinner fa-spin"></i>&nbsp; Please wait
+          </span>
+        ) : (
+          <span>
+            <i className="fas fa-plus"></i>&nbsp; Add Record
+          </span>
+        )}
+      </button>
+    </div>
+  );
+};
+
+export default Records;
diff --git a/client/src/components/Transfers.tsx b/client/src/components/Transfers.tsx
new file mode 100644
index 0000000..3bd1e65
--- /dev/null
+++ b/client/src/components/Transfers.tsx
@@ -0,0 +1,70 @@
+import React, { useState, Dispatch, SetStateAction } from "react";
+import { TezosToolkit } from "@taquito/taquito";
+
+const Transfers = ({
+  Tezos,
+  setUserBalance,
+  userAddress
+}: {
+  Tezos: TezosToolkit;
+  setUserBalance: Dispatch<SetStateAction<number>>;
+  userAddress: string;
+}): JSX.Element => {
+  const [recipient, setRecipient] = useState<string>("");
+  const [amount, setAmount] = useState<string>("");
+  const [loading, setLoading] = useState<boolean>(false);
+
+  const sendTransfer = async (): Promise<void> => {
+    if (recipient && amount) {
+      setLoading(true);
+      try {
+        const op = await Tezos.wallet
+          .transfer({ to: recipient, amount: parseInt(amount) })
+          .send();
+        await op.confirmation();
+        setRecipient("");
+        setAmount("");
+        const balance = await Tezos.tz.getBalance(userAddress);
+        setUserBalance(balance.toNumber());
+      } catch (error) {
+        console.log(error);
+      } finally {
+        setLoading(false);
+      }
+    }
+  };
+
+  return (
+    <div id="transfer-inputs">
+      <input
+        type="text"
+        placeholder="Recipient"
+        value={recipient}
+        onChange={e => setRecipient(e.target.value)}
+      />
+      <input
+        type="number"
+        placeholder="Amount"
+        value={amount}
+        onChange={e => setAmount(e.target.value)}
+      />
+      <button
+        className="button"
+        disabled={!recipient && !amount}
+        onClick={sendTransfer}
+      >
+        {loading ? (
+          <span>
+            <i className="fas fa-spinner fa-spin"></i>&nbsp; Please wait
+          </span>
+        ) : (
+          <span>
+            <i className="far fa-paper-plane"></i>&nbsp; Send
+          </span>
+        )}
+      </button>
+    </div>
+  );
+};
+
+export default Transfers;