From 1b991b134e82f0437d1c68d864ceb286bd4e1085 Mon Sep 17 00:00:00 2001 From: Manank Patni Date: Sun, 2 Jul 2023 09:04:58 +0530 Subject: [PATCH 1/7] Add api call to deployer Signed-off-by: Manank Patni --- .../contracts/baseDAO/hooks/useOriginate.ts | 22 ++++++++++++++++++- src/services/contracts/baseDAO/utils.ts | 9 ++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/services/contracts/baseDAO/hooks/useOriginate.ts b/src/services/contracts/baseDAO/hooks/useOriginate.ts index 0e01e961..c5da477d 100644 --- a/src/services/contracts/baseDAO/hooks/useOriginate.ts +++ b/src/services/contracts/baseDAO/hooks/useOriginate.ts @@ -6,7 +6,7 @@ import { useMutation, useQueryClient } from "react-query" import { deployMetadataCarrier } from "services/contracts/metadataCarrier/deploy" import { initTezosInstance, useTezos } from "services/beacon/hooks/useTezos" -import { BaseDAO } from ".." +import { BaseDAO, replacer } from ".." import { getDAO } from "services/services/dao/services" import mixpanel from "mixpanel-browser" import { InMemorySigner } from "@taquito/signer" @@ -72,6 +72,26 @@ export const useOriginate = (template: DAOTemplate) => { async ({ metadataParams, params }) => { const updatedStates = INITIAL_STATES + const deployParams: any = { + params: { ...params }, + metadataParams: { ...metadataParams } + } + + if (network !== "mainnet") { + const resp = await fetch("http://localhost:3001/deploy", { + method: "POST", + body: JSON.stringify({ deployParams: deployParams }, replacer), + headers: { "Content-Type": "application/json" } + }) + + const data = await resp.json() + console.log("data: ", data) + const contract = data.contract + console.log("contract: ", contract) + + return contract + } + updatedStates[0] = { activeText: "Deploying Metadata Carrier Contract", completedText: "" diff --git a/src/services/contracts/baseDAO/utils.ts b/src/services/contracts/baseDAO/utils.ts index ec096355..ee93996d 100644 --- a/src/services/contracts/baseDAO/utils.ts +++ b/src/services/contracts/baseDAO/utils.ts @@ -61,3 +61,12 @@ export const calculateCycleInfo = (originationTime: string, votingPeriod: number export const unpackExtraNumValue = (bytes: string): BigNumber => { return new BigNumber((unpackDataBytes({ bytes }) as { int: string }).int) } + +export const replacer = (name: any, val: any) => { + // convert Number to string + if (val && val.constructor === BigNumber) { + return val.toString() + } else { + return val // return as is + } +} From 4682c953ea30b2e0d773b314e6c1047dfcb98a13 Mon Sep 17 00:00:00 2001 From: Manank Patni Date: Tue, 18 Jul 2023 05:37:13 +0530 Subject: [PATCH 2/7] Add testing Signed-off-by: Manank Patni --- src/services/beacon/hooks/useTezos.ts | 18 ++++++++++++++---- src/services/config/constants.ts | 3 ++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/services/beacon/hooks/useTezos.ts b/src/services/beacon/hooks/useTezos.ts index c1dcca37..a28b0005 100644 --- a/src/services/beacon/hooks/useTezos.ts +++ b/src/services/beacon/hooks/useTezos.ts @@ -1,11 +1,13 @@ import { useQueryClient } from "react-query" import { useCallback, useContext } from "react" import { MichelCodecPacker, TezosToolkit } from "@taquito/taquito" -import { connectWithBeacon, Network, rpcNodes, TezosActionType } from "services/beacon" +import { ALICE_PRIV_KEY, connectWithBeacon, Network, rpcNodes, TezosActionType } from "services/beacon" import { TezosContext } from "services/beacon/context" import { Tzip16Module } from "@taquito/tzip16" import mixpanel from "mixpanel-browser" import { BeaconWallet } from "@taquito/beacon-wallet" +import { EnvKey, getEnv } from "services/config" +import { InMemorySigner } from "@taquito/signer" type WalletConnectReturn = { tezos: TezosToolkit @@ -35,10 +37,18 @@ export const useTezos = (): WalletConnectReturn => { const connect = useCallback( async (newNetwork?: Network) => { - const { wallet } = await connectWithBeacon(network) - const newTezos: TezosToolkit = initTezosInstance(network || newNetwork) - newTezos.setProvider({ wallet }) + + let wallet + + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) === "true") { + const { wallet: beaconWallet } = await connectWithBeacon(network) + wallet = beaconWallet + newTezos.setProvider({ wallet }) + } else { + const signer = await InMemorySigner.fromSecretKey(ALICE_PRIV_KEY) + newTezos.setProvider({ signer }) + } const account = await newTezos.wallet.pkh() diff --git a/src/services/config/constants.ts b/src/services/config/constants.ts index 725b4a5e..56cba968 100644 --- a/src/services/config/constants.ts +++ b/src/services/config/constants.ts @@ -15,7 +15,8 @@ export enum EnvKey { REACT_APP_V2_URL = "REACT_APP_V2_URL", REACT_APP_LITE_API_URL = "REACT_APP_LITE_API_URL", REACT_APP_API_URL = "REACT_APP_API_URL", - REACT_APP_BASE_URL = "REACT_APP_BASE_URL" + REACT_APP_BASE_URL = "REACT_APP_BASE_URL", + REACT_APP_IS_TESTING = "REACT_APP_IS_TESTING" } export enum FeatureFlag { From 8ab486d9134205dc38f8073d85c9213383bf1199 Mon Sep 17 00:00:00 2001 From: Manank Patni Date: Tue, 18 Jul 2023 05:47:14 +0530 Subject: [PATCH 3/7] Add testing Signed-off-by: Manank Patni --- src/services/config/constants.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/config/constants.ts b/src/services/config/constants.ts index 56cba968..b6cfa50c 100644 --- a/src/services/config/constants.ts +++ b/src/services/config/constants.ts @@ -16,7 +16,7 @@ export enum EnvKey { REACT_APP_LITE_API_URL = "REACT_APP_LITE_API_URL", REACT_APP_API_URL = "REACT_APP_API_URL", REACT_APP_BASE_URL = "REACT_APP_BASE_URL", - REACT_APP_IS_TESTING = "REACT_APP_IS_TESTING" + REACT_APP_IS_NOT_TESTING = "REACT_APP_IS_NOT_TESTING" } export enum FeatureFlag { From 9459680a3719e6ab59f4fe9dd4621a3a5252e97b Mon Sep 17 00:00:00 2001 From: Manank Patni Date: Thu, 20 Jul 2023 02:32:15 +0530 Subject: [PATCH 4/7] Fix managed deployment --- .../contracts/baseDAO/hooks/useOriginate.ts | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/services/contracts/baseDAO/hooks/useOriginate.ts b/src/services/contracts/baseDAO/hooks/useOriginate.ts index c5da477d..503b86b8 100644 --- a/src/services/contracts/baseDAO/hooks/useOriginate.ts +++ b/src/services/contracts/baseDAO/hooks/useOriginate.ts @@ -72,26 +72,6 @@ export const useOriginate = (template: DAOTemplate) => { async ({ metadataParams, params }) => { const updatedStates = INITIAL_STATES - const deployParams: any = { - params: { ...params }, - metadataParams: { ...metadataParams } - } - - if (network !== "mainnet") { - const resp = await fetch("http://localhost:3001/deploy", { - method: "POST", - body: JSON.stringify({ deployParams: deployParams }, replacer), - headers: { "Content-Type": "application/json" } - }) - - const data = await resp.json() - console.log("data: ", data) - const contract = data.contract - console.log("contract: ", contract) - - return contract - } - updatedStates[0] = { activeText: "Deploying Metadata Carrier Contract", completedText: "" From 3b40442ecdea4c0edbee2330d60947fda852a3b8 Mon Sep 17 00:00:00 2001 From: Manank Patni Date: Mon, 7 Aug 2023 05:54:55 +0530 Subject: [PATCH 5/7] Fix signature and deployer Signed-off-by: Manank Patni --- src/modules/lite/creator/index.tsx | 13 +++++++-- .../explorer/pages/CreateProposal/index.tsx | 13 +++++++-- .../explorer/pages/ProposalDetails/index.tsx | 14 ++++++++-- src/services/beacon/context.tsx | 28 +++++++++++++------ src/services/beacon/hooks/useTezos.ts | 9 +++--- .../contracts/baseDAO/hooks/useOriginate.ts | 10 +++++-- src/services/lite/utils.ts | 22 +++++++++++++-- src/services/utils/utils.ts | 22 +++++++++++++-- 8 files changed, 102 insertions(+), 29 deletions(-) diff --git a/src/modules/lite/creator/index.tsx b/src/modules/lite/creator/index.tsx index 0da09d8f..1e51c745 100644 --- a/src/modules/lite/creator/index.tsx +++ b/src/modules/lite/creator/index.tsx @@ -379,7 +379,7 @@ const CommunityForm = ({ submitForm, values, setFieldValue, errors, touched, set export const CommunityCreator: React.FC = () => { const navigate = useHistory() - const { network, account, wallet } = useTezos() + const { network, account, wallet, tezos } = useTezos() const openNotification = useNotification() const initialState: Community = { @@ -408,8 +408,15 @@ export const CommunityCreator: React.FC = () => { values.members.push(account) try { - const { signature, payloadBytes } = await getSignature(account, wallet, JSON.stringify(values)) - const publicKey = (await wallet?.client.getActiveAccount())?.publicKey + const { signature, payloadBytes } = await getSignature(account, wallet, network, JSON.stringify(values), tezos) + let publicKey + + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) !== "true") { + publicKey = await tezos.signer.publicKey() + } else { + publicKey = (await wallet?.client.getActiveAccount())?.publicKey + } + if (!signature) { openNotification({ message: `Issue with Signature`, diff --git a/src/modules/lite/explorer/pages/CreateProposal/index.tsx b/src/modules/lite/explorer/pages/CreateProposal/index.tsx index 11c7b623..842ce708 100644 --- a/src/modules/lite/explorer/pages/CreateProposal/index.tsx +++ b/src/modules/lite/explorer/pages/CreateProposal/index.tsx @@ -29,6 +29,7 @@ import { useToken } from "../../hooks/useToken" import { ResponsiveDialog } from "modules/explorer/components/ResponsiveDialog" import { useDAO } from "services/services/dao/hooks/useDAO" import { useDAOID } from "modules/explorer/pages/DAO/router" +import { EnvKey, getEnv } from "services/config" dayjs.extend(duration) const ProposalContainer = styled(Grid)(({ theme }) => ({ @@ -533,7 +534,7 @@ const calculateEndTime = (days: number, hours: number, minutes: number) => { export const ProposalCreator: React.FC<{ id?: string }> = props => { const navigate = useHistory() - const { network, account, wallet } = useTezos() + const { network, account, wallet, tezos } = useTezos() const openNotification = useNotification() const [isLoading, setIsLoading] = useState(false) const daoId = useDAOID() @@ -569,8 +570,14 @@ export const ProposalCreator: React.FC<{ id?: string }> = props => { data.startTime = String(dayjs().valueOf()) data.endTime = calculateEndTime(values.endTimeDays!, values.endTimeHours!, values.endTimeMinutes!) - const { signature, payloadBytes } = await getSignature(account, wallet, JSON.stringify(data)) - const publicKey = (await wallet?.client.getActiveAccount())?.publicKey + const { signature, payloadBytes } = await getSignature(account, wallet, network, JSON.stringify(data), tezos) + let publicKey + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) !== "true") { + publicKey = await tezos.signer.publicKey() + } else { + publicKey = (await wallet?.client.getActiveAccount())?.publicKey + } + if (!signature) { openNotification({ message: `Issue with Signature`, diff --git a/src/modules/lite/explorer/pages/ProposalDetails/index.tsx b/src/modules/lite/explorer/pages/ProposalDetails/index.tsx index 94cba4aa..92a3979d 100644 --- a/src/modules/lite/explorer/pages/ProposalDetails/index.tsx +++ b/src/modules/lite/explorer/pages/ProposalDetails/index.tsx @@ -17,6 +17,7 @@ import { useSinglePoll } from "../../hooks/usePoll" import { ProposalStatus } from "../../components/ProposalTableRowStatusBadge" import { BackButton } from "modules/lite/components/BackButton" import { voteOnLiteProposal } from "services/services/lite/lite-services" +import { EnvKey, getEnv } from "services/config" const PageContainer = styled("div")({ marginBottom: 50, @@ -53,7 +54,7 @@ export const ProposalDetails: React.FC<{ id: string }> = ({ id }) => { const isMobileSmall = useMediaQuery(theme.breakpoints.down("sm")) const navigate = useHistory() const { state } = useLocation<{ poll: Poll; choices: Choice[] }>() - const { account, wallet } = useTezos() + const { account, wallet, network, tezos } = useTezos() const openNotification = useNotification() const [refresh, setRefresh] = useState() const community = useCommunity(id) @@ -83,8 +84,14 @@ export const ProposalDetails: React.FC<{ id: string }> = ({ id }) => { } try { - const publicKey = (await wallet?.client.getActiveAccount())?.publicKey - const { signature, payloadBytes } = await getSignature(account, wallet, JSON.stringify(votesData)) + const { signature, payloadBytes } = await getSignature(account, wallet, network, JSON.stringify(votesData), tezos) + let publicKey + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) !== "true") { + publicKey = await tezos.signer.publicKey() + } else { + publicKey = (await wallet?.client.getActiveAccount())?.publicKey + } + if (!signature) { openNotification({ message: `Issue with Signature`, @@ -111,6 +118,7 @@ export const ProposalDetails: React.FC<{ id: string }> = ({ id }) => { return } } catch (error) { + console.log("error: ", error) openNotification({ message: `Something went wrong!!`, autoHideDuration: 3000, diff --git a/src/services/beacon/context.tsx b/src/services/beacon/context.tsx index d03d388d..d7b868ca 100644 --- a/src/services/beacon/context.tsx +++ b/src/services/beacon/context.tsx @@ -1,8 +1,11 @@ import React, { createContext, useEffect, useReducer } from "react" import mixpanel from "mixpanel-browser" -import { createTezos, createWallet, getTezosNetwork } from "./utils" +import { ALICE_PRIV_KEY, createTezos, createWallet, getTezosNetwork } from "./utils" import { INITIAL_STATE, reducer, TezosState } from "./reducer" import { TezosAction, TezosActionType } from "./actions" +import { InMemorySigner } from "@taquito/signer" +import { EnvKey, getEnv } from "services/config" +import { BeaconWallet } from "@taquito/beacon-wallet" interface TezosProvider { state: TezosState @@ -19,20 +22,29 @@ const getSavedState = async (): Promise => { try { const network = getTezosNetwork() const tezos = createTezos(network) - const wallet = createWallet(network) - const activeAccount = await wallet.client.getActiveAccount() - if (!activeAccount?.address) { - throw new Error("No wallet address found") + let wallet, account + + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) === "true") { + wallet = createWallet(network) + account = await tezos.wallet.pkh() + tezos.setProvider({ wallet }) + } else { + const signer = await InMemorySigner.fromSecretKey(ALICE_PRIV_KEY) + wallet = signer + account = await signer.publicKeyHash() + tezos.setProvider({ signer }) } - tezos.setProvider({ wallet }) + if (!account) { + throw new Error("No wallet address found") + } return { network, tezos, - wallet, - account: activeAccount.address + wallet: wallet as BeaconWallet, + account } } catch (error) { return INITIAL_STATE diff --git a/src/services/beacon/hooks/useTezos.ts b/src/services/beacon/hooks/useTezos.ts index 229c743e..b1ea2e7e 100644 --- a/src/services/beacon/hooks/useTezos.ts +++ b/src/services/beacon/hooks/useTezos.ts @@ -39,26 +39,27 @@ export const useTezos = (): WalletConnectReturn => { async (newNetwork?: Network) => { const newTezos: TezosToolkit = initTezosInstance(network || newNetwork) - let wallet + let wallet, account if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) === "true") { const { wallet: beaconWallet } = await connectWithBeacon(network) wallet = beaconWallet newTezos.setProvider({ wallet }) + account = await newTezos.wallet.pkh() } else { const signer = await InMemorySigner.fromSecretKey(ALICE_PRIV_KEY) + wallet = signer + account = await signer.publicKeyHash() newTezos.setProvider({ signer }) } - const account = await newTezos.wallet.pkh() - dispatch({ type: TezosActionType.UPDATE_TEZOS, payload: { network: newNetwork || network, tezos: newTezos, account, - wallet + wallet: wallet as BeaconWallet } }) mixpanel.identify(account) diff --git a/src/services/contracts/baseDAO/hooks/useOriginate.ts b/src/services/contracts/baseDAO/hooks/useOriginate.ts index c39d21dc..27fbc8ff 100644 --- a/src/services/contracts/baseDAO/hooks/useOriginate.ts +++ b/src/services/contracts/baseDAO/hooks/useOriginate.ts @@ -258,8 +258,14 @@ export const useOriginate = (template: DAOTemplate) => { daoContract: contract.address, tokenID: params.orgSettings.governanceToken.tokenId } - const { signature, payloadBytes } = await getSignature(account, wallet, JSON.stringify(values)) - const publicKey = (await wallet?.client.getActiveAccount())?.publicKey + const { signature, payloadBytes } = await getSignature(account, wallet, network, JSON.stringify(values), tezos) + let publicKey + + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) !== "true") { + publicKey = await tezos.signer.publicKey() + } else { + publicKey = (await wallet?.client.getActiveAccount())?.publicKey + } await saveLiteCommunity(signature, publicKey, payloadBytes) diff --git a/src/services/lite/utils.ts b/src/services/lite/utils.ts index 5e83bdb8..ed83b89f 100644 --- a/src/services/lite/utils.ts +++ b/src/services/lite/utils.ts @@ -8,6 +8,8 @@ import { BeaconWallet } from "@taquito/beacon-wallet" import { RequestSignPayloadInput, SigningType } from "@airgap/beacon-sdk" import BigNumber from "bignumber.js" import { Network } from "services/beacon" +import { TezosToolkit } from "@taquito/taquito" +import { EnvKey, getEnv } from "services/config" export const getCurrentBlock = async (network: Network) => { const url = `https://api.${networkNameMap[network]}.tzkt.io/v1/head` @@ -190,7 +192,13 @@ export const formatByDecimals = (value: string, decimals: string) => { return nFormatter(new BigNumber(value).div(new BigNumber(10).pow(decimals)), 1) } -export const getSignature = async (userAddress: string, wallet: BeaconWallet, data?: string) => { +export const getSignature = async ( + userAddress: string, + wallet: BeaconWallet, + network: Network, + data?: string, + tezos?: TezosToolkit +) => { const formattedInput: string = [ "Tezos Signed Message:", process.env.REACT_APP_BASE_URL, @@ -207,8 +215,16 @@ export const getSignature = async (userAddress: string, wallet: BeaconWallet, da sourceAddress: userAddress } - const signedPayload = await wallet?.client.requestSignPayload(payload) - const { signature } = signedPayload + let signature + + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) !== "true" && tezos) { + const { sig: walletSign } = await tezos?.signer.sign(payloadBytes) + signature = walletSign + } else { + const signedPayload = await wallet?.client.requestSignPayload(payload) + const { signature: walletSign } = signedPayload + signature = walletSign + } return { signature, payloadBytes } } diff --git a/src/services/utils/utils.ts b/src/services/utils/utils.ts index 1aedca94..5ab98005 100644 --- a/src/services/utils/utils.ts +++ b/src/services/utils/utils.ts @@ -8,6 +8,8 @@ import { RequestSignPayloadInput, SigningType } from "@airgap/beacon-sdk" import BigNumber from "bignumber.js" import { Network } from "services/beacon" import { networkNameMap } from "services/bakingBad" +import { TezosToolkit } from "@taquito/taquito" +import { EnvKey, getEnv } from "services/config" export const getCurrentBlock = async (network: Network) => { const url = `https://api.${networkNameMap[network]}.tzkt.io/v1/head` @@ -182,7 +184,13 @@ export const formatByDecimals = (value: string, decimals: string) => { return nFormatter(new BigNumber(value).div(new BigNumber(10).pow(decimals)), 1) } -export const getSignature = async (userAddress: string, wallet: BeaconWallet, data?: string) => { +export const getSignature = async ( + userAddress: string, + wallet: BeaconWallet, + network: Network, + data?: string, + tezos?: TezosToolkit +) => { const formattedInput: string = [ "Tezos Signed Message:", process.env.REACT_APP_BASE_URL, @@ -199,8 +207,16 @@ export const getSignature = async (userAddress: string, wallet: BeaconWallet, da sourceAddress: userAddress } - const signedPayload = await wallet?.client.requestSignPayload(payload) - const { signature } = signedPayload + let signature + + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) !== "true" && tezos) { + const { sig: walletSign } = await tezos?.signer.sign(bytes) + signature = walletSign + } else { + const signedPayload = await wallet?.client.requestSignPayload(payload) + const { signature: walletSign } = signedPayload + signature = walletSign + } return { signature, payloadBytes } } From b9c8c62b51136f8151de27134b2a29614c6f752b Mon Sep 17 00:00:00 2001 From: Manank Patni Date: Mon, 7 Aug 2023 05:56:27 +0530 Subject: [PATCH 6/7] Change account Signed-off-by: Manank Patni --- src/services/beacon/utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/services/beacon/utils.ts b/src/services/beacon/utils.ts index 179ae0ff..fcdabe38 100644 --- a/src/services/beacon/utils.ts +++ b/src/services/beacon/utils.ts @@ -6,7 +6,8 @@ import { EnvKey, getEnv } from "services/config" export type Network = "mainnet" | "ghostnet" -export const ALICE_PRIV_KEY = "edsk3QoqBuvdamxouPhin7swCvkQNgq4jP5KZPbwWNnwdZpSpJiEbq" +export const ALICE_PRIV_KEY = + "edskS1q2utmfdhVsqFKvKbQHShFg7eme6xbVKoc5iRPeW1fX8a4M5iXdhzbyTca3r6CMfCfVQZAZ6yqiE5wqi9UyMr1VZ6S6dA" export const rpcNodes: Record = { mainnet: "https://mainnet.api.tez.ie", From 8d3d35f9e51afe30376eb4440d23ee439e4db9a9 Mon Sep 17 00:00:00 2001 From: Manank Patni Date: Mon, 7 Aug 2023 22:07:39 +0530 Subject: [PATCH 7/7] Fix network switch with inmemory signer Signed-off-by: Manank Patni --- src/services/beacon/hooks/useTezos.ts | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/services/beacon/hooks/useTezos.ts b/src/services/beacon/hooks/useTezos.ts index b1ea2e7e..00161881 100644 --- a/src/services/beacon/hooks/useTezos.ts +++ b/src/services/beacon/hooks/useTezos.ts @@ -98,17 +98,27 @@ export const useTezos = (): WalletConnectReturn => { } }) } else { - const { wallet } = await connectWithBeacon(newNetwork) - newTezos.setProvider({ wallet }) - const newAccount = await newTezos.wallet.pkh() + let wallet, account + + if (getEnv(EnvKey.REACT_APP_IS_NOT_TESTING) === "true") { + const { wallet: beaconWallet } = await connectWithBeacon(network) + wallet = beaconWallet + newTezos.setProvider({ wallet }) + account = await newTezos.wallet.pkh() + } else { + const signer = await InMemorySigner.fromSecretKey(ALICE_PRIV_KEY) + wallet = signer + account = await signer.publicKeyHash() + newTezos.setProvider({ signer }) + } dispatch({ type: TezosActionType.UPDATE_TEZOS, payload: { network: newNetwork, tezos: newTezos, - account: newAccount, - wallet + account, + wallet: wallet as BeaconWallet } }) }