diff --git a/package.json b/package.json index 4f5ce9ba..2d4483a8 100644 --- a/package.json +++ b/package.json @@ -175,6 +175,9 @@ "window": { "height": "450" } + }, + "linux": { + "target": "AppImage" } } } diff --git a/packages/renderer/src/components/PasswordDecrypt.tsx b/packages/renderer/src/components/PasswordDecrypt.tsx index 894c2645..120e2d40 100644 --- a/packages/renderer/src/components/PasswordDecrypt.tsx +++ b/packages/renderer/src/components/PasswordDecrypt.tsx @@ -46,14 +46,16 @@ export default function PasswordDecrypt({onSuccess, onClose}: IPasswordDecrypt) return (

Insert your password to proceed

- { - setPassword(e.target.value); - }} - /> +
+ { + setPassword(e.target.value); + }} + /> +
diff --git a/packages/renderer/src/components/UI/modals/zkAppIntegration/ConfirmZkappPayment.tsx b/packages/renderer/src/components/UI/modals/zkAppIntegration/ConfirmZkappPayment.tsx index fc235cad..fe5b111c 100644 --- a/packages/renderer/src/components/UI/modals/zkAppIntegration/ConfirmZkappPayment.tsx +++ b/packages/renderer/src/components/UI/modals/zkAppIntegration/ConfirmZkappPayment.tsx @@ -12,13 +12,13 @@ import {signTransaction} from '../../../../tools/utils'; import PasswordDecrypt from '../../../PasswordDecrypt'; import {toast} from 'react-toastify'; import {mnemonicToPrivateKey} from '../../../../../../preload/src/bip'; -import {client, createPaymentInputFromPayload, createSignatureInputFromSignature} from '/@/tools'; +import {client, createPaymentInputFromPayload, createSignatureInputFromSignature, toNanoMINA} from '/@/tools'; import {ERROR_CODES} from '/@/tools/zkapp'; import ConfirmZkappLedger from './ConfirmZkappLedger'; import TransactionData from './TransactionData'; import {IBalanceContext} from '/@/contexts/balance/BalanceTypes'; import {BalanceContext} from '/@/contexts/balance/BalanceContext'; -import * as Big from 'big.js'; +import Big from 'big.js'; export default function ConfirmZkappPayment() { const wallet = useRecoilValue(walletState); @@ -57,7 +57,7 @@ export default function ConfirmZkappPayment() { const address = getAccountAddress(); const balance = getBalance(address[0]); const available = +(balance?.liquidUnconfirmed || 0); - if (+available > 0 && +Big(+available).sub(fee) >= 0) { + if (+available > 0 && (+Big(available).sub(fee)) >= 0) { return true; } } @@ -81,6 +81,8 @@ export default function ConfirmZkappPayment() { ...transactionData, nonce, from: address[0], + amount: toNanoMINA(transactionData.amount), + fee: toNanoMINA(transactionData.fee), }); completePayment(signedTx); }; @@ -110,7 +112,7 @@ export default function ConfirmZkappPayment() { // Define the required balance const {fee} = transactionData; // Check if the current balance is sufficient - if (checkBalance(fee)) { + if (checkBalance(toNanoMINA(fee))) { // If the balance is sufficient, change the state setShowPassword(true); } else { diff --git a/packages/renderer/src/components/UI/modals/zkAppIntegration/ZkappIframe.tsx b/packages/renderer/src/components/UI/modals/zkAppIntegration/ZkappIframe.tsx index 94ef8d47..665bf90b 100644 --- a/packages/renderer/src/components/UI/modals/zkAppIntegration/ZkappIframe.tsx +++ b/packages/renderer/src/components/UI/modals/zkAppIntegration/ZkappIframe.tsx @@ -32,7 +32,7 @@ export const ZkappIframe = () => { diff --git a/packages/renderer/src/components/ZkappIntegration.tsx b/packages/renderer/src/components/ZkappIntegration.tsx index d14e704b..84cdfe3e 100644 --- a/packages/renderer/src/components/ZkappIntegration.tsx +++ b/packages/renderer/src/components/ZkappIntegration.tsx @@ -1,5 +1,5 @@ import {useRecoilValue, useSetRecoilState, useRecoilState} from 'recoil'; -import {DEFAULT_FEE, client} from '../tools'; +import {DEFAULT_FEE, client, toNanoMINA} from '../tools'; import {NetConfig, sendResponse} from '../tools/mina-zkapp-bridge'; import { configState, @@ -27,7 +27,7 @@ export default function ZkappIntegration() { const {address: sender} = wallet; const setZkappState = useSetRecoilState(zkappState); const config = useRecoilValue(configState); - const [{availableNetworks, selectedNetwork}, setNetworkState] = useRecoilState(networkState); + const [{availableNetworks, selectedNetwork, selectedNode}, setNetworkState] = useRecoilState(networkState); useEffect(() => { setListeners(); @@ -144,9 +144,10 @@ export default function ZkappIntegration() { const getNetworkConfig = async () => { console.log('Received get-network-config'); - const netConfig: NetConfig = selectedNetwork as NetConfig; - // Mock for Berkeley - // sendResponse('clorio-set-network-config', {chainId: 'berkeley', name: 'Berkeley'}); + const netConfig: NetConfig = { + chainId: selectedNode?.label, + name: selectedNetwork?.name, + } as NetConfig; sendResponse('clorio-set-network-config', netConfig); }; @@ -215,7 +216,12 @@ export default function ZkappIntegration() { setZkappState(prev => { return { ...prev, - transactionData: {...data, from: sender}, + transactionData: { + ...data, + from: sender, + fee: data.fee || DEFAULT_FEE, + amount: data.amount, + }, showPaymentConfirmation: true, isPendingConfirmation: true, type: 'send-payment', @@ -315,7 +321,6 @@ export default function ZkappIntegration() { rejectIfLedger(); console.log('Received verify-message'); const parsedDocument = {...data, signature: JSON.parse(data.signature)}; - console.log('🚀 ~ verifyMessage ~ parsedDocument:', parsedDocument); const verified = await (await client()).verifyMessage(parsedDocument); sendResponse('clorio-verified-message', verified); }; diff --git a/packages/renderer/src/components/userIdUpdater/UserIDUpdater.tsx b/packages/renderer/src/components/userIdUpdater/UserIDUpdater.tsx index 15da086c..965ba9ab 100644 --- a/packages/renderer/src/components/userIdUpdater/UserIDUpdater.tsx +++ b/packages/renderer/src/components/userIdUpdater/UserIDUpdater.tsx @@ -5,6 +5,8 @@ import {GET_ID} from '../../graphql/query'; import type {IWalletIdData} from '../../types/WalletIdData'; import {DEFAULT_QUERY_REFRESH_INTERVAL} from '../../tools'; import {useWallet} from '/@/contexts/WalletContext'; +import {useRecoilState, useRecoilValue} from 'recoil'; +import {walletState} from '/@/store'; const UserIDUpdater = () => { const [address, setAddress] = useState(''); @@ -13,7 +15,8 @@ const UserIDUpdater = () => { skip: !address, pollInterval: DEFAULT_QUERY_REFRESH_INTERVAL, }); - const {wallet, updateWallet} = useWallet(); + // const {wallet, updateWallet} = useWallet(); + const [wallet, updateWallet] = useRecoilState(walletState); /** * Read the wallet address from the storage and set it inside the component state @@ -34,9 +37,9 @@ const UserIDUpdater = () => { if (userID?.idByPublicKey) { updateUser(address, +userID.idByPublicKey.id); if ((userID && !wallet.id) || +wallet.id === -1) { - updateWallet({...wallet, id: +userID.idByPublicKey.id}); + updateWallet(state => ({...state, id: +userID.idByPublicKey.id})); } - stopPolling(); + // stopPolling(); } }, [userID]); diff --git a/packages/renderer/src/pages/Login.tsx b/packages/renderer/src/pages/Login.tsx index 2c1e17d9..16dcbdda 100644 --- a/packages/renderer/src/pages/Login.tsx +++ b/packages/renderer/src/pages/Login.tsx @@ -158,7 +158,7 @@ function Login({toggleLoader}: IProps) { */ const checkCredentials = async () => { try { - const derivedAccount = await deriveAccount(privateKey); + const derivedAccount = await deriveAccount(privateKey.trim()); if (derivedAccount.publicKey) { setPublicKey(derivedAccount.publicKey); await userIdRefetch({publicKey: derivedAccount.publicKey}); @@ -187,7 +187,7 @@ function Login({toggleLoader}: IProps) { }; const onSecureStorageSubmit = (key: string) => { - encryptData({key, data: privateKey}); + encryptData({key, data: privateKey.trim()}); if (userIdData) { saveAndStoreSession(); } else { diff --git a/packages/renderer/src/pages/Overview.tsx b/packages/renderer/src/pages/Overview.tsx index ee83e05f..4d1bc0e3 100644 --- a/packages/renderer/src/pages/Overview.tsx +++ b/packages/renderer/src/pages/Overview.tsx @@ -20,6 +20,8 @@ import type { } from '../components/transactionsTable/TransactionsTypes'; import type {IHomeNewsQuery} from '/@/types/NewsData'; import {useWallet} from '../contexts/WalletContext'; +import {useRecoilValue} from 'recoil'; +import {walletState} from '../store'; interface IProps { sessionData: IWalletData; @@ -29,6 +31,7 @@ const Overview = ({sessionData}: IProps) => { const {balanceData} = useContext>(BalanceContext); const balance = balanceData?.balances[sessionData.address]; const {wallet} = useWallet(); + const {id} = useRecoilValue(walletState); const [offset, setOffset] = useState(0); const [walletId, setWalletId] = useState(+sessionData.id); const {data: newsData} = useQuery(GET_HOME_NEWS); @@ -41,9 +44,9 @@ const Overview = ({sessionData}: IProps) => { stopPolling: transactionStopPolling, startPolling: transactionStartPolling, } = useQuery(GET_TRANSACTIONS, { - variables: {accountId: walletId, offset}, + variables: {accountId: +id || walletId, offset}, fetchPolicy: 'network-only', - skip: !wallet.id || wallet.id === -1, + skip: !id, pollInterval: DEFAULT_QUERY_REFRESH_INTERVAL, }); const { diff --git a/packages/renderer/src/pages/SplashScreen.tsx b/packages/renderer/src/pages/SplashScreen.tsx index 5e48224b..ac6040db 100644 --- a/packages/renderer/src/pages/SplashScreen.tsx +++ b/packages/renderer/src/pages/SplashScreen.tsx @@ -34,10 +34,10 @@ const SplashScreen = ({toggleLoader}: IProps) => { variables: {publicKey: derivedAccount.publicKey as string}, }); if (called) { - const id = +data ? data.idByPublicKey.id || -1 : -1; + const id = data?.idByPublicKey.id || -1; const isUsingMnemonic = privateKey.trim().split(' ').length === 12; setPassphrase(isUsingMnemonic); - const success = await storeSession(derivedAccount.publicKey, id, false, 0, isUsingMnemonic); + const success = await storeSession(derivedAccount.publicKey, +id, false, 0, isUsingMnemonic); updateWallet({ address: derivedAccount.publicKey, id, diff --git a/packages/renderer/src/pages/sendTX/SendTX.tsx b/packages/renderer/src/pages/sendTX/SendTX.tsx index 59e3f6c0..2b59e44f 100644 --- a/packages/renderer/src/pages/sendTX/SendTX.tsx +++ b/packages/renderer/src/pages/sendTX/SendTX.tsx @@ -1,5 +1,5 @@ import {useState, useEffect, useContext} from 'react'; -import {useQuery, useMutation} from '@apollo/client'; +import {useQuery, useMutation, useLazyQuery} from '@apollo/client'; import {useNavigate} from 'react-router-dom'; import {toast} from 'react-toastify'; import TransactionForm from '/@/components/forms/transactionForm/TransactionForm'; @@ -22,9 +22,10 @@ import { MINIMUM_NONCE, deriveAccount, getPassphrase, + toMINA, } from '/@/tools'; import Spinner from '/@/components/UI/Spinner'; -import {BROADCAST_TRANSACTION, GET_FEE, GET_NONCE} from '/@/graphql/query'; +import {BROADCAST_TRANSACTION, GET_BALANCE, GET_FEE, GET_NONCE} from '/@/graphql/query'; import type {INonceQueryResult} from './SendTXHelper'; import { checkBalanceAfterTransaction, @@ -44,6 +45,9 @@ import Stepper from '/@/components/UI/stepper/Stepper'; import TransactionAuthentication from '/@/components/transactionAuthentication/TransactionAuthentication'; import {useWallet} from '/@/contexts/WalletContext'; import {signTransaction} from '/@/tools/utils'; +import {IBalanceQueryResult} from '/@/components/balance/BalanceTypes'; +import {useRecoilState, useRecoilValue} from 'recoil'; +import {walletState} from '/@/store'; interface IProps { sessionData: IWalletData; @@ -66,9 +70,10 @@ function SendTX(props: IProps) { const [storedPassphrase, setStoredPassphrase] = useState(''); const {isLedgerEnabled} = useContext>(LedgerContext); const {getBalance, setShouldBalanceUpdate} = useContext>(BalanceContext); - const {wallet} = useWallet(); + // const {wallet} = useWallet(); + const wallet = useRecoilValue(walletState); const senderAddress = wallet.address; - const balance = getBalance && getBalance(senderAddress); + const balance = getBalance && getBalance(wallet.address); const { data: nonceData, refetch: nonceRefetch, @@ -79,6 +84,7 @@ function SendTX(props: IProps) { skip: !senderAddress, fetchPolicy: 'network-only', }); + const [fetchBalance] = useLazyQuery(GET_BALANCE); useEffect(() => { getPassphrase().then(passphrase => { setStoredPassphrase(passphrase); @@ -195,7 +201,7 @@ function SendTX(props: IProps) { * Check if nonce is available, if not ask the user for a custom nonce. * After the nonce is set, proceed with transaction data verification and Passphrase/Private key verification */ - const openConfirmationModal = () => { + const openConfirmationModal = async () => { if (nonceLoading) { setWaitingNonce(true); return; @@ -204,10 +210,16 @@ function SendTX(props: IProps) { if (!nonceData && !customNonce) { return setShowModal(ModalStates.NONCE); } - checkBalanceAfterTransaction({balance, transactionData}); - checkTransactionFields(transactionData); - setStep(SendTXPageSteps.PRIVATE_KEY); - setShowModal(''); + if (getBalance) { + const {data} = await fetchBalance({variables: {publicKey: wallet.address}}); + checkBalanceAfterTransaction({ + balance: data?.accountByKey?.balance, + transactionData, + }); + checkTransactionFields(transactionData); + setStep(SendTXPageSteps.PRIVATE_KEY); + setShowModal(''); + } } catch (e) { toast.error(e.message); } @@ -222,7 +234,10 @@ function SendTX(props: IProps) { throw new Error(); } setShowModal(''); - const derivedData = await deriveAccount(passphrase || privateKey, wallet.accountNumber); + const derivedData = await deriveAccount( + passphrase?.trim() || privateKey.trim(), + wallet.accountNumber, + ); setTransactionData({ ...transactionData, senderAddress: derivedData.publicKey || '', @@ -311,7 +326,10 @@ function SendTX(props: IProps) { } try { const actualNonce = getNonce(); - const derivedData = await deriveAccount(key.privateKey || privateKey, wallet.accountNumber); + const derivedData = await deriveAccount( + key.privateKey.trim() || privateKey.trim(), + wallet.accountNumber, + ); setTransactionData({ ...transactionData, senderAddress: derivedData.publicKey || '', @@ -320,11 +338,13 @@ function SendTX(props: IProps) { privateKey: derivedData?.privateKey, publicKey: derivedData?.publicKey, } as IKeypair; - const signedPayment = await signTransaction({ - transactionData, - keypair, - sender: derivedData?.publicKey || senderAddress, - actualNonce, + const signedPayment = await signTransaction(keypair.privateKey, { + ...transactionData, + from: derivedData?.publicKey || senderAddress, + to: transactionData.receiverAddress, + nonce: actualNonce, + fee: transactionData.fee, + amoun: transactionData.amount, }); if (signedPayment) { diff --git a/packages/renderer/src/pages/stake/Stake.tsx b/packages/renderer/src/pages/stake/Stake.tsx index cba1936d..5bb16cdd 100644 --- a/packages/renderer/src/pages/stake/Stake.tsx +++ b/packages/renderer/src/pages/stake/Stake.tsx @@ -49,7 +49,8 @@ import {IFeeQuery} from '/@/types/Fee'; import {INonceDelegateQueryResult} from './StakeTypes'; import {IKeypair} from '/@/types'; import WaitingLedger from '/@/components/UI/modals/WaitingLedger'; -import {useWallet} from '/@/contexts/WalletContext'; +import {useRecoilValue} from 'recoil'; +import {walletState} from '/@/store'; interface IProps { sessionData: IWalletData; @@ -71,8 +72,8 @@ const Stake = ({sessionData}: IProps) => { const [sendTransactionFlag, setSendTransactionFlag] = useState(false); const {isLedgerEnabled} = useContext>(LedgerContext); const {getBalance, setShouldBalanceUpdate} = useContext>(BalanceContext); - const {wallet} = useWallet(); - const {address} = wallet; + const {address, accountNumber} = useRecoilValue(walletState); + const balance = getBalance && getBalance(address); const { data: validatorsData, @@ -329,14 +330,14 @@ const Stake = ({sessionData}: IProps) => { } checkBalance(selectedFee, balance); const actualNonce = getNonce(); - const derivedAccount = await deriveAccount(passphrase || privateKey, wallet.accountNumber); + const derivedAccount = await deriveAccount(passphrase?.trim() || privateKey.trim(), accountNumber); const keypair = { privateKey: derivedAccount.privateKey, publicKey: derivedAccount.publicKey, } as IKeypair; const stakeDelegation = { to: delegateData.publicKey, - from: address, + from: address || keypair.publicKey, fee: selectedFee, nonce: actualNonce, }; @@ -344,7 +345,7 @@ const Stake = ({sessionData}: IProps) => { stakeDelegation, keypair.privateKey, ); - (await client()).verifyStakeDelegation(signedTransaction); + const verify = (await client()).verifyStakeDelegation(signedTransaction); if (signedTransaction) { const signatureInput = createSignatureInputFromSignature(signedTransaction.signature); const sendPaymentInput = createDelegationPaymentInputFromPayload(signedTransaction.data); diff --git a/packages/renderer/src/store/network.ts b/packages/renderer/src/store/network.ts index eb6059c2..2cb0697b 100644 --- a/packages/renderer/src/store/network.ts +++ b/packages/renderer/src/store/network.ts @@ -9,7 +9,7 @@ export interface NetworkConfigType { export interface NetworkSettingsType { availableNetworks: NetworkConfigType[]; showChangeNetworkModal: boolean; - selectedNetwork?: NetworkConfigType; + selectedNetwork?: NetworkConfigType | INetworkOption; switchNetwork?: string; addChainData?: {name: string; url: string}; isAddingChain: boolean; diff --git a/packages/renderer/src/styles/__new_design.scss b/packages/renderer/src/styles/__new_design.scss index 8f8d68e9..403c7823 100644 --- a/packages/renderer/src/styles/__new_design.scss +++ b/packages/renderer/src/styles/__new_design.scss @@ -508,6 +508,11 @@ p { align-items: start; } +.password-input{ + width: 500px; + margin: 0 auto; +} + @media screen and (max-width: 600px) { .homepage-card { height: 100vh; diff --git a/packages/renderer/src/styles/__table.scss b/packages/renderer/src/styles/__table.scss index ce651fc4..af3fcf37 100644 --- a/packages/renderer/src/styles/__table.scss +++ b/packages/renderer/src/styles/__table.scss @@ -29,6 +29,7 @@ $global-radius: 4px; } .table-icon { + height: 50px; width: 20%; } @@ -80,6 +81,7 @@ th { } .table-hash { + height: 50px; a { max-width: 90%; padding-top: 3px; diff --git a/packages/renderer/src/tools/utils.ts b/packages/renderer/src/tools/utils.ts index 6229e140..6bf4c84a 100644 --- a/packages/renderer/src/tools/utils.ts +++ b/packages/renderer/src/tools/utils.ts @@ -290,23 +290,22 @@ async function getSignClient() { if (netConfig.netType) { netType = netConfig.netType; } - let client; - if (netType === NET_CONFIG_TYPE.Mainnet) { - client = new Client({network: 'mainnet'}); - } else { - client = new Client({network: 'testnet'}); - } + const client = await new Client({ + network: + JSON.parse(localStorage.getItem('networkSettings'))?.network || + import.meta.env.VITE_REACT_APP_NETWORK, + }); return client; } /** build payment and delegation tx body */ function buildSignTxBody(params) { // const sendAction = params.sendAction; - const sendFee = toNanoMINA(+params.fee || 0.1); - const sendAmount = toNanoMINA(+params.amount || 0.1); + const sendFee = +params.fee || 0.1; + const sendAmount = +params.amount || 0.1; const signBody = { - to: params.to, - from: params.to, + to: params.to || params.receiverAddress, + from: params.to || params.senderAddress, fee: sendFee, nonce: params.nonce || 0, memo: params.memo || '', @@ -320,7 +319,7 @@ function buildSignTxBody(params) { } /** QA net sign */ -export async function signTransaction(privateKey, params) { +export async function signTransaction(privateKey: string, params: unknown) { let signResult; try { const signClient = await getSignClient(); @@ -342,6 +341,7 @@ export async function signTransaction(privateKey, params) { // }; // } else { signBody = buildSignTxBody(params); + console.log('🚀 ~ signTransaction ~ signBody:', signBody); // } signResult = signClient.signTransaction(signBody, privateKey); return signResult;