Skip to content

Commit

Permalink
Transaction list UI fix, fixed ledger zkapp integration, minor UI fix
Browse files Browse the repository at this point in the history
  • Loading branch information
Cryptosaka committed Jun 6, 2024
1 parent cb1b45d commit 5c1fed6
Show file tree
Hide file tree
Showing 27 changed files with 478 additions and 99 deletions.
26 changes: 24 additions & 2 deletions .electron-builder.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
* @see https://www.electron.build/configuration/configuration
*/
module.exports = async function () {
const {getVersion} = await import('./version/getVersion.mjs');
const {
getVersion
} = await import('./version/getVersion.mjs');

return {
directories: {
Expand All @@ -23,7 +25,27 @@ module.exports = async function () {
productName: "Clorio Wallet",
// Specify linux target just for disabling snap compilation
linux: {
target: 'deb',
target: [{
target: "deb",
},
{
target: "AppImage",
},
]
},
dmg: {
contents: [{
x: 340,
y: 270,
type: 'file',
},
{
x: 560,
y: 270,
type: 'link',
path: '/Applications',
},
],
},
};
};
Binary file added build/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added buildResources/background.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "clorio-wallet",
"description": "Clorio wallet",
"version": "2.1.1",
"version": "2.1.2",
"private": true,
"main": "packages/main/dist/index.cjs",
"author": {
Expand All @@ -19,6 +19,7 @@
"compile:mac": "yarn build && ./node_modules/.bin/electron-builder --config .electron-builder.config.cjs --publish never",
"compile:all": "CSC_IDENTITY_AUTO_DISCOVERY=false yarn build && ./node_modules/.bin/electron-builder -mwl --config .electron-builder.config.cjs --publish never",
"compile:linux": "CSC_IDENTITY_AUTO_DISCOVERY=false yarn build && ./node_modules/.bin/electron-builder -l --config .electron-builder.config.cjs --publish never",
"compile:ml": "CSC_IDENTITY_AUTO_DISCOVERY=false yarn build && ./node_modules/.bin/electron-builder -ml --config .electron-builder.config.cjs --publish never",
"test": "npm run test:main && npm run test:preload && npm run test:renderer && npm run test:e2e",
"test:e2e": "npm run build && vitest run",
"test:main": "vitest run -r packages/main --passWithNoTests",
Expand Down
1 change: 1 addition & 0 deletions packages/renderer/src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@import "./styles/__new_design";
@import "./styles/__accountAvatar";
@import "./styles/__sidebar";
@import "./styles/__zkapps";
@import url("https://fonts.googleapis.com/css2?family=Mada:wght@200;300;400;500;600;700;900&display=swap");

a {
Expand Down
23 changes: 14 additions & 9 deletions packages/renderer/src/components/UI/epochBar/EpochBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface RemainingTime {

const EpochBar = () => {
const {settings} = useNetworkSettingsContext();
const [epochError, setEpochError] = useState(false);
const [epochData, setEpochData] = useState({
slot: 0,
epoch: 0,
Expand Down Expand Up @@ -42,17 +43,21 @@ const EpochBar = () => {
}, []);

const fetchEpochData = async () => {
const data = await fetch(settings?.epochUrl || '')
.then(response => response.json())
.then(data => data);
const realSlot = +data.slot % (MAX_SLOT + 1);
const lastTime = ((MAX_SLOT - +realSlot) * SLOT_DURATION) / 1000;
setEpochData(data);
setRemainingTime(calculateTime(lastTime));
setPercentage(parseInt(((100 * +realSlot) / MAX_SLOT).toFixed(0)));
try {
const data = await fetch(settings?.epochUrl || '')
.then(response => response.json())
.then(data => data);
const realSlot = +data.slot % (MAX_SLOT + 1);
const lastTime = ((MAX_SLOT - +realSlot) * SLOT_DURATION) / 1000;
setEpochData(data);
setRemainingTime(calculateTime(lastTime));
setPercentage(parseInt(((100 * +realSlot) / MAX_SLOT).toFixed(0)));
} catch (error) {
setEpochError(true);
}
};

if (!settings?.epochUrl) {
if (!settings?.epochUrl || epochError) {
return (
<div
className="w-100 h-80"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {IBalanceContext} from '/@/contexts/balance/BalanceTypes';
import {BalanceContext} from '/@/contexts/balance/BalanceContext';
import {ERROR_CODES} from '/@/tools/zkapp';
import TransactionData from './TransactionData';
import ConfirmZkappLedgerDelegation from './ConfirmZkappLedgerDelegation';

interface SignedTx {
signature: {
Expand All @@ -37,6 +38,7 @@ interface SignedTx {

export default function ConfirmZkappDelegation() {
const wallet = useRecoilValue(walletState);
const isLedgerEnabled = wallet.ledger;
const fromRef = useRef(null);
const [fromTextWidth, setFromTextWidth] = useState(0);
const [showPassword, setShowPassword] = useState(false);
Expand All @@ -51,6 +53,10 @@ export default function ConfirmZkappDelegation() {
},
});

useEffect(() => {
fetchAndSetNonce();
}, [showDelegationConfirmation]);

useEffect(() => {
if (fromRef.current) {
setFromTextWidth(fromRef.current.offsetWidth - 250);
Expand All @@ -67,6 +73,21 @@ export default function ConfirmZkappDelegation() {
sendResponse('clorio-error', ERROR_CODES.userRejectedRequest);
};

const fetchAndSetNonce = async () => {
if (showDelegationConfirmation) {
const {data: nonceData} = await fetchNonce({variables: {publicKey: wallet.address}});
if (nonceData?.accountByKey?.usableNonce || nonceData?.accountByKey?.usableNonce === 0) {
setZkappState(state => ({
...state,
transactionData: {
...state.transactionData,
nonce: nonceData.accountByKey.usableNonce,
},
}));
}
}
};

// Check with BigJs if the balance is enough
const checkBalance = (fee: number | string) => {
if (getBalance) {
Expand Down Expand Up @@ -110,38 +131,30 @@ export default function ConfirmZkappDelegation() {
sendResponse('error', {error: nonceError});
return;
}
// TODO: Add custom nonce
// Get the nonce

const nonceResponse = await fetchNonce({variables: {publicKey: address[0]}});
const nonce = nonceResponse?.data?.accountByKey?.usableNonce;
if (!nonce && nonce !== 0) {
throw new Error('Nonce not found');
}
// Prepare the stake data
const stakeData = {
...transactionData,
nonce,
// nonce,
from: address[0],
fee: toNanoMINA(transactionData.fee),
};
// Sign the stake delegation
const clientInstance = await client();
const signedTx = await clientInstance.signStakeDelegation(stakeData, privateKey);
const hashedTx = await clientInstance.hashStakeDelegation(signedTx);
await broadcastDelegationTx(signedTx);
sendResponse('clorio-staked-delegation', {hash: hashedTx});
onPostSign();
await broadcastDelegationTx(signedTx, hashedTx);
} catch (error) {
console.error('Error in onConfirm:', error);
toast.error('An error occurred while confirming the transaction');
}
};

const broadcastDelegationTx = async (signedTx: SignedTx) => {
const broadcastDelegationTx = async (signedTx: SignedTx, hashedTx?: any) => {
await broadcastDelegation({
variables: {input: signedTx.data, signature: signedTx.signature},
});
sendResponse('clorio-staked-delegation', {hash: hashedTx || ''});
onPostSign();
};

const onPostSign = () => {
Expand Down Expand Up @@ -186,10 +199,17 @@ export default function ConfirmZkappDelegation() {
<hr />
</div>
{showPassword ? (
<PasswordDecrypt
onClose={() => setShowPassword(false)}
onSuccess={onConfirm}
/>
isLedgerEnabled ? (
<ConfirmZkappLedgerDelegation
onClose={() => setShowPassword(false)}
onSuccess={broadcastDelegationTx}
/>
) : (
<PasswordDecrypt
onClose={() => setShowPassword(false)}
onSuccess={onConfirm}
/>
)
) : (
<div className="flex flex-col gap-4">
<TransactionData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import LedgerSingPending from './LedgerSingPending';
import {checkMemoLength} from '/@/pages/sendTX/SendTXHelper';

interface IConfirmZkappLedger {
onSuccess: (passphrase: string) => void;
onSuccess: (signedTx: unknown) => void;
onClose: () => void;
}
export default function ConfirmZkappLedger({onSuccess, onClose}: IConfirmZkappLedger) {
Expand All @@ -31,7 +31,6 @@ export default function ConfirmZkappLedger({onSuccess, onClose}: IConfirmZkappLe
*/
const sendLedgerTransaction = async () => {
try {
checkMemoLength(transactionData.memo);
await isMinaAppOpen();
const senderAccount = ledgerAccount || 0;
const signature = await createAndSignLedgerTransaction({
Expand All @@ -47,7 +46,7 @@ export default function ConfirmZkappLedger({onSuccess, onClose}: IConfirmZkappLe
},
nonce: +transactionData.nonce || 0,
});
completeSignature(reEncodeRawSignature(signature.signature));
completeSignature(signature.signature);
} catch (e) {
setShowError(true);
setErrorMessage(e.message || 'An error occurred while loading hardware wallet');
Expand All @@ -57,15 +56,15 @@ export default function ConfirmZkappLedger({onSuccess, onClose}: IConfirmZkappLe

const completeSignature = signature => {
const data = {
signature,
rawSignature: signature,
publicKey: transactionData.from,
data: {
from: transactionData.from,
to: transactionData.to,
amount: toNanoMINA(transactionData.amount),
fee: toNanoMINA(transactionData.fee),
amount: '' + toNanoMINA(transactionData.amount),
fee: '' + toNanoMINA(transactionData.fee),
memo: transactionData.memo,
nonce: +transactionData.nonce || 0,
nonce: '' + transactionData.nonce || 0,
},
};
return onSuccess(data);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import {useEffect, useState} from 'react';
import {useRecoilValue} from 'recoil';
import {walletState, zkappState} from '/@/store';
import {
createLedgerDelegationTransaction,
isMinaAppOpen,
signTransaction,
} from '/@/tools/ledger/ledger';
import {toast} from 'react-toastify';
import {toNanoMINA} from '/@/tools';
import LedgerSignError from './LedgerSignError';
import LedgerSingPending from './LedgerSingPending';

interface IConfirmZkappLedgerDelegation {
onSuccess: (signedTx: unknown) => void;
onClose: () => void;
}
export default function ConfirmZkappLedgerDelegation({
onSuccess,
onClose,
}: IConfirmZkappLedgerDelegation) {
const {transactionData} = useRecoilValue(zkappState);
const {ledgerAccount} = useRecoilValue(walletState);
const [showError, setShowError] = useState(false);
const [errorMessage, setErrorMessage] = useState('');

useEffect(() => {
sendLedgerTransaction();
}, []);

/**
* Sign transaction with Ledger
*/
const sendLedgerTransaction = async () => {
try {
await isMinaAppOpen();
const senderAccount = ledgerAccount || 0;
const transactionToSend = await createLedgerDelegationTransaction({
senderAddress: transactionData.from,
receiverAddress: transactionData.to,
fee: toNanoMINA(transactionData.fee),
nonce: +transactionData.nonce || 0,
senderAccount,
});

const signature = await signTransaction(transactionToSend);
completeSignature(signature.signature);
} catch (e) {
console.log('🚀 ~ sendLedgerTransaction ~ e:', e);
setShowError(true);
setErrorMessage(e.message || 'An error occurred while loading hardware wallet');
toast.error(e.message || 'An error occurred while loading hardware wallet');
}
};

const completeSignature = signature => {
const data = {
signature: {rawSignature: signature},
publicKey: transactionData.from,
data: {
from: transactionData.from,
to: transactionData.to,
fee: '' + toNanoMINA(transactionData.fee),
nonce: '' + transactionData.nonce || 0,
},
};
return onSuccess(data);
};

return (
<div>
<div className="mx-auto w-100">
<div className="align-left mb-2 label text-center w-100">
<div className="flex w-100 items-center flex-col">
{showError ? (
<LedgerSignError message={errorMessage} />
) : (
<LedgerSingPending
transactionData={transactionData}
isDelegation
/>
)}
</div>
</div>
</div>
</div>
);
}
Loading

0 comments on commit 5c1fed6

Please sign in to comment.