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

[issue-209] Feature - Enable users to pay from a multi sig #211

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/react-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
"@ant-design/icons": "^4.2.2",
"@apollo/react-hooks": "^4.0.0",
"@craco/craco": "^6.3.0",
"@gnosis.pm/safe-apps-react-sdk": "^4.0.8",
"@gnosis.pm/safe-apps-sdk": "^6.1.1",
"@gnosis.pm/safe-apps-web3modal": "^6.0.1",
"@portis/web3": "^4.0.5",
"@ramp-network/ramp-instant-sdk": "^2.2.0",
"@testing-library/jest-dom": "^5.11.4",
Expand Down
1 change: 1 addition & 0 deletions packages/react-app/public/CORS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*
5 changes: 3 additions & 2 deletions packages/react-app/public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"short_name": "🏗 Scaffold-Eth App",
"short_name": "Tip party",
"start_url": ".",
"name": "🏗 Scaffold-Eth App",
"name": "Tip party",
"iconPath": "favicon.ico",
"icons": [
{
"src": "favicon.ico",
Expand Down
89 changes: 6 additions & 83 deletions packages/react-app/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,17 @@ import { Alert, Button, Menu, Select, Space, Switch as AntdSwitch } from "antd";
import "antd/dist/antd.css";
import React, { useCallback, useEffect, useState } from "react";
import { BrowserRouter, Link, Route, Switch } from "react-router-dom";
import Web3Modal from "web3modal";
import "./App.css";
import { Account, Contract } from "./components";
import { INFURA_ID, NETWORK, NETWORKS } from "./constants";
import { Transactor, Address as AddressHelper } from "./helpers";
import { NETWORK, NETWORKS } from "./constants";
import { Transactor, Address as AddressHelper, Web3ModalSetup } from "./helpers";
import { useBalance, useContractLoader, useExchangePrice, useGasPrice, useOnBlock, useUserSigner } from "./hooks";
import { Rooms, Home } from "./views";
// Wallets for wallet connect
import Portis from "@portis/web3";
import Fortmatic from "fortmatic";
import Authereum from "authereum";
const { ethers } = require("ethers");

// 😬 Sorry for all the console logging
const DEBUG = true;
const DEBUG = false;
const NETWORKCHECK = true;

// Add more networks as the dapp expands to more networks
Expand Down Expand Up @@ -65,85 +61,11 @@ const localProvider = new ethers.providers.StaticJsonRpcProvider(localProviderUr
// 🔭 block explorer URL
const blockExplorer = targetNetwork.blockExplorer;

// Coinbase walletLink init
const walletLink = new WalletLink({
appName: "coinbase",
});

// WalletLink provider
const walletLinkProvider = walletLink.makeWeb3Provider(
"https://eth-mainnet.alchemyapi.io/v2/qCdzfF9UqXcJYIle-Ff-BN0MII8LjLQs",
1,
);

// Portis ID: 6255fb2b-58c8-433b-a2c9-62098c05ddc9
/*
Web3 modal helps us "connect" external wallets:
*/
const web3Modal = new Web3Modal({
network: "mainnet", // Optional. If using WalletConnect on xDai, change network to "xdai" and add RPC info below for xDai chain.
cacheProvider: true, // optional
theme: "light", // optional. Change to "dark" for a dark theme.
providerOptions: {
walletconnect: {
package: WalletConnectProvider, // required
options: {
bridge: "https://polygon.bridge.walletconnect.org",
infuraId: INFURA_ID,
rpc: {
1: "https://eth-mainnet.alchemyapi.io/v2/qCdzfF9UqXcJYIle-Ff-BN0MII8LjLQs", // mainnet // For more WalletConnect providers: https://docs.walletconnect.org/quick-start/dapps/web3-provider#required
42: `https://kovan.infura.io/v3/${INFURA_ID}`,
100: "https://dai.poa.network", // xDai
},
},
},
portis: {
display: {
logo: "https://user-images.githubusercontent.com/9419140/128913641-d025bc0c-e059-42de-a57b-422f196867ce.png",
name: "Portis",
description: "Connect to Portis App",
},
package: Portis,
options: {
id: "6255fb2b-58c8-433b-a2c9-62098c05ddc9",
},
},
fortmatic: {
package: Fortmatic, // required
options: {
key: "pk_live_5A7C91B2FC585A17", // required
},
},
// torus: {
// package: Torus,
// options: {
// networkParams: {
// host: "https://localhost:8545", // optional
// chainId: 1337, // optional
// networkId: 1337 // optional
// },
// config: {
// buildEnv: "development" // optional
// },
// },
// },
"custom-walletlink": {
display: {
logo: "https://play-lh.googleusercontent.com/PjoJoG27miSglVBXoXrxBSLveV6e3EeBPpNY55aiUUBM9Q1RCETKCOqdOkX2ZydqVf0",
name: "Coinbase",
description: "Connect to Coinbase Wallet (not Coinbase App)",
},
package: walletLinkProvider,
connector: async (provider, options) => {
await provider.enable();
return provider;
},
},
authereum: {
package: Authereum, // required
},
},
});
const web3Modal = Web3ModalSetup(targetNetwork);

function App(props) {
const mainnetProvider =
Expand Down Expand Up @@ -412,7 +334,7 @@ function App(props) {
);

const loadWeb3Modal = useCallback(async () => {
const provider = await web3Modal.connect();
const provider = await web3Modal.requestProvider();
setInjectedProvider(new ethers.providers.Web3Provider(provider));

provider.on("chainChanged", chainId => {
Expand All @@ -436,6 +358,7 @@ function App(props) {
if (web3Modal.cachedProvider) {
loadWeb3Modal();
}
console.log("Checking URLS: ", injectedProvider);
}, [loadWeb3Modal]);

const [route, setRoute] = useState();
Expand Down
2 changes: 1 addition & 1 deletion packages/react-app/src/components/Account/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default function Account({

const modalButtons = [];
if (web3Modal) {
if (web3Modal.cachedProvider) {
if (web3Modal?.cachedProvider || web3Modal?.provider?.safe) {
modalButtons.push(
<div key="first">
{isValidAddress(address) ? (
Expand Down
7 changes: 5 additions & 2 deletions packages/react-app/src/components/PayButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,10 @@ export default function PayButton({
const payParams = { token, ...tokenInfo[token] };
if (isETH()) {
setStatus(4);
console.log("pay happening ", status);
await ethPayHandler();
setStatus(3);
console.log("end of pay happening ", status);
} else {
if (status === 1) {
await approveTokenAllowance();
Expand All @@ -103,7 +105,9 @@ export default function PayButton({

useEffect(() => {
if (isETH()) {
console.log("refresh happening ", status);
refreshETH();
console.log("after refresh happening ", status);
} else if (tokenInfo[token]) {
const adjustedAmount = ethers.utils.parseUnits(amount || "0", tokenInfo[token].decimals);
const hasEnoughAllowance = tokenInfo[token].allowance.lt(adjustedAmount);
Expand All @@ -113,6 +117,7 @@ export default function PayButton({
}, [amount]);

useEffect(() => {
console.log("check it out ", status, renderButtonText());
if (!isETH()) {
setStatus(0);
refreshTokenDetails();
Expand All @@ -123,7 +128,6 @@ export default function PayButton({

const renderButtonText = () => {
let text = "Loading...";

switch (status) {
case 1:
text = `Approve ${appName} to transfer ${token}`;
Expand All @@ -144,7 +148,6 @@ export default function PayButton({
text = "Loading...";
break;
}

return text;
};

Expand Down
2 changes: 1 addition & 1 deletion packages/react-app/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ export const NETWORKS = {
name: "rinkeby",
color: "#e0d068",
chainId: 4,
rpcUrl: `https://rinkeby.infura.io/v3/${INFURA_ID}`,
rpcUrl: "https://eth-rinkeby.alchemyapi.io/v2/0meerwuMivq7wbFsUFTcirfUVM79w1fW",
faucet: "https://faucet.rinkeby.io/",
blockExplorer: "https://rinkeby.etherscan.io/",
nativeCurrency: "ETH",
Expand Down
81 changes: 53 additions & 28 deletions packages/react-app/src/helpers/Transactor.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { notification } from "antd";
import Notify from "bnc-notify";
import { BLOCKNATIVE_DAPPID } from "../constants";
import { useSafeAppsSDK } from "@gnosis.pm/safe-apps-react-sdk";

const { ethers } = require("ethers");

Expand All @@ -12,9 +13,14 @@ const callbacks = {};
const DEBUG = true;

export default function Transactor(providerOrSigner, gasPrice, etherscan) {
const { sdk, safe } = useSafeAppsSDK();

if (typeof providerOrSigner !== "undefined") {
// eslint-disable-next-line consistent-return
return async (tx, callback) => {
console.log("Transactor tx ", tx);
console.log("Transactor callback ", callback);
console.log("providerOrSigner callback ", providerOrSigner);
let signer;
let network;
let provider;
Expand All @@ -29,26 +35,23 @@ export default function Transactor(providerOrSigner, gasPrice, etherscan) {
}

console.log("network", network);

var options = null;
var notify = null;
if (navigator.onLine) {
options = {
dappId: BLOCKNATIVE_DAPPID, // GET YOUR OWN KEY AT https://account.blocknative.com
system: "ethereum",
networkId: network.chainId,
// darkMode: Boolean, // (default: false)
transactionHandler: txInformation => {
if (DEBUG) console.log("HANDLE TX", txInformation);
const possibleFunction = callbacks[txInformation.transaction.hash];
if (typeof possibleFunction === "function") {
possibleFunction(txInformation.transaction);
}
},
};
options = {
dappId: BLOCKNATIVE_DAPPID, // GET YOUR OWN KEY AT https://account.blocknative.com
system: "ethereum",
networkId: network.chainId,
// darkMode: Boolean, // (default: false)
transactionHandler: txInformation => {
if (DEBUG) console.log("HANDLE TX", txInformation);
const possibleFunction = callbacks[txInformation.transaction.hash];
if (typeof possibleFunction === "function") {
possibleFunction(txInformation.transaction);
}
},
};

notify = Notify(options);
}
notify = Notify(options);

let etherscanNetwork = "";
if (network.name && network.chainId > 1) {
Expand All @@ -62,26 +65,48 @@ export default function Transactor(providerOrSigner, gasPrice, etherscan) {

try {
let result;
if (tx instanceof Promise) {
if (DEBUG) console.log("AWAITING TX", tx);
if (providerOrSigner?.provider?.provider?.wc?._peerMeta?.name === "Gnosis Safe Multisig") {
const accountData = providerOrSigner?.provider?.wc?._peerMeta?.accounts[0];
console.log("GNOSIS Safe TX", tx, callback);
result = await tx;
console.log("result", result);
// Returns a hash to identify the Safe transaction
const safeTxHash = await sdk.txs.send({
txs: [
{
to: accountData,
value: "0x0",
data: result,
},
],
});
console.log("safeTxHash ", safeTxHash);
const safeTx = await sdk.txs.getBySafeTxHash(safeTxHash);
console.log("safeTx ", safeTx);
} else {
if (!tx.gasPrice) {
tx.gasPrice = gasPrice || ethers.utils.parseUnits("4.1", "gwei");
}
if (!tx.gasLimit) {
tx.gasLimit = ethers.utils.hexlify(120000);
if (tx instanceof Promise) {
if (DEBUG) console.log("AWAITING TX", tx);
result = await tx;
console.log("callback result ", result);
} else {
if (!tx.gasPrice) {
tx.gasPrice = gasPrice || ethers.utils.parseUnits("4.1", "gwei");
}
if (!tx.gasLimit) {
tx.gasLimit = ethers.utils.hexlify(120000);
}
if (DEBUG) console.log("RUNNING TX", tx);
result = await signer.sendTransaction(tx);
}
if (DEBUG) console.log("RUNNING TX", tx);
result = await signer.sendTransaction(tx);
}

if (DEBUG) console.log("RESULT:", result);
// console.log("Notify", notify);

if (callback) {
callbacks[result.hash] = callback;
}

console.log("callback result view callbacks ", callbacks);
// if it is a valid Notify.js network, use that, if not, just send a default notification
if (notify && [1, 3, 4, 5, 42, 100].indexOf(network.chainId) >= 0) {
const { emitter } = notify.hash(result.hash);
Expand Down Expand Up @@ -117,6 +142,7 @@ export default function Transactor(providerOrSigner, gasPrice, etherscan) {

return result;
} catch (e) {
console.log("main error ", e);
if (DEBUG) console.log(e);
// Accounts for Metamask and default signer on all networks
let message =
Expand All @@ -127,7 +153,6 @@ export default function Transactor(providerOrSigner, gasPrice, etherscan) {
: e.data
? e.data
: JSON.stringify(e);

if (!e.error && e.message) {
message = e.message;
}
Expand Down
Loading