mirror of
https://github.com/getwax/bls-single-pool-dex.git
synced 2026-01-09 15:48:01 -05:00
Add dapp sponsored txs, modal, tidy up
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
"react-blockies": "^1.4.1",
|
||||
"react-css-theme-switcher": "^0.2.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-modal": "^3.15.1",
|
||||
"react-qr-reader": "^2.2.1",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "4.0.0",
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import { Button, Col, Menu, Row, List } from "antd";
|
||||
import "antd/dist/antd.css";
|
||||
import {
|
||||
useBalance,
|
||||
useContractLoader,
|
||||
useContractReader,
|
||||
useGasPrice,
|
||||
useOnBlock,
|
||||
} from "eth-hooks";
|
||||
import { useBalance, useContractLoader, useContractReader, useGasPrice, useOnBlock } from "eth-hooks";
|
||||
import { useExchangeEthPrice } from "eth-hooks/dapps/dex";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { Link, Route, Switch, useLocation } from "react-router-dom";
|
||||
import ReactModal from "react-modal";
|
||||
import "./App.css";
|
||||
import {
|
||||
Account,
|
||||
@@ -35,6 +30,7 @@ import { Transactor, Web3ModalSetup } from "./helpers";
|
||||
import { Home, ExampleUI, Hints, Subgraph } from "./views";
|
||||
import { useStaticJsonRPC, useProvider, useSigner, useAddress } from "./hooks";
|
||||
import { useEventListener } from "eth-hooks/events/useEventListener";
|
||||
import { sendTransaction } from "./helpers/transactionController";
|
||||
|
||||
const { ethers } = require("ethers");
|
||||
/*
|
||||
@@ -79,6 +75,8 @@ function App(props) {
|
||||
// reference './constants.js' for other networks
|
||||
const networkOptions = [initialNetwork.name, "mainnet", "rinkeby"];
|
||||
|
||||
const [transactions, setTransactions] = useState([]);
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [injectedProvider, setInjectedProvider] = useState();
|
||||
const [selectedNetwork, setSelectedNetwork] = useState(networkOptions[0]);
|
||||
const location = useLocation();
|
||||
@@ -92,7 +90,6 @@ function App(props) {
|
||||
const localProvider = useProvider(targetNetwork.rpcUrl);
|
||||
const mainnetProvider = useStaticJsonRPC(providers);
|
||||
|
||||
|
||||
const logoutOfWeb3Modal = async () => {
|
||||
await web3Modal.clearCachedProvider();
|
||||
if (injectedProvider && injectedProvider.provider && typeof injectedProvider.provider.disconnect == "function") {
|
||||
@@ -161,6 +158,22 @@ function App(props) {
|
||||
console.log("🏷 Resolved austingriffith.eth as:",addressFromENS)
|
||||
*/
|
||||
|
||||
const sendTransaction = async () => {
|
||||
if (transactions === []) {
|
||||
console.log("No transactions set");
|
||||
return;
|
||||
}
|
||||
|
||||
setIsModalOpen(false);
|
||||
|
||||
const result = await tx(transactions, price);
|
||||
console.log("RESULT: ", result);
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
const loadWeb3Modal = useCallback(async () => {
|
||||
const provider = await web3Modal.connect();
|
||||
setInjectedProvider(new ethers.providers.Web3Provider(provider));
|
||||
@@ -240,6 +253,25 @@ function App(props) {
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
|
||||
<ReactModal
|
||||
isOpen={isModalOpen}
|
||||
style={{
|
||||
content: {
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
right: "auto",
|
||||
bottom: "auto",
|
||||
marginRight: "-50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
},
|
||||
}}
|
||||
ariaHideApp={false}
|
||||
>
|
||||
<p>Are you sure you want to initiate a swap?</p>
|
||||
<button onClick={closeModal}>Cancel</button>
|
||||
<button onClick={() => sendTransaction()}>Confirm</button>
|
||||
</ReactModal>
|
||||
|
||||
<Switch>
|
||||
<Route exact path="/">
|
||||
{/* pass in any web3 props to this Home component. For example, yourLocalBalance */}
|
||||
@@ -254,10 +286,11 @@ function App(props) {
|
||||
readContracts={readContracts} //this is causing issues
|
||||
contractConfig={contractConfig}
|
||||
signer={userSigner}
|
||||
price={price}
|
||||
setIsModalOpen={setIsModalOpen}
|
||||
setTransactions={setTransactions}
|
||||
/>
|
||||
// ""
|
||||
) : (
|
||||
// ""
|
||||
""
|
||||
)}
|
||||
{/* TODO: The DEX.jsx file actually logs a bunch of the results so we think that instead of creating completely new event components (or whatever), we would figure out how to work with the txs that are happening as a result of EthersJS calling the respective functions in DEX.jsx. 😵 Lines 321-335 are an example of attempting to place emitted events on the front-page UI. It is not working though for now! */}
|
||||
|
||||
@@ -12,28 +12,36 @@ import deployedContracts from "./../contracts/hardhat_contracts.json";
|
||||
const contractName = "DEX";
|
||||
const tokenName = "Balloons";
|
||||
|
||||
export default function Dex(props) {
|
||||
export default function Dex({
|
||||
tx,
|
||||
writeContracts,
|
||||
localProvider,
|
||||
mainnetProvider,
|
||||
blockExplorer,
|
||||
address,
|
||||
readContracts,
|
||||
contractConfig,
|
||||
signer,
|
||||
setIsModalOpen,
|
||||
setTransactions,
|
||||
}) {
|
||||
let display = [];
|
||||
|
||||
const [values, setValues] = useState({});
|
||||
const tx = props.tx;
|
||||
const price = props.price;
|
||||
|
||||
const writeContracts = props.writeContracts;
|
||||
const contractAddress = readContracts[contractName].address;
|
||||
const tokenAddress = readContracts[tokenName].address;
|
||||
const contractBalance = useBalance(localProvider, contractAddress);
|
||||
|
||||
const contractAddress = props.readContracts[contractName].address;
|
||||
const tokenAddress = props.readContracts[tokenName].address;
|
||||
const contractBalance = useBalance(props.localProvider, contractAddress);
|
||||
|
||||
const tokenBalance = useTokenBalance(props.readContracts[tokenName], contractAddress, props.localProvider);
|
||||
const tokenBalance = useTokenBalance(readContracts[tokenName], contractAddress, localProvider);
|
||||
const tokenBalanceFloat = parseFloat(ethers.utils.formatEther(tokenBalance));
|
||||
const ethBalanceFloat = parseFloat(ethers.utils.formatEther(contractBalance));
|
||||
const liquidity = useContractReader(props.readContracts, contractName, "liquidity", [props.address]);
|
||||
const liquidity = useContractReader(readContracts, contractName, "liquidity", [address]);
|
||||
|
||||
// Contract addresses and ABIs
|
||||
const dexAddress = props.readContracts[contractName].address;
|
||||
const dexAddress = readContracts[contractName].address;
|
||||
const dexAbi = deployedContracts[421613].arbitrumGoerli.contracts.DEX.abi;
|
||||
const balloonAddress = props.readContracts[tokenName].address;
|
||||
const balloonAddress = readContracts[tokenName].address;
|
||||
const balloonAbi = deployedContracts[421613].arbitrumGoerli.contracts.Balloons.abi;
|
||||
|
||||
const rowForm = (title, icon, onClick) => {
|
||||
@@ -71,17 +79,17 @@ export default function Dex(props) {
|
||||
);
|
||||
};
|
||||
|
||||
if (props.readContracts && props.readContracts[contractName]) {
|
||||
if (readContracts && readContracts[contractName]) {
|
||||
display.push(
|
||||
<div>
|
||||
{/* {rowForm("ethToToken", "💸", async value => {
|
||||
let valueInEther = ethers.utils.parseEther("" + value);
|
||||
{rowForm("ethToToken", "💸", async value => {
|
||||
const valueInEther = ethers.utils.parseEther("" + value);
|
||||
const DexContractInstance = new ethers.Contract(dexAddress, dexAbi);
|
||||
const encodedEthToTokenFunction = DexContractInstance.interface.encodeFunctionData("ethToToken", [
|
||||
props.address,
|
||||
address,
|
||||
]);
|
||||
|
||||
const transaction = [
|
||||
const transactions = [
|
||||
{
|
||||
value: valueInEther,
|
||||
to: dexAddress,
|
||||
@@ -90,12 +98,12 @@ export default function Dex(props) {
|
||||
},
|
||||
];
|
||||
|
||||
let swapEthToTokenResult = await tx(transaction);
|
||||
console.log("swapEthToTokenResult:", swapEthToTokenResult);
|
||||
setTransactions(transactions);
|
||||
setIsModalOpen(true);
|
||||
})}
|
||||
|
||||
{rowForm("tokenToEth", "🔏", async value => {
|
||||
let valueInEther = ethers.utils.parseEther("" + value);
|
||||
const valueInEther = ethers.utils.parseEther("" + value);
|
||||
const BalloonContractInstance = new ethers.Contract(balloonAddress, balloonAbi);
|
||||
const encodedApproveFunction = BalloonContractInstance.interface.encodeFunctionData("approve", [
|
||||
dexAddress,
|
||||
@@ -120,61 +128,8 @@ export default function Dex(props) {
|
||||
},
|
||||
];
|
||||
|
||||
let result = await tx(transactions);
|
||||
result = await result;
|
||||
console.log("Approve and swap transaction result:", result);
|
||||
})} */}
|
||||
|
||||
{/* <Divider>dApp Sponsored Transactions</Divider> */}
|
||||
|
||||
{rowForm("ethToToken", "💸", async value => {
|
||||
let valueInEther = ethers.utils.parseEther("" + value);
|
||||
const DexContractInstance = new ethers.Contract(dexAddress, dexAbi);
|
||||
const encodedEthToTokenFunction = DexContractInstance.interface.encodeFunctionData("ethToToken", [
|
||||
props.address,
|
||||
]);
|
||||
|
||||
const transaction = [
|
||||
{
|
||||
value: valueInEther,
|
||||
to: dexAddress,
|
||||
data: encodedEthToTokenFunction,
|
||||
gasLimit: 200000,
|
||||
},
|
||||
];
|
||||
|
||||
const swapEthToTokenResult = await tx(transaction, true, price);
|
||||
console.log("swapEthToTokenResult:", swapEthToTokenResult);
|
||||
})}
|
||||
|
||||
{rowForm("tokenToEth", "🔏", async value => {
|
||||
let valueInEther = ethers.utils.parseEther("" + value);
|
||||
const BalloonContractInstance = new ethers.Contract(balloonAddress, balloonAbi);
|
||||
const encodedApproveFunction = BalloonContractInstance.interface.encodeFunctionData("approve", [
|
||||
dexAddress,
|
||||
valueInEther,
|
||||
]);
|
||||
|
||||
const DexContractInstance = new ethers.Contract(dexAddress, dexAbi);
|
||||
const encodedtokenToEthFunction = DexContractInstance.interface.encodeFunctionData("tokenToEth", [
|
||||
valueInEther,
|
||||
]);
|
||||
|
||||
const transaction = [
|
||||
{
|
||||
to: balloonAddress,
|
||||
data: encodedApproveFunction,
|
||||
gasLimit: 200000,
|
||||
},
|
||||
{
|
||||
to: dexAddress,
|
||||
data: encodedtokenToEthFunction,
|
||||
gasLimit: 200000,
|
||||
},
|
||||
];
|
||||
|
||||
const swapTokenToEthResult = await tx(transaction, true, price);
|
||||
console.log("Approve and swap transaction result:", swapTokenToEthResult);
|
||||
setTransactions(transactions);
|
||||
setIsModalOpen(true);
|
||||
})}
|
||||
|
||||
<Divider> Liquidity ({liquidity ? ethers.utils.formatEther(liquidity) : "none"}):</Divider>
|
||||
@@ -229,7 +184,7 @@ export default function Dex(props) {
|
||||
<Address value={contractAddress} />
|
||||
<div style={{ float: "right", fontSize: 24 }}>
|
||||
{parseFloat(ethers.utils.formatEther(contractBalance)).toFixed(4)} ⚖️
|
||||
<TokenBalance name={tokenName} img={"🎈"} address={contractAddress} contracts={props.readContracts} />
|
||||
<TokenBalance name={tokenName} img={"🎈"} address={contractAddress} contracts={readContracts} />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -241,12 +196,12 @@ export default function Dex(props) {
|
||||
<Row span={12}>
|
||||
<Contract
|
||||
name="Balloons"
|
||||
signer={props.signer}
|
||||
provider={props.localProvider}
|
||||
signer={signer}
|
||||
provider={localProvider}
|
||||
show={["balanceOf", "approve"]}
|
||||
address={props.address}
|
||||
blockExplorer={props.blockExplorer}
|
||||
contractConfig={props.contractConfig}
|
||||
address={address}
|
||||
blockExplorer={blockExplorer}
|
||||
contractConfig={contractConfig}
|
||||
/>
|
||||
</Row>
|
||||
</Col>
|
||||
|
||||
12
packages/react-app/src/constants.js
vendored
12
packages/react-app/src/constants.js
vendored
@@ -18,13 +18,7 @@ export const NETWORKS = {
|
||||
rpcUrl: "http://localhost:8545",
|
||||
verificationGateway: "0x3C17E9cF70B774bCf32C66C8aB83D19661Fc27E2",
|
||||
aggregator: "http://localhost:3000",
|
||||
},
|
||||
mainnet: {
|
||||
name: "mainnet",
|
||||
color: "#ff8b9e",
|
||||
chainId: 1,
|
||||
rpcUrl: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}`,
|
||||
blockExplorer: "https://etherscan.io/",
|
||||
proxyAggregator: "http://localhost:3501",
|
||||
},
|
||||
arbitrumGoerli: {
|
||||
name: "arbitrumGoerli",
|
||||
@@ -33,8 +27,8 @@ export const NETWORKS = {
|
||||
blockExplorer: "https://goerli-rollup-explorer.arbitrum.io/",
|
||||
rpcUrl: "https://goerli-rollup.arbitrum.io/rpc",
|
||||
verificationGateway: "0xAf96d6e0817Ff8658f0E2a39b641920fA7fF0957",
|
||||
// aggregator: "https://arbitrum-goerli.blswallet.org",
|
||||
aggregator: "http://localhost:3000",
|
||||
aggregator: "https://arbitrum-goerli-paid.blswallet.org",
|
||||
proxyAggregator: "https://arbitrum-goerli-dex-proxy.blswallet.org/",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
4
packages/react-app/src/helpers/Transactor.js
vendored
4
packages/react-app/src/helpers/Transactor.js
vendored
@@ -16,7 +16,7 @@ const DEBUG = true;
|
||||
export default function Transactor(providerOrSigner, gasPrice, etherscan) {
|
||||
if (typeof providerOrSigner !== "undefined") {
|
||||
// eslint-disable-next-line consistent-return
|
||||
return async (tx, isSponsored, price, callback) => {
|
||||
return async (tx, price, callback) => {
|
||||
let signer;
|
||||
let network;
|
||||
let provider;
|
||||
@@ -69,7 +69,7 @@ export default function Transactor(providerOrSigner, gasPrice, etherscan) {
|
||||
}
|
||||
if (DEBUG) console.log("RUNNING TX", tx);
|
||||
|
||||
result = await sendTransaction(provider, tx, isSponsored);
|
||||
result = await sendTransaction(provider, tx);
|
||||
const gasSavedInDollars = "$" + (gasSavings.paymentAmount * price).toFixed(7);
|
||||
|
||||
let retries = 0;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"paymentAmount": "0.000000674914899998"
|
||||
"paymentAmount": "0.000000691033199998"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Aggregator, BlsWalletWrapper } from "bls-wallet-clients";
|
||||
import { NETWORKS } from "../constants";
|
||||
|
||||
export const sendTransaction = async (provider, params, isSponsored = false) => {
|
||||
export const sendTransaction = async (provider, params) => {
|
||||
const network = NETWORKS.arbitrumGoerli;
|
||||
|
||||
const privateKey = localStorage.getItem("privateKey");
|
||||
@@ -20,10 +20,7 @@ export const sendTransaction = async (provider, params, isSponsored = false) =>
|
||||
actions,
|
||||
});
|
||||
|
||||
const proxyAggregator = "http://localhost:3501";
|
||||
const aggregatorUrl = isSponsored ? proxyAggregator : network.aggregator;
|
||||
|
||||
const aggregator = new Aggregator(aggregatorUrl);
|
||||
const aggregator = new Aggregator(network.proxyAggregator);
|
||||
const result = await aggregator.add(bundle);
|
||||
|
||||
if ("failures" in result) {
|
||||
|
||||
20
yarn.lock
20
yarn.lock
@@ -10398,6 +10398,11 @@ execa@^4.0.0:
|
||||
signal-exit "^3.0.2"
|
||||
strip-final-newline "^2.0.0"
|
||||
|
||||
exenv@^1.2.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
|
||||
integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==
|
||||
|
||||
exit-on-epipe@~1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
|
||||
@@ -18866,6 +18871,21 @@ react-is@^17.0.1:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
|
||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||
|
||||
react-lifecycles-compat@^3.0.0:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-modal@^3.15.1:
|
||||
version "3.15.1"
|
||||
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.15.1.tgz#950ce67bfef80971182dd0ed38f2d9b1a681288b"
|
||||
integrity sha512-duB9bxOaYg7Zt6TMFldIFxQRtSP+Dg3F1ZX3FXxSUn+3tZZ/9JCgeAQKDg7rhZSAqopq8TFRw3yIbnx77gyFTw==
|
||||
dependencies:
|
||||
exenv "^1.2.0"
|
||||
prop-types "^15.7.2"
|
||||
react-lifecycles-compat "^3.0.0"
|
||||
warning "^4.0.3"
|
||||
|
||||
react-qr-reader@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-qr-reader/-/react-qr-reader-2.2.1.tgz#dc89046d1c1a1da837a683dd970de5926817d55b"
|
||||
|
||||
Reference in New Issue
Block a user