From d12f977c60b4206301f7cb78a92e3505f588757c Mon Sep 17 00:00:00 2001 From: Jack Gilcrest Date: Sun, 20 Mar 2022 11:04:47 -0400 Subject: [PATCH] debugged biconomy --- src/contexts/WalletContext.tsx | 51 ++-- src/views/BuildBoardView/index.tsx | 19 +- src/views/Game/index.tsx | 18 +- src/web3/BattleshipGame.json | 402 +++++++++++++++++++++++++++++ src/web3/constants.ts | 13 +- src/web3/erc2771.ts | 74 +++--- 6 files changed, 498 insertions(+), 79 deletions(-) create mode 100644 src/web3/BattleshipGame.json diff --git a/src/contexts/WalletContext.tsx b/src/contexts/WalletContext.tsx index 02017d1..6f06d70 100644 --- a/src/contexts/WalletContext.tsx +++ b/src/contexts/WalletContext.tsx @@ -14,16 +14,14 @@ import { DEFAULT_NETWORK, NETWORK_NAMES } from 'web3/constants'; import { switchChainOnMetaMask } from 'web3/metamask'; export type WalletContextType = { - rawProvider: providers.Provider | null | undefined; - fallbackProvider: providers.Web3Provider | null | undefined; // ethers provider - provider: providers.Web3Provider | null | undefined; // biconomy provider + provider: providers.Web3Provider | null | undefined; // ethers provider biconomy: any; // biconomy object - chainId: number | null | undefined; - address: string | null | undefined; + chainId: number | null | undefined; // network id + address: string | null | undefined; // signer public key // authToken: string | null | undefined; - ensName: string | null | undefined; - connectWallet: () => Promise; - disconnect: () => void; + ensName: string | null | undefined; // public key ENS resolution + connectWallet: () => Promise; // connect an eip1193 object + disconnect: () => void; // disconnect an eip1193 object isConnecting: boolean; isConnected: boolean; isMetamask: boolean; @@ -36,16 +34,12 @@ const web3Modal = new Web3Modal({ }); export const WalletContext = createContext({ - rawProvider: null, - fallbackProvider: null, provider: null, biconomy: null, chainId: null, address: null, ensName: null, - connectWallet: async () => { - return; - }, + connectWallet: async () => { return }, disconnect: () => undefined, isConnecting: true, isConnected: false, @@ -53,8 +47,6 @@ export const WalletContext = createContext({ }); type WalletStateType = { - rawProvider?: providers.Provider | null; - fallbackProvider?: providers.Web3Provider | null; provider?: providers.Web3Provider | null; biconomy?: any | null; chainId?: number | null; @@ -70,8 +62,6 @@ const isMetamaskProvider = ( export const WalletProvider: React.FC = ({ children }) => { const [ { - rawProvider, - fallbackProvider, provider, biconomy, chainId, @@ -107,8 +97,13 @@ export const WalletProvider: React.FC = ({ children }) => { [disconnect] ); - const setWalletProvider = useCallback(async (prov) => { - const ethersProvider = new providers.Web3Provider(prov); + /** + * Set the EIP-1193 Compliant web3 Provider with Signer in context + * + * @param prov - the eip1193 object being set + */ + const setWalletProvider = useCallback(async (_provider) => { + const ethersProvider = new providers.Web3Provider(_provider); await ethersProvider.ready; const providerNetwork = await ethersProvider.getNetwork(); let network = Number(providerNetwork.chainId); @@ -121,11 +116,9 @@ export const WalletProvider: React.FC = ({ children }) => { // toast.error(errorMsg); throw new Error(errorMsg); } - network = DEFAULT_NETWORK; } - console.log('PROV: ', prov); - const biconomy = new window.Biconomy(prov, { + const biconomy = new window.Biconomy(_provider, { strictMode: true, apiKey: process.env.REACT_APP_BICONOMY_API, debug: true @@ -137,6 +130,7 @@ export const WalletProvider: React.FC = ({ children }) => { .onEvent(biconomy.ERROR, (err: Error) => reject(err)); }); } catch (err) { + // TODO: handle switch to non-metatransactions gracefully throw new Error('Biconomy failed to connect'); } // TODO: Move to better location @@ -146,9 +140,7 @@ export const WalletProvider: React.FC = ({ children }) => { ? await ethersProvider.lookupAddress(signerAddress) : ''; setWalletState({ - rawProvider: prov, - fallbackProvider: ethersProvider, - provider: new ethers.providers.Web3Provider(biconomy), + provider: ethersProvider, biconomy, chainId: network, address: signerAddress.toLowerCase(), @@ -160,10 +152,9 @@ export const WalletProvider: React.FC = ({ children }) => { try { setConnecting(true); const modalProvider = await (async () => { - const choosenProvider = await web3Modal.connect(); - await setWalletProvider(choosenProvider); - - return choosenProvider; + const chosenProvider = await web3Modal.connect(); + await setWalletProvider(chosenProvider); + return chosenProvider; })(); if (modalProvider.isMetaMask) addMetaMaskListeners(modalProvider); } catch (web3Error) { @@ -189,8 +180,6 @@ export const WalletProvider: React.FC = ({ children }) => { return ( => { - const provider = biconomy.getEthersProvider(); - const sender = provider.getSigner(); - const contractAddress = BATTLESHIP_GAME_CONTRACT[provider.provider.networkId]; - const instance = new Contract(contractAddress, ABI, sender); - const { data } = await instance.populateTransaction[name](...args); - const gasLimit = await provider.estimateGas({ - to: contractAddress, - from: await sender.getAddress(), - data: data as BytesLike - }) - const params = { - to: contractAddress, - from: await sender.getAddress(), - data: data as BytesLike, - gasLimit, - signatureType: "EIP712_SIGN" - } +export const metatransaction = async ({ provider, biconomy, functionName, args }: IMetaTx): + Promise => { + + // get biconomy compatible sender/ signer + const from = await provider.getSigner().getAddress(); // signer in eip1193 provider + const sender = biconomy.getSignerByAddress(from); + + // create instance of contract to use + const chainId = (await provider.getNetwork()).chainId; + const to = BATTLESHIP_GAME_CONTRACT[chainId]; // BattleshipGame.sol address + const instance = new Contract(to, ABI, sender); + + // define transaction parameters + const { data } = await instance.populateTransaction[functionName](...args); + const params = { to, from, data, signatureType: "EIP712_SIGN" }; + + // send transaction + const _provider = new providers.Web3Provider(biconomy); + const hash = await _provider.send('eth_sendTransaction', [params]); + const blockNum = await provider._getInternalBlockNumber(100 + 2 * provider.pollingInterval); - let tx = await provider.send("eth_sendTransaction", [params]) - provider.once(tx, (transaction: any) => { - console.log('xxx', tx) - console.log('xxxy', transaction) - return tx; - }) + // wait for transaction result + if (typeof hash === 'string') { + const res = await poll(async () => { + const tx = await provider.getTransaction(hash); + if (tx === null) return undefined; + else return provider._wrapTransaction(tx, hash, blockNum); + }, { oncePoll: provider }); + if (!res) throw new Error('Unable to locate tx response from metatransaction relay') + return res; + } else return hash; } \ No newline at end of file