diff --git a/bun.lockb b/bun.lockb index 5cba6d3..01129a6 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 5b1bde5..5f2ba8d 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,14 @@ "type": "module", "scripts": { "dev": "bun i && bun link @biconomy/account && vite", + "start": "vite", "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" }, "dependencies": { - "@biconomy/account": "^4.4.0", + "@biconomy/account": "^4.4.5", + "@biconomy/use-aa": "^1.0.8", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", "@ethersproject/providers": "^5.7.2", @@ -24,8 +26,8 @@ "react-dom": "^18.2.0", "react-scripts": "5.0.1", "react-toastify": "^9.0.8", - "viem": "^2.10.2", - "wagmi": "latest" + "viem": "^2.13.7", + "wagmi": "^2.9.9" }, "devDependencies": { "@types/react": "^18.3.1", diff --git a/src/App.tsx b/src/App.tsx index 13354ca..9e3da80 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,29 @@ import React from "react"; import { makeStyles } from "@mui/styles"; import { ToastContainer } from "react-toastify"; -import { useAccount } from 'wagmi' -import { ConnectButton } from '@rainbow-me/rainbowkit'; +import { useAccount } from "wagmi"; +import { ConnectButton } from "@rainbow-me/rainbowkit"; import TabsBody from "./components/TabsBody"; -import { useSmartAccountContext } from "./contexts/SmartAccountContext"; const App: React.FC = () => { const classes = useStyles(); - const { address } = useAccount() - const { loading } = useSmartAccountContext(); + const { address } = useAccount(); if (!address) { return (

- - Biconomy SDK

+ + Biconomy SDK +

Solve complex UX challenges with customisable SDK modules in minutes. @@ -34,7 +36,7 @@ const App: React.FC = () => { return (

- +
); diff --git a/src/components/AA/BatchLiquidity.tsx b/src/components/AA/BatchLiquidity.tsx deleted file mode 100644 index c9e7d0e..0000000 --- a/src/components/AA/BatchLiquidity.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import React, { useState } from "react"; -import { makeStyles } from "@mui/styles"; -import { Hex, encodeFunctionData, parseEther, parseUnits } from "viem"; -import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { - configInfo as config, - showSuccessMessage, - showErrorMessage, -} from "../../utils"; -import { PaymasterMode } from "@biconomy/account"; - -const BatchLiquidity: React.FC = () => { - const classes = useStyles(); - const { smartAccount, scwAddress } = useSmartAccountContext(); - const [loading, setLoading] = useState(false); - - const makeTx = async () => { - if (!scwAddress || !smartAccount) return; - try { - setLoading(true); - - const approveCallData = encodeFunctionData({ - abi: config.usdc.abi, - functionName: "approve", - args: [config.hyphenLP.address, parseEther("1")], - }); - const tx1 = { - to: config.usdc.address as Hex, - value: BigInt(0), - data: approveCallData, - }; - - const addLiquidityData = encodeFunctionData({ - abi: config.hyphenLP.abi, - functionName: "addTokenLiquidity", - args: [config.usdc.address, parseUnits("0.001", 6)], - }); - const tx2 = { - to: config.hyphenLP.address as Hex, - value: BigInt(0), - data: addLiquidityData, - }; - - let { waitForTxHash } = await smartAccount.sendTransaction([tx1, tx2], { - paymasterServiceData: { mode: PaymasterMode.SPONSORED }, - }); - const { transactionHash } = await waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage( - `Added batch liquidity ${transactionHash}`, - transactionHash - ); - setLoading(false); - } catch (err: any) { - console.error(err); - setLoading(false); - showErrorMessage(err.message || "Error in sending the transaction"); - } - }; - - return ( -
-

- Use Cases {"->"} Gasless {"->"} USDC Liquidity on Hyphen -

- -

Approve and Add Liquidity in Hyphen

- -

- This magic bundle will approve USDC then provide the USDC liquidity to - Hyphen Pool -

- -

Transaction Batched

-
    -
  • Approve USDC
  • -
  • Provide USDC Liquidity on Hyphen
  • -
- -
- ); -}; - -const useStyles = makeStyles(() => ({ - main: { - padding: "10px 40px", - color: "#EEEEEE", - }, - subTitle: { - color: "#FFB999", - fontSize: 36, - margin: 0, - }, - h3Title: { - color: "#e6e6e6", - }, - container: { - // backgroundColor: "rgb(29, 31, 33)", - }, - containerBtn: { - display: "flex", - gap: 15, - // justifyContent: "space-between", - }, - tab: { - padding: "5px 15px", - backgroundColor: "#FCF8E8", - marginBottom: 10, - }, - listHover: { - "&:hover": { - color: "#FF9551", - }, - }, -})); - -export default BatchLiquidity; diff --git a/src/components/AA/MintNft.tsx b/src/components/AA/MintNft.tsx index b8fc259..1bc3fa6 100644 --- a/src/components/AA/MintNft.tsx +++ b/src/components/AA/MintNft.tsx @@ -3,20 +3,34 @@ import { makeStyles } from "@mui/styles"; import { usePublicClient } from "wagmi"; import { Hex, encodeFunctionData, getContract } from "viem"; import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; +import { configInfo as config, showSuccessMessage } from "../../utils"; import { - configInfo as config, - showErrorMessage, - showSuccessMessage, -} from "../../utils"; -import { PaymasterMode } from "@biconomy/account"; + useSendTransaction, + useSmartAccount, + useUserOpWait, +} from "@biconomy/use-aa"; +import { ErrorGuard } from "../../utils/ErrorGuard"; +import { polygonAmoy } from "viem/chains"; const MintNft: React.FC = () => { const classes = useStyles(); const publicClient = usePublicClient(); - const { smartAccount, scwAddress } = useSmartAccountContext(); const [nftCount, setNftCount] = useState(null); - const [loading, setLoading] = useState(false); + const [loadedCount, setLoadedCount] = useState(false); + + const { smartAccountAddress: scwAddress } = useSmartAccount(); + const { + mutate, + data: userOpResponse, + error, + isPending, + } = useSendTransaction(); + const { + isLoading: waitIsLoading, + isSuccess: waitIsSuccess, + error: waitError, + data: waitData, + } = useUserOpWait({ userOpResponse }); const getNftCount = useCallback(async () => { if (!scwAddress || !publicClient) return; @@ -31,66 +45,56 @@ const MintNft: React.FC = () => { }, [publicClient, scwAddress]); useEffect(() => { - getNftCount(); - }, [getNftCount, publicClient]); - - const mintNft = async () => { - if (!scwAddress || !smartAccount || !publicClient) return; - try { - setLoading(true); - const mintData = encodeFunctionData({ - abi: config.nft.abi, - functionName: "safeMint", - args: [scwAddress as Hex], - }); - const tx1 = { - to: config.nft.address as Hex, - value: BigInt(0), - data: mintData, - }; - let { waitForTxHash } = await smartAccount.sendTransaction(tx1, { - paymasterServiceData: { mode: PaymasterMode.SPONSORED }, - }); - const { transactionHash } = await waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage(`Minted Nft ${transactionHash}`, transactionHash); - setLoading(false); - await new Promise((resolve) => setTimeout(resolve, 2000)); + if (waitIsSuccess || !loadedCount) { getNftCount(); - } catch (err: any) { - console.error(err); - setLoading(false); - showErrorMessage(err.message || "Error in sending the transaction"); + setLoadedCount(true); } - }; - - return ( -
-

- Use Cases {"->"} Gasless {"->"} Mint Nft -

+ }, [getNftCount, waitIsSuccess]); -

Mint Nft Flow

+ useEffect(() => { + waitIsSuccess && + showSuccessMessage( + "Successful mint: " + + `${polygonAmoy.blockExplorers.default.url}/tx/${waitData?.receipt?.transactionHash}` + ); + }, [waitIsSuccess]); -

- This is an example gasless transaction to Mint Nft. -

-

- Nft Contract Address: {config.nft.address}{" "} - - (same of goerli, amoy, polygon) - -

-

- Nft Balance in SCW:{" "} - {nftCount === null ? ( -

fetching...

- ) : ( - nftCount - )} -

+ const mintNft = () => + mutate({ + manyOrOneTransactions: { + to: config.nft.address as Hex, + data: encodeFunctionData({ + abi: config.nft.abi, + functionName: "safeMint", + args: [scwAddress as Hex], + }), + }, + }); -
); }; diff --git a/src/components/AA/index.tsx b/src/components/AA/index.tsx index 55bd844..439ee5d 100644 --- a/src/components/AA/index.tsx +++ b/src/components/AA/index.tsx @@ -1,9 +1,6 @@ import React from "react"; import { makeStyles } from "@mui/styles"; -// import ControlPointIcon from "@mui/icons-material/ControlPoint"; import ImageIcon from "@mui/icons-material/Image"; -import ControlPointDuplicateIcon from "@mui/icons-material/ControlPointDuplicate"; -// import CollectionsIcon from "@mui/icons-material/Collections"; interface Props { useCase: number; @@ -12,19 +9,6 @@ interface Props { } const cardItems = [ - // { - // title: "Mint ERC20 Token", - // description: "This is single transaction to give Mint an ERC-20 token", - // index: 4, - // icon: ( - // - // ), - // }, { title: "Mint NFT", description: @@ -39,34 +23,6 @@ const cardItems = [ /> ), }, - { - title: "BatchTx - Liquidity", - description: - "This magic bundle will approve USDC then provide the USDC liquidity to Hyphen Pool.", - index: 4, - icon: ( - - ), - }, - // { - // title: "BatchTx - NFT", - // description: - // "This magic bundle will batch two single safeMint into one transaction.", - // index: 7, - // icon: ( - // - // ), - // }, ]; const AccountAbstraction: React.FC = ({ diff --git a/src/components/Faucet/index.tsx b/src/components/Faucet/index.tsx index 7412432..d07e7e1 100644 --- a/src/components/Faucet/index.tsx +++ b/src/components/Faucet/index.tsx @@ -1,69 +1,79 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { makeStyles } from "@mui/styles"; import { Hex, encodeFunctionData } from "viem"; import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; import { - configInfo as config, - showErrorMessage, - showInfoMessage, - showSuccessMessage, -} from "../../utils"; + useSendTransaction, + useSmartAccount, + useUserOpWait, +} from "@biconomy/use-aa"; +import { configInfo as config, showSuccessMessage } from "../../utils"; +import { ErrorGuard } from "../../utils/ErrorGuard"; const Faucet: React.FC = () => { const classes = useStyles(); - const { smartAccount, scwAddress } = useSmartAccountContext(); + const { smartAccountAddress: scwAddress } = useSmartAccount(); const [address, setAddress] = useState(scwAddress); - const makeTx = async () => { - if (!smartAccount || !scwAddress) { - showErrorMessage("Please connect your wallet"); - return; - } - showInfoMessage("Initiating Faucet..."); - try { - const faucetTxData = encodeFunctionData({ - abi: config.faucet.abi, - functionName: "drip", - args: [address as Hex], - }); - const tx1 = { + const { + mutate, + data: userOpResponse, + error, + isPending, + } = useSendTransaction(); + const { + isSuccess: waitIsSuccess, + error: waitError, + isLoading: waitIsLoading, + data: waitData, + } = useUserOpWait({ + userOpResponse, + }); + + const drip = () => + mutate({ + manyOrOneTransactions: { to: config.faucet.address as Hex, - value: BigInt(0), - data: faucetTxData, - }; - let userOpResponse = await smartAccount.sendTransaction(tx1); - console.log("userOpHash", userOpResponse); - const { transactionHash } = await userOpResponse.waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage(`Tokens sent ${transactionHash}`, transactionHash); - } catch (error: any) { - console.error(error); - showErrorMessage(error.message); - } - }; + data: encodeFunctionData({ + abi: config.faucet.abi, + functionName: "drip", + args: [address as Hex], + }), + }, + }); + + useEffect(() => { + waitIsSuccess && + showSuccessMessage( + "Successful mint: " + + `${polygonAmoy.blockExplorers.default.url}/tx/${waitData?.receipt?.transactionHash}` + ); + }, [waitIsSuccess]); return (
-

Faucet

- -

- Get USDC and USDT test tokens. We will airdrop these tokens to the SCW - address so you can test the SDK. -

- -

You can also change the address

- - setAddress(e.target.value as Hex)} - className={classes.input} - /> + +

Faucet

+

+ Get USDC and USDT test tokens. We will airdrop these tokens to the SCW + address so you can test the SDK. +

+

You can also change the address

+ setAddress(e.target.value as Hex)} + className={classes.input} + /> -
); }; diff --git a/src/components/Forward/BatchLiquidity.tsx b/src/components/Forward/BatchLiquidity.tsx deleted file mode 100644 index 8a35918..0000000 --- a/src/components/Forward/BatchLiquidity.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { makeStyles } from "@mui/styles"; -import { CircularProgress } from "@mui/material"; -import { PaymasterFeeQuote, PaymasterMode } from "@biconomy/account"; - -import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { - configInfo as config, - showSuccessMessage, - showErrorMessage, -} from "../../utils"; -import { Hex, encodeFunctionData, parseEther, parseUnits } from "viem"; - -const BatchLiquidity: React.FC = () => { - const classes = useStyles(); - const { smartAccount, scwAddress } = useSmartAccountContext(); - const [isLoading, setIsLoading] = useState(true); - const [isLoadingFee, setIsLoadingFee] = useState(false); - - const [spender, setSpender] = useState(""); - const [feeQuotesArr, setFeeQuotesArr] = useState([]); - const [selectedQuote, setSelectedQuote] = useState(); - const [tx, setTx] = useState([]); - - // pre calculate the fee - useEffect(() => { - const fetchFeeOption = async () => { - setIsLoading(true); - setIsLoadingFee(true); - setFeeQuotesArr([]); - if (!smartAccount || !scwAddress) return; - const approveCallData = encodeFunctionData({ - abi: config.usdc.abi, - functionName: "approve", - args: [config.hyphenLP.address, parseEther("1")], - }); - const tx1 = { - to: config.usdc.address as Hex, - data: approveCallData, - }; - - const addLiquidityData = encodeFunctionData({ - abi: config.hyphenLP.abi, - functionName: "addTokenLiquidity", - args: [config.usdc.address, parseUnits("0.001", 6)], - }); - const tx2 = { - to: config.hyphenLP.address as Hex, - data: addLiquidityData, - }; - - console.log("Tx array created", [tx1, tx2]); - setTx([tx1, tx2]); - const feeQuotesResponse = await smartAccount.getTokenFees([tx1, tx2], { - paymasterServiceData: { mode: PaymasterMode.ERC20 }, - }); - setSpender(feeQuotesResponse.tokenPaymasterAddress || ""); - const feeQuotes = feeQuotesResponse.feeQuotes as PaymasterFeeQuote[]; - setFeeQuotesArr(feeQuotes); - console.log("getFeeQuotesForBatch", feeQuotes); - setIsLoadingFee(false); - setIsLoading(false); - }; - fetchFeeOption(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [scwAddress]); - - const makeTx = async () => { - if (!smartAccount || !scwAddress) return; - if (!selectedQuote) { - showErrorMessage("Please select a fee quote"); - return; - } - try { - setIsLoading(true); - console.log("selected quote", selectedQuote); - // const finalUserOp = { ...estimatedUserOp } as any; - const userOpResponse = await smartAccount.sendTransaction(tx, { - paymasterServiceData: { - feeQuote: selectedQuote, - spender: spender as Hex, - mode: PaymasterMode.ERC20, - maxApproval: false, - }, - }); - - console.log("userOpHash", userOpResponse); - const { transactionHash } = await userOpResponse.waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage( - `Batch Add Hyphen Liq ${transactionHash}`, - transactionHash - ); - setIsLoading(false); - } catch (err: any) { - console.error(err); - setIsLoading(false); - showErrorMessage(err.message || "Error in sending the transaction"); - } - }; - - return ( -
-

- Use Cases {"->"} Forward {"->"} USDC Liquidity on Hyphen -

- -

Approve and Add Liquidity in Hyphen

- -

- This magic bundle will approve USDC then provide the USDC liquidity to - Hyphen Pool -

- -

Transaction Batched

-
    -
  • Deploy Wallet if not already deployed
  • -
  • Approve USDC
  • -
  • Provide USDC Liquidity on Hyphen
  • -
- -

Available Fee options

- - {isLoadingFee && ( -
- {" "} - {" Loading Fee Options"} -
- )} - -
    - {feeQuotesArr.map((token, ind) => ( - //
  • - // {parseFloat( - // (token.payment / Math.pow(10, token.decimal)).toString() - // ).toFixed(8)}{" "} - // {token.symbol} - //
  • -
    - setSelectedQuote(token)} - style={{ - color: "#FFB999", - }} - name={token.symbol} - id={token.symbol} - checked={selectedQuote === token} - /> - -
    - ))} -
-
- ); -}; - -const useStyles = makeStyles(() => ({ - main: { - margin: "auto", - padding: "10px 40px", - color: "#EEEEEE", - }, - subTitle: { - color: "#FFB999", - fontSize: 36, - margin: 0, - }, - h3Title: { - color: "#e6e6e6", - }, - container: { - // backgroundColor: "rgb(29, 31, 33)", - }, - containerBtn: { - display: "flex", - gap: 15, - // justifyContent: "space-between", - }, - tab: { - padding: "5px 15px", - backgroundColor: "#FCF8E8", - marginBottom: 10, - }, - listHover: { - "&:hover": { - color: "#FFB999", - }, - }, -})); - -export default BatchLiquidity; diff --git a/src/components/Forward/MintNft.tsx b/src/components/Forward/MintNft.tsx index 25fca40..63031b2 100644 --- a/src/components/Forward/MintNft.tsx +++ b/src/components/Forward/MintNft.tsx @@ -1,30 +1,35 @@ -import React, { useEffect, useState } from "react"; import { makeStyles } from "@mui/styles"; import CircularProgress from "@mui/material/CircularProgress"; import { PaymasterFeeQuote, PaymasterMode } from "@biconomy/account"; +import React, { useCallback, useEffect, useState } from "react"; import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; +import { + useSendTransaction, + useSmartAccount, + useUserOpWait, +} from "@biconomy/use-aa"; import { configInfo as config, showErrorMessage, showSuccessMessage, } from "../../utils"; import { Hex, encodeFunctionData, getContract } from "viem"; -import { usePublicClient } from "wagmi"; +import { useCall, usePublicClient } from "wagmi"; +import { ErrorGuard } from "../../utils/ErrorGuard"; +import { polygonAmoy } from "viem/chains"; const MintNftForward: React.FC = () => { const classes = useStyles(); const publicClient = usePublicClient(); - const { smartAccount, scwAddress } = useSmartAccountContext(); + const { smartAccountClient: smartAccount, smartAccountAddress: scwAddress } = + useSmartAccount(); const [nftCount, setNftCount] = useState(null); - const [isLoading, setIsLoading] = useState(false); const [isLoadingFee, setIsLoadingFee] = useState(false); const [spender, setSpender] = useState(""); const [feeQuotesArr, setFeeQuotesArr] = useState([]); const [selectedQuote, setSelectedQuote] = useState(); - const [tx, setTx] = useState(); useEffect(() => { const getNftCount = async () => { @@ -46,18 +51,17 @@ const MintNftForward: React.FC = () => { const getFee = async () => { if (!smartAccount || !scwAddress || !publicClient) return; setIsLoadingFee(true); - const mintData = encodeFunctionData({ - abi: config.nft.abi, - functionName: "safeMint", - args: [scwAddress as Hex], - }); - const tx1 = { + + const tx = { to: config.nft.address, - value: 0, - data: mintData, + data: encodeFunctionData({ + abi: config.nft.abi, + functionName: "safeMint", + args: [scwAddress as Hex], + }), }; - setTx(tx1 as any); - const feeQuotesResponse = await smartAccount.getTokenFees([tx1], { + + const feeQuotesResponse = await smartAccount.getTokenFees([tx], { paymasterServiceData: { mode: PaymasterMode.ERC20 }, }); setSpender(feeQuotesResponse.tokenPaymasterAddress || ""); @@ -67,110 +71,128 @@ const MintNftForward: React.FC = () => { setIsLoadingFee(false); }; - const makeTx = async () => { - if (!smartAccount || !scwAddress || !publicClient) return; - if (!selectedQuote) { - showErrorMessage("Please select a fee quote"); - return; - } - try { - setIsLoading(true); - console.log("selected quote", selectedQuote); - // const finalUserOp = { ...estimatedUserOp } as any; - const userOpResponse = await smartAccount.sendTransaction(tx!, { + const { + mutate, + data: userOpResponse, + error, + isPending: isLoading, + } = useSendTransaction(); + const { + isLoading: waitIsLoading, + isSuccess: waitIsSuccess, + error: waitError, + data: waitData, + } = useUserOpWait({ userOpResponse }); + + useEffect(() => { + waitIsSuccess && + showSuccessMessage( + "Successful mint: " + + `${polygonAmoy.blockExplorers.default.url}/tx/${waitData?.receipt?.transactionHash}` + ); + }, [waitIsSuccess]); + + const mintNft = () => { + const manyOrOneTransactions = { + to: config.nft.address, + data: encodeFunctionData({ + abi: config.nft.abi, + functionName: "safeMint", + args: [scwAddress as Hex], + }), + }; + + mutate({ + manyOrOneTransactions, + buildUseropDto: { paymasterServiceData: { feeQuote: selectedQuote, mode: PaymasterMode.ERC20, spender: spender as Hex, maxApproval: false, }, - }); - - console.log("userOpHash", userOpResponse); - const { transactionHash } = await userOpResponse.waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage(`Minted Nft ${transactionHash}`, transactionHash); - setIsLoading(false); - } catch (err: any) { - console.error(err); - setIsLoading(false); - showErrorMessage(err.message || "Error in sending the transaction"); - } + }, + }); }; return (
-

- Use Cases {"->"} Gasless {"->"} Mint Nft -

- -

Mint Nft Flow

- -

- This is an example gasless transaction to Mint Nft. -

-

- Nft Balance in SCW:{" "} - {nftCount === null ? ( -

fetching...

- ) : ( - nftCount - )} -

+ +

+ Use Cases {"->"} Gasless {"->"} Mint Nft +

-

Available Fee options

+

Mint Nft Flow

- {isLoadingFee && ( -
+ This is an example gasless transaction to Mint Nft. +

+

+ Nft Balance in SCW:{" "} + {nftCount === null ? ( +

fetching...

+ ) : ( + nftCount + )} +

+ +

Available Fee options

+ + {isLoadingFee && ( +
+ {" "} + {" Loading Fee Options"} +
+ )} +
    - {" "} - {" Loading Fee Options"} -
- )} -
    - {feeQuotesArr.map((token, ind) => ( - //
  • - // {parseFloat( - // (token.payment / Math.pow(10, token.decimal)).toString() - // ).toFixed(8)}{" "} - // {token.symbol} - //
  • -
    - setSelectedQuote(token)} - style={{ - color: "#FFB999", - }} - name={token.symbol} - id={token.symbol} - checked={selectedQuote === token} - /> - -
    - ))} -
+ {feeQuotesArr.map((token, ind) => ( +
+ setSelectedQuote(token)} + style={{ + color: "#FFB999", + }} + name={token.symbol} + id={token.symbol} + checked={selectedQuote === token} + /> + +
+ ))} + -
); }; diff --git a/src/components/Forward/index.tsx b/src/components/Forward/index.tsx index 0477f42..07b744a 100644 --- a/src/components/Forward/index.tsx +++ b/src/components/Forward/index.tsx @@ -1,6 +1,5 @@ import React from "react"; import { makeStyles } from "@mui/styles"; -import ControlPointDuplicateIcon from "@mui/icons-material/ControlPointDuplicate"; import CollectionsIcon from "@mui/icons-material/Collections"; interface Props { @@ -24,20 +23,6 @@ const cardItems = [ /> ), }, - { - title: "Batch Liquidity", - description: - "This magic bundle will approve USDC then provide the USDC liquidity to Hyphen Pool.", - index: 7, - icon: ( - - ), - }, ]; const ForwardFlow: React.FC = ({ diff --git a/src/components/Modules/ABI_SVM.tsx b/src/components/Modules/ABI_SVM.tsx deleted file mode 100644 index 5b7caeb..0000000 --- a/src/components/Modules/ABI_SVM.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { useState } from "react"; -import { Contract, ethers } from "ethers"; -import abis from "../../utils/configs/contractsInfo.json"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { useAccount } from "wagmi"; -import CreateABISVM from "./CreateABISVM"; -import { DEFAULT_ABI_SVM_MODULE } from "@biconomy/account"; - -export default function ABISVM() { - const { address } = useAccount(); - const { smartAccount, scwAddress } = useSmartAccountContext(); - const [loading, setLoading] = useState(false); - const [provider, setProvider] = useState(null); - - const [mockStake, setMockStake] = useState(); - - const connect = async () => { - // @ts-ignore - const { ethereum } = window; - try { - setLoading(true); - const provider = new ethers.BrowserProvider(ethereum); - await provider.send("eth_requestAccounts", []); - setProvider(provider); - - setMockStake(mockStake); - setLoading(false); - } catch (error) { - console.error(error); - } - }; - - console.log(smartAccount); - console.log(provider); - - return ( - <> -
-

ABI SVM Demo

- {!loading && !address && ( - - )} - {loading &&

Loading Smart Account...

} - {scwAddress &&

Smart Account: {scwAddress}

} - - {smartAccount && ( - - )} -
- - ); -} diff --git a/src/components/Modules/CreateABISVM.tsx b/src/components/Modules/CreateABISVM.tsx deleted file mode 100644 index 576523b..0000000 --- a/src/components/Modules/CreateABISVM.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import React, { useState } from "react"; -import { Provider, ethers } from "ethers"; -import { toast, ToastContainer } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -import UseABISVM from "./UseABISVM"; -import { useAccount } from "wagmi"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { - BiconomySmartAccountV2, - createSession, - createSessionKeyEOA, - Session, - Policy, - PaymasterMode, -} from "@biconomy/account"; - -import { polygonAmoy } from "viem/chains"; -import Button from "../Button"; - -interface props { - smartAccount: BiconomySmartAccountV2; - address: string; - provider: Provider; - nftContract: ethers.Contract; - abiSVMAddress: string; -} - -const CreateABISVM: React.FC = () => { - const nftAddress = "0x1758f42Af7026fBbB559Dc60EcE0De3ef81f665e"; - const [hasSession, setHasSession] = useState(false); - const { address } = useAccount(); - const { smartAccount, scwAddress } = useSmartAccountContext(); - - const createSessionHandler = async () => { - const toastMessage = "Creating Sessions for " + address; - toast.info(toastMessage, { - position: "top-right", - autoClose: 15000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - theme: "dark", - }); - if (!address || !smartAccount) { - alert("Please connect wallet first"); - } else { - try { - const { sessionKeyAddress, sessionStorageClient } = - // @ts-ignore - await createSessionKeyEOA(smartAccount, polygonAmoy); - - const policy: Policy[] = [ - { - sessionKeyAddress, - contractAddress: nftAddress, - functionSelector: "safeMint(address)", - rules: [ - { - offset: 0, - condition: 0, - referenceValue: scwAddress, - }, - ], - interval: { - validUntil: 0, - validAfter: 0, - }, - valueLimit: 0n, - }, - ]; - - const { wait } = await createSession( - smartAccount, - policy, - sessionStorageClient, - { - paymasterServiceData: { - mode: PaymasterMode.SPONSORED, - }, - } - ); - const { - receipt: { transactionHash }, - success, - } = await wait(); - - console.log("txHash", transactionHash); - console.log("Sessions Enabled"); - if (success) { - setHasSession(true); - toast.success(`Success ${success}`, { - position: "top-right", - autoClose: 6000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - theme: "dark", - }); - } - } catch (err: any) { - console.error(err); - } - } - }; - - return ( -
- - - {!!hasSession ? ( - - ) : ( -
- ); -}; - -export default CreateABISVM; diff --git a/src/components/Modules/CreateBatchSession.tsx b/src/components/Modules/CreateBatchSession.tsx index f74fad6..474dacf 100644 --- a/src/components/Modules/CreateBatchSession.tsx +++ b/src/components/Modules/CreateBatchSession.tsx @@ -1,138 +1,115 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { makeStyles } from "@mui/styles"; -import { - CreateSessionDataParams, - PaymasterMode, - Session, - createABISessionDatum, - createSessionKeyEOA, - createERC20SessionDatum, - createBatchSession, -} from "@biconomy/account"; import { useAccount } from "wagmi"; import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { configInfo, showErrorMessage, showSuccessMessage } from "../../utils"; -import { getActionForErrorMessage } from "../../utils/error-utils"; +import { + Sponsored, + bigIntReplacer, + useCreateBatchSession, + useSmartAccount, + useUserOpWait, +} from "@biconomy/use-aa"; +import { configInfo, showSuccessMessage } from "../../utils"; import { polygonAmoy } from "viem/chains"; -import { Hex, encodeAbiParameters } from "viem"; +import { Hex } from "viem"; import UseBatchSession from "./UseBatchSession"; - -const nftAddress = "0x1758f42Af7026fBbB559Dc60EcE0De3ef81f665e"; -const receiver = "0x42138576848E839827585A3539305774D36B9602"; -const amount = BigInt(50000000); +import { ErrorGuard } from "../../utils/ErrorGuard"; const CreateBatchSession: React.FC = () => { const classes = useStyles(); const { address } = useAccount(); - const { smartAccount, scwAddress } = useSmartAccountContext(); - const [loading, setLoading] = useState(false); + const { smartAccountAddress: scwAddress } = useSmartAccount(); const [hasSession, setHasSession] = useState(false); - const createSessionHandler = async () => { - if (!scwAddress || !smartAccount || !address) { - showErrorMessage("Please connect wallet first"); - return; - } - try { - const { sessionKeyAddress, sessionStorageClient } = - // @ts-ignore - await createSessionKeyEOA(smartAccount, polygonAmoy); - - const leaves: CreateSessionDataParams[] = [ - createERC20SessionDatum({ - interval: { - validUntil: 0, - validAfter: 0, - }, - sessionKeyAddress, - sessionKeyData: encodeAbiParameters( - [ - { type: "address" }, - { type: "address" }, - { type: "address" }, - { type: "uint256" }, - ], - [ - sessionKeyAddress, - configInfo.usdt.address as Hex, // erc20 token address - receiver, // receiver address - amount, - ] - ), - }), - createABISessionDatum({ - interval: { - validUntil: 0, - validAfter: 0, - }, - sessionKeyAddress, - contractAddress: nftAddress, - functionSelector: "safeMint(address)", - rules: [ - { - offset: 0, - condition: 0, - referenceValue: scwAddress, - }, - ], - valueLimit: 0n, - }), - ]; - - const { wait } = await createBatchSession( - smartAccount, - sessionStorageClient, - leaves, + const policyLeaves = [ + { + interval: { + validUntil: 0, + validAfter: 0, + }, + contractAddress: configInfo.nft.address as Hex, + functionSelector: "safeMint(address)", + rules: [ { - paymasterServiceData: { - mode: PaymasterMode.SPONSORED, - }, - } - ); + offset: 0, + condition: 0, + referenceValue: scwAddress, + }, + ], + valueLimit: 0n, + }, + { + interval: { + validUntil: 0, + validAfter: 0, + }, + contractAddress: configInfo.nft.address as Hex, + functionSelector: "safeMint(address)", + rules: [ + { + offset: 0, + condition: 0, + referenceValue: scwAddress, + }, + ], + valueLimit: 0n, + }, + ]; + + const { + mutate, + data: userOpResponse, + error, + isPending: isLoading, + } = useCreateBatchSession(); - const { - receipt: { transactionHash }, - success, - } = await wait(); + const { + isLoading: waitIsLoading, + isSuccess: waitIsSuccess, + error: waitError, + data: waitData, + } = useUserOpWait({ userOpResponse }); - console.log("txHash", transactionHash); - if (success) { - setHasSession(true); - showSuccessMessage( - `Session Created: ${transactionHash}`, - transactionHash - ); - } - } catch (err: any) { - console.error(err); - setLoading(false); - const errorAction = getActionForErrorMessage(err.message); - showErrorMessage( - errorAction || err.message || "Error in sending the transaction" + useEffect(() => { + if (waitIsSuccess) { + setHasSession(true); + showSuccessMessage( + "Successful mint: " + + `${polygonAmoy.blockExplorers.default.url}/tx/${waitData?.receipt?.transactionHash}` ); } - }; + }, [waitIsSuccess]); + + const createSessionHandler = () => + mutate({ + policy: policyLeaves, + buildUseropDto: Sponsored, + }); return (
-

- Use Cases {"->"} Session {"->"} Create Session -

+ +

+ Use Cases {"->"} Session {"->"} Create Batch Session +

+ +

Create Batch Session Flow

-

Create Batch Session Flow

+
policy: {JSON.stringify(policyLeaves, bigIntReplacer, 2)}
- {!!hasSession ? ( - - ) : ( -
); }; diff --git a/src/components/Modules/CreateSession.tsx b/src/components/Modules/CreateSession.tsx new file mode 100644 index 0000000..15ab13a --- /dev/null +++ b/src/components/Modules/CreateSession.tsx @@ -0,0 +1,140 @@ +import React, { useEffect, useState } from "react"; +import { toast, ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; +import UseSession from "./UseSession"; +import { useAccount } from "wagmi"; +import { + Sponsored, + bigIntReplacer, + useCreateSession, + useSmartAccount, + useUserOpWait, +} from "@biconomy/use-aa"; +import Button from "../Button"; +import { makeStyles } from "@mui/styles"; +import { Hex } from "viem"; +import { ErrorGuard } from "../../utils/ErrorGuard"; +import { showSuccessMessage } from "../../utils"; +import { polygonAmoy } from "viem/chains"; + +const CreateSession: React.FC = () => { + const classes = useStyles(); + + const nftAddress: Hex = "0x1758f42Af7026fBbB559Dc60EcE0De3ef81f665e"; + + const [hasSession, setHasSession] = useState(false); + const { address } = useAccount(); + const { smartAccountAddress: scwAddress } = useSmartAccount(); + + const policy = [ + { + contractAddress: nftAddress, + functionSelector: "safeMint(address)", + rules: [ + { + offset: 0, + condition: 0, + referenceValue: scwAddress, + }, + ], + interval: { + validUntil: 0, + validAfter: 0, + }, + valueLimit: 0n, + }, + ]; + + const { + mutate, + data: userOpResponse, + error, + isPending: isLoading, + } = useCreateSession(); + + const { + isLoading: waitIsLoading, + isSuccess: waitIsSuccess, + error: waitError, + data: waitData, + } = useUserOpWait({ userOpResponse }); + + useEffect(() => { + if (waitIsSuccess) { + setHasSession(true); + showSuccessMessage( + "Successful mint: " + + `${polygonAmoy.blockExplorers.default.url}/tx/${waitData?.receipt?.transactionHash}` + ); + } + }, [waitIsSuccess]); + + const createSessionHandler = () => + mutate({ + policy, + buildUseropDto: Sponsored, + }); + + return ( +
+ +

+ Use Cases {"->"} Modules {"->"} {hasSession ? "Use" : "Create"}{" "} + Session +

+ +

+ {hasSession ? "Use" : "Create"} a Session +

+ + + +
policy: {JSON.stringify(policy, bigIntReplacer, 2)}
+ + {!!hasSession ? ( + + ) : ( +
+ ); +}; + +const useStyles = makeStyles(() => ({ + main: { + margin: "auto", + padding: "10px 40px", + color: "#EEEEEE", + }, + subTitle: { + color: "#FFB999", + fontSize: 36, + margin: 0, + }, + h3Title: { + color: "#e6e6e6", + }, + listHover: { + "&:hover": { + color: "#FF9551", + }, + }, +})); + +export default CreateSession; diff --git a/src/components/Modules/CreateSessionForCustomSVM.tsx b/src/components/Modules/CreateSessionForCustomSVM.tsx deleted file mode 100644 index 883f730..0000000 --- a/src/components/Modules/CreateSessionForCustomSVM.tsx +++ /dev/null @@ -1,241 +0,0 @@ -import React, { useEffect, useState } from "react"; -import { makeStyles } from "@mui/styles"; -import { useAccount } from "wagmi"; -import { - Hex, - encodeAbiParameters, - encodeFunctionData, - getFunctionSelector, - parseEther, - slice, -} from "viem"; -import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; -import { createSessionKeyManagerModule } from "@biconomy/account"; -import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { CONTRACT_CALL_SESSION_VALIDATION_MODULE } from "../../utils/chainConfig"; -import { getActionForErrorMessage } from "../../utils/error-utils"; -import { - configInfo as config, - showErrorMessage, - showSuccessMessage, -} from "../../utils"; -import { managerModuleAddr } from "../../utils/constants"; - -const CreateCustomSession: React.FC = () => { - const classes = useStyles(); - const { address } = useAccount(); - const { scwAddress, smartAccount } = useSmartAccountContext(); - const [loading, setLoading] = useState(false); - const [isSessionKeyModuleEnabled, setIsSessionKeyModuleEnabled] = - useState(false); - - useEffect(() => { - let checkSessionModuleEnabled = async () => { - if (!scwAddress || !smartAccount || !address) { - setIsSessionKeyModuleEnabled(false); - return; - } - try { - let biconomySmartAccount = smartAccount; - const sessionKeyManagerModuleAddr = managerModuleAddr; - // Checks if Session Key Manager module is enabled on the smart account. - // Before using session keys this module must be enabled. - // If not, createSession transaction will also enable this module along with storing session info on-chain. - const isEnabled = await biconomySmartAccount.isModuleEnabled( - sessionKeyManagerModuleAddr - ); - console.log("isSessionKeyModuleEnabled", isEnabled); - setIsSessionKeyModuleEnabled(isEnabled); - return; - } catch (err: any) { - console.error(err); - setLoading(false); - setIsSessionKeyModuleEnabled(false); - return; - } - }; - checkSessionModuleEnabled(); - }, [isSessionKeyModuleEnabled, scwAddress, smartAccount, address]); - - const createSession = async (enableSessionKeyModule: boolean) => { - if (!scwAddress || !smartAccount || !address) { - showErrorMessage("Please connect wallet first"); - return; - } - try { - let biconomySmartAccount = smartAccount; - const sessionKeyManagerModuleAddr = managerModuleAddr; - const ccSessionValidationModuleAddr = - CONTRACT_CALL_SESSION_VALIDATION_MODULE; - - // -----> setMerkle tree tx flow - // create dapp side session key - const sessionPKey = generatePrivateKey(); - const sessionSigner = privateKeyToAccount(sessionPKey); - const sessionKeyEOA = sessionSigner.address; - console.log("sessionKeyEOA", sessionKeyEOA); - - // Optional: JUST FOR DEMO: update local storage with session key - // If you have session key-pair on the client side you can keep using those without making part of any storage - window.localStorage.setItem("sessionPKey", sessionPKey); - - console.log("here it works "); - - // Create an instance of Session Key Manager module from modules package - // This module is responsible for below tasks/helpers: - // a. Maintain session leaf storage in defined storage client (Biconomy by default using browser local storage which works for front-end apps) - // b. Generate dummy signature for userOp estimations - // c. Provides helpers to sign userOpHash with session key in the right format and generate proof for particular leaf - const sessionManagerModule = await createSessionKeyManagerModule({ - moduleAddress: sessionKeyManagerModuleAddr, - smartAccountAddress: scwAddress, - }); - - console.log("ever here? "); - - // Cretae session key data - // Session key data is always corrsponding to the Session Validation Module being used - // It always requires the public address of the session key - // Rest of the details depends on the actual permissions - - const permission = [ - config.hyphenLP.address, - slice(getFunctionSelector("addTokenLiquidity(address,uint256)"), 0, 4), - ]; - - const sessionKeyData = encodeAbiParameters( - [ - { type: "address" }, - { - type: "tuple", - components: [{ type: "address" }, { type: "bytes4" }], - }, - ], - [sessionKeyEOA, [permission[0] as Hex, permission[1] as Hex]] - ); - - // Below helper gives you tx data to be used to make a call from Smart Account to enable session on-chain - // This transaction needs a user signature and for gas sponsorship or ERC20 paymaster can be used. - const sessionTxData = await sessionManagerModule.createSessionData([ - { - validUntil: 0, // 0 value means extremes - validAfter: 0, // 0 value means extremes - sessionValidationModule: ccSessionValidationModuleAddr, - sessionPublicKey: sessionKeyEOA, - sessionKeyData: sessionKeyData, - }, - // can optionally enable multiple leaves(sessions) altogether - ]); - console.log("sessionTxData", sessionTxData); - - // tx to set session key - const tx2 = { - to: sessionKeyManagerModuleAddr as Hex, // session manager module address - value: BigInt(0), - data: sessionTxData.data as Hex, - }; - - let transactionArray = []; - if (enableSessionKeyModule) { - // -----> enableModule session manager module - const tx1 = await biconomySmartAccount.getEnableModuleData( - sessionKeyManagerModuleAddr - ); - transactionArray.push({ - to: tx1.to as Hex, - value: BigInt(0), - data: tx1.data as Hex, - }); - } - transactionArray.push(tx2); - - const approveCallData = encodeFunctionData({ - abi: config.usdc.abi, - functionName: "approve", - args: [config.hyphenLP.address, parseEther("100", "gwei")], - }); - const tx3 = { - to: config.usdc.address as Hex, - value: BigInt(0), - data: approveCallData, - }; - transactionArray.push(tx3); - - // Building the user operation - // If you're going to use sponsorship paymaster details can be provided at this step - let userOpResponse = await smartAccount.sendTransaction(transactionArray); - console.log("userOpHash", userOpResponse); - const { transactionHash } = await userOpResponse.waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage("Session Created Successfully", transactionHash); - } catch (err: any) { - console.error(err); - setLoading(false); - const errorAction = getActionForErrorMessage(err.message); - showErrorMessage( - errorAction || err.message || "Error in sending the transaction" - ); - } - }; - - return ( -
-

- Use Cases {"->"} Session {"->"} Create Session -

- -

Create Session Flow

- - {isSessionKeyModuleEnabled ? ( -
-

- Session Key Manager Module is already enabled ✅. Click on the - button to create a new session. -

- -
- ) : ( -
-

- This is a single transaction to enable the sesion key manager module - and make a session active on-chain using Contract call (ABI) session - validation module. -

- -
- )} -
- ); -}; - -const useStyles = makeStyles(() => ({ - main: { - padding: "10px 40px", - color: "#EEEEEE", - }, - subTitle: { - color: "#FFB999", - fontSize: 36, - margin: 0, - }, - h3Title: { - color: "#e6e6e6", - }, -})); - -export default CreateCustomSession; diff --git a/src/components/Modules/ERC20TransferUsingSession.tsx b/src/components/Modules/ERC20TransferUsingSession.tsx deleted file mode 100644 index 4ff04db..0000000 --- a/src/components/Modules/ERC20TransferUsingSession.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import React, { useState } from "react"; -import { ethers } from "ethers"; -import { makeStyles } from "@mui/styles"; - -import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { - configInfo as config, - showSuccessMessage, - showErrorMessage, -} from "../../utils"; -import { - DEFAULT_ERC20_MODULE, - createSessionKeyManagerModule, -} from "@biconomy/account"; -import { EthersSigner } from "@biconomy/account"; -import { useAccount } from "wagmi"; -import { managerModuleAddr } from "../../utils/constants"; - -const ERC20Transfer: React.FC = () => { - const classes = useStyles(); - const { smartAccount, scwAddress } = useSmartAccountContext(); - const { address } = useAccount(); - const [loading, setLoading] = useState(false); - - const erc20Transfer = async () => { - if (!scwAddress || !smartAccount || !address) { - showErrorMessage("Please connect wallet first"); - return; - } - try { - setLoading(true); - let biconomySmartAccount = smartAccount; - const sessionKeyManagerModuleAddr = managerModuleAddr; - const erc20SessionValidationModuleAddr = DEFAULT_ERC20_MODULE; - - // get session key from local storage - const sessionKeyPrivKey = window.localStorage.getItem("sessionPKey"); - - if (!sessionKeyPrivKey) { - showErrorMessage("Session key not found"); - return; - } - const sessionSigner = new ethers.Wallet(sessionKeyPrivKey); - console.log("sessionSigner", sessionSigner); - - const newSigner = new EthersSigner(sessionSigner, "ethers"); - - // generate sessionManagerModule - const sessionManagerModule = await createSessionKeyManagerModule({ - moduleAddress: sessionKeyManagerModuleAddr, - smartAccountAddress: scwAddress, - }); - - // set active module to sessionManagerModule - // This time we will make use of enabled session hence transaction needs to via go through session manager module - // Hence it is set as runtime active module - biconomySmartAccount = - biconomySmartAccount.setActiveValidationModule(sessionManagerModule); - - const tokenContract = new ethers.Contract( - config.usdc.address, - config.usdc.abi, - sessionSigner - ); - let decimals = 18; - - try { - decimals = await tokenContract.decimals(); - } catch (error) { - throw new Error("invalid token address supplied"); - } - - // @ts-ignore - const { data } = await tokenContract.populateTransaction.transfer( - "0x42138576848E839827585A3539305774D36B9602", // receiver address // Has to be the same receiver for which session permissions are set - ethers.parseUnits("5".toString(), decimals) - ); - - // generate tx data to erc20 transfer - // NOTE: It can only be used for single transaction and not part of batch calldata - // If you want to make use of batch calldata then you need to use the session router module - const tx1 = { - to: config.usdc.address, //erc20 token address - data: data, - value: 0, - }; - - // send user operation - const userOpResponse = await biconomySmartAccount.sendTransaction( - tx1, - // below params are required for passing on this information to session key manager module to create padded signature - { - params: { - sessionSigner: newSigner, - sessionValidationModule: erc20SessionValidationModuleAddr, - }, - simulationType: "validation_and_execution", - } - ); - - console.log("userOpHash", userOpResponse); - const { transactionHash } = await userOpResponse.waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage(`ERC20 Transfer ${transactionHash}`, transactionHash); - setLoading(false); - } catch (err: any) { - console.error(err); - setLoading(false); - showErrorMessage(err.message || "Error in sending the transaction"); - } - }; - - return ( -
-

- Use Cases {"->"} Gasless {"->"} ERC20 Transfer -

- -

ERC20 Transfer via Session Key

- -

- This is an example to transfer ERC20 tokens makin use of enabled - session. -

- -
- ); -}; - -const useStyles = makeStyles(() => ({ - main: { - padding: "10px 40px", - color: "#EEEEEE", - }, - subTitle: { - color: "#FFB999", - fontSize: 36, - margin: 0, - }, - h3Title: { - color: "#e6e6e6", - }, -})); - -export default ERC20Transfer; diff --git a/src/components/Modules/HyphenLpUsingSession.tsx b/src/components/Modules/HyphenLpUsingSession.tsx deleted file mode 100644 index 40c1d44..0000000 --- a/src/components/Modules/HyphenLpUsingSession.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import React, { useState } from "react"; -import { ethers } from "ethers"; -import { makeStyles } from "@mui/styles"; - -import Button from "../Button"; -import { useSmartAccountContext } from "../../contexts/SmartAccountContext"; -import { - configInfo as config, - showSuccessMessage, - showErrorMessage, -} from "../../utils"; -import { createSessionKeyManagerModule } from "@biconomy/account"; -import { CONTRACT_CALL_SESSION_VALIDATION_MODULE } from "../../utils/chainConfig"; -import { EthersSigner } from "@biconomy/account"; -import { useAccount } from "wagmi"; -import { managerModuleAddr } from "../../utils/constants"; -import { parseUnits } from "viem"; - -const HyphenLpUsingSession: React.FC = () => { - const classes = useStyles(); - const { address } = useAccount(); - const { smartAccount, scwAddress } = useSmartAccountContext(); - const [loading, setLoading] = useState(false); - - const hyphenLpUsingSession = async () => { - if (!scwAddress || !smartAccount || !address) { - showErrorMessage("Please connect wallet first"); - return; - } - try { - setLoading(true); - let biconomySmartAccount = smartAccount; - const sessionKeyManagerModuleAddr = managerModuleAddr; - const ccSessionValidationModuleAddr = - CONTRACT_CALL_SESSION_VALIDATION_MODULE; - - // get session key from local storage - const sessionKeyPrivKey = window.localStorage.getItem("sessionPKey"); - - if (!sessionKeyPrivKey) { - showErrorMessage("Session key not found"); - return; - } - const sessionSigner = new ethers.Wallet(sessionKeyPrivKey); - console.log("sessionSigner", sessionSigner); - - const newSigner = new EthersSigner(sessionSigner, "ethers"); - - // generate sessionManagerModule - const sessionManagerModule = await createSessionKeyManagerModule({ - moduleAddress: sessionKeyManagerModuleAddr, - smartAccountAddress: scwAddress, - }); - - // set active module to sessionManagerModule - // This time we will make use of enabled session hence transaction needs to via go through session manager module - // Hence it is set as runtime active module - biconomySmartAccount = - biconomySmartAccount.setActiveValidationModule(sessionManagerModule); - - const hyphenContract = new ethers.Contract( - config.hyphenLP.address, - config.hyphenLP.abi, - sessionSigner - ); - - const addLiquidityData = hyphenContract.interface.encodeFunctionData( - "addTokenLiquidity", - [config.usdc.address, parseUnits("0.01", 6)] - ); // 1 USDC (amoy USDC has 6 decimals) - const tx1 = { - to: config.hyphenLP.address, - data: addLiquidityData, - value: 0, - }; - - // build user op - // with calldata to provide LP - let userOpResponse = await biconomySmartAccount.sendTransaction(tx1, { - params: { - sessionSigner: newSigner, - sessionValidationModule: ccSessionValidationModuleAddr, - }, - simulationType: "validation_and_execution", - }); - - console.log("userOpHash", userOpResponse); - const { transactionHash } = await userOpResponse.waitForTxHash(); - console.log("txHash", transactionHash); - showSuccessMessage(`LP Deposit ${transactionHash}`, transactionHash); - setLoading(false); - } catch (err: any) { - console.error(err); - setLoading(false); - showErrorMessage(err.message || "Error in sending the transaction"); - } - }; - - return ( -
-

- Use Cases {"->"} Gasless {"->"} Deposit into Hyphen Pool using session - key -

- -

- Deposit into Hyphen Pool via Session Key -

- -

- This is an example to Deposit into Hyphen Pool making use of enabled - session. Requires prior approval from smart account -

- -
- ); -}; - -const useStyles = makeStyles(() => ({ - main: { - padding: "10px 40px", - color: "#EEEEEE", - }, - subTitle: { - color: "#FFB999", - fontSize: 36, - margin: 0, - }, - h3Title: { - color: "#e6e6e6", - }, -})); - -export default HyphenLpUsingSession; diff --git a/src/components/Modules/UseABISVM.tsx b/src/components/Modules/UseABISVM.tsx deleted file mode 100644 index 426d9ee..0000000 --- a/src/components/Modules/UseABISVM.tsx +++ /dev/null @@ -1,110 +0,0 @@ -import React from "react"; -import { - PaymasterMode, - Session, - createSessionSmartAccountClient, -} from "@biconomy/account"; -import { toast } from "react-toastify"; -import "react-toastify/dist/ReactToastify.css"; -import { Hex, encodeFunctionData, parseAbi } from "viem"; -import Button from "../Button"; -import { configInfo } from "../../utils"; -import { polygonAmoy } from "viem/chains"; -import { bundlerUrl, paymasterApiKey } from "../../utils/chainConfig"; - -interface props { - smartAccountAddress: Hex; - address: string; -} - -const UseABISVM: React.FC = ({ smartAccountAddress, address }) => { - const sendUserOpWithData = async () => { - if (!address || !smartAccountAddress || !address) { - alert("Connect wallet first"); - return; - } - - try { - toast.info("Firing tx", { - position: "top-right", - autoClose: 15000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - theme: "dark", - }); - - const emulatedSmartAccount = await createSessionSmartAccountClient( - { - accountAddress: smartAccountAddress, // Set the account address on behalf of the user - bundlerUrl, - biconomyPaymasterApiKey: paymasterApiKey, - chainId: polygonAmoy.id, - }, - smartAccountAddress - ); - - const tx = { - to: configInfo.nft.address, - data: encodeFunctionData({ - abi: parseAbi(["function safeMint(address _to)"]), - functionName: "safeMint", - args: [smartAccountAddress as Hex], - }), - }; - - // build user op - let userOpResponse = await emulatedSmartAccount.sendTransaction(tx, { - paymasterServiceData: { - mode: PaymasterMode.SPONSORED, - }, - }); - console.log("userOpHash %o for Session Id %s", userOpResponse); - - const { receipt, success } = await userOpResponse.wait(1); - - const scanLink = `${polygonAmoy.blockExplorers.default.url}/tx/${receipt.transactionHash}`; - success && - toast.success( - - Success Click to view transaction - , - { - position: "top-right", - autoClose: 6000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - theme: "dark", - } - ); - } catch (err: any) { - console.error(err); - toast.error(err.message, { - position: "top-right", - autoClose: 6000, - hideProgressBar: false, - closeOnClick: true, - pauseOnHover: true, - draggable: true, - progress: undefined, - theme: "dark", - }); - } - }; - - return ( -