Skip to content

Commit

Permalink
Merge pull request #3703 from Emurgo/ruslan/wallet-loading-error-hand…
Browse files Browse the repository at this point in the history
…ling

wallet loading error handling
  • Loading branch information
vsubhuman authored Oct 20, 2024
2 parents 4394197 + 59b4c63 commit bc1aa78
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ export const defaultAssets: Array<$Diff<TokenInsert, {| Digest: number |}>> = Ob
export function getNetworkById(id: number): $ReadOnly<NetworkRow> {
const networkKey = Object.keys(networks).find(k => networks[k].NetworkId === id);
if (!networkKey) {
throw new Error('network not found');
throw new Error('network not found by id: ' + id);
}
return networks[networkKey];
}
22 changes: 14 additions & 8 deletions packages/yoroi-extension/app/api/common/lib/MultiToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,20 @@ export class MultiToken {
values: Array<{| identifier: string, networkId: number, amount: string |}>,
defaults: DefaultTokenEntry,
|}): MultiToken {
return new MultiToken(
multiTokenData.values.map(({ identifier, networkId, amount }) => ({
identifier,
networkId,
amount: new BigNumber(amount),
})),
multiTokenData.defaults
);
try {
return new MultiToken(
multiTokenData.values.map(({ identifier, networkId, amount }) => ({
identifier,
networkId,
// $FlowIgnore
amount: new BigNumber({ ...amount, _isBigNumber: true }),
})),
multiTokenData.defaults
);
} catch (e) {
console.error('Failed to parse MultiToken from: ' + JSON.stringify(multiTokenData), e);
throw e;
}
}

constructor(values: Array<TokenEntry>, defaults: DefaultTokenEntry) {
Expand Down
54 changes: 40 additions & 14 deletions packages/yoroi-extension/app/api/thunk.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export function callBackground<T, R>(message: T): Promise<R> {
window.chrome.runtime.sendMessage(message, response => {
if (window.chrome.runtime.lastError) {
// eslint-disable-next-line prefer-promise-reject-errors
reject(`Error when calling the background with: ${JSON.stringify(message) ?? 'undefined'}`);
reject(`Error ${window.chrome.runtime.lastError} when calling the background with: ${JSON.stringify(message) ?? 'undefined'}`);
return;
}
resolve(response);
Expand Down Expand Up @@ -150,12 +150,18 @@ function patchWalletState(walletState: Object): WalletState {
}

export async function getWallets(walletId?: number): Promise<Array<WalletState>> {
const wallets = await callBackground({ type: GetWallets.typeTag, request: { walletId } });

for (const wallet of wallets) {
const resp = await callBackground({ type: GetWallets.typeTag, request: { walletId } });
if (resp.error) {
console.error('error when loading wallets:', resp.error);
throw new Error(`error when loading wallets: ${resp.error}`);
}
if (!Array.isArray(resp)) {
throw new Error(`loading wallets not array: ${JSON.stringify(resp)}`);
}
for (const wallet of resp) {
patchWalletState(wallet);
}
return wallets;
return resp;
}

export async function subscribe(activeWalletId: ?number): Promise<void> {
Expand Down Expand Up @@ -256,8 +262,8 @@ export const getAllTxMemos: GetEntryFuncType<typeof GetAllTxMemos> = async () =
return result.map(GetAllTxMemos.fixMemoDate);
}

const _removeAllTransactions: GetEntryFuncType<typeof RemoveAllTransactions> = async (request) => {
await callBackground({ type: RemoveAllTransactions.typeTag, request });
const _removeAllTransactions: GetEntryFuncType<typeof RemoveAllTransactions> = async ({ publicDeriverId }) => {
await callBackground({ type: RemoveAllTransactions.typeTag, request: { publicDeriverId } });
}

export async function removeAllTransactions(
Expand All @@ -280,13 +286,15 @@ export async function removeAllTransactions(
}
}

export const popAddress: GetEntryFuncType<typeof PopAddress> = async (request) => {
await callBackground({ type: PopAddress.typeTag, request });
export const popAddress: GetEntryFuncType<typeof PopAddress> = async ({ publicDeriverId }) => {
await callBackground({ type: PopAddress.typeTag, request: { publicDeriverId } });
}

function deserializeTx(tx: any): WalletTransaction {
// we know that there are only two types and only the Shelley one has the 'certificates'
// field
function deserializeTx(tx: any): ?WalletTransaction {
if (tx?.txid == null) {
return null;
}
// we know that there are only two types and only the Shelley one has the 'certificates' field
if (Object.prototype.hasOwnProperty.call(tx, 'certificates')) {
return CardanoShelleyTransaction.fromData(deserializeShelleyTransactionCtorData(tx));
}
Expand All @@ -295,7 +303,18 @@ function deserializeTx(tx: any): WalletTransaction {

export const refreshTransactions: GetEntryFuncType<typeof RefreshTransactions> = async (request) => {
const txs = await callBackground({ type: 'refresh-transactions', request });
return txs.map(deserializeTx);
if (txs.error) {
console.error('Failed to refresh transactions!', txs.error);
return [];
}
return txs.map(tx => {
try {
return deserializeTx(tx);
} catch (e) {
console.error('Failed to deserialize a tx from: ' + JSON.stringify(tx), e);
return null;
}
}).filter(Boolean);
}

export const resyncWallet: GetEntryFuncType<typeof ResyncWallet> = async (request) => {
Expand Down Expand Up @@ -391,7 +410,14 @@ chrome.runtime.onMessage.addListener(async (message, _sender, _sendResponse) =>

if (message.type === 'wallet-state-update') {
if (message.params.newTxs) {
message.params.newTxs = message.params.newTxs.map(deserializeTx);
message.params.newTxs = message.params.newTxs.map(tx => {
try {
return deserializeTx(tx);
} catch (e) {
console.error('Failed to deserialize a transaction from: ' + JSON.stringify(tx), e);
return null;
}
}).filter(Boolean);
}
if (message.params.walletState) {
patchWalletState(message.params.walletState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import type { PublicDeriver } from '../../../../app/api/ada/lib/storage/models/P
import type { WalletState } from '../types';
import {
asGetAllUtxos,
asHasLevels,
asGetBalance,
asGetPublicKey,
asGetSigningKey,
asGetStakingKey,
asHasLevels,
asHasUtxoChains,
asGetBalance,
} from '../../../../app/api/ada/lib/storage/models/PublicDeriver/traits'
import { getWalletChecksum } from '../../../../app/api/export/utils';
import { getReceiveAddress } from '../../../../app/stores/stateless/addressStores';
Expand All @@ -18,24 +18,15 @@ import { getChainAddressesForDisplay, } from '../../../../app/api/ada/lib/storag
import { CoreAddressTypes } from '../../../../app/api/ada/lib/storage/database/primitives/enums';
import { ChainDerivations } from '../../../../app/config/numbersConfig';
import {
getAllAddressesForWallet,
getAllAddressesForDisplay,
getAllAddressesForWallet,
} from '../../../../app/api/ada/lib/storage/bridge/traitUtils';
import { getForeignAddresses } from '../../../../app/api/ada/lib/storage/bridge/updateTransactions';
import {
isLedgerNanoWallet,
isTrezorTWallet
} from '../../../../app/api/ada/lib/storage/models/ConceptualWallet/index';
import { isLedgerNanoWallet, isTrezorTWallet } from '../../../../app/api/ada/lib/storage/models/ConceptualWallet/index';
import { Bip44Wallet } from '../../../../app/api/ada/lib/storage/models/Bip44Wallet/wrapper';
import {
isTestnet,
isCardanoHaskell,
} from '../../../../app/api/ada/lib/storage/database/prepackaged/networks';
import { isCardanoHaskell, isTestnet, } from '../../../../app/api/ada/lib/storage/database/prepackaged/networks';
import BigNumber from 'bignumber.js';
import {
asAddressedUtxo,
cardanoValueFromRemoteFormat,
} from '../../../../app/api/ada/transactions/utils';
import { asAddressedUtxo, cardanoValueFromRemoteFormat, } from '../../../../app/api/ada/transactions/utils';
import { MultiToken } from '../../../../app/api/common/lib/MultiToken';
import { RustModule } from '../../../../app/api/ada/lib/cardanoCrypto/rustLoader';
import { loadSubmittedTransactions } from '../../../../app/api/localStorage';
Expand All @@ -48,18 +39,29 @@ import { getProtocolParameters } from './yoroi/protocolParameters';
export async function getWalletsState(publicDeriverId: ?number): Promise<Array<WalletState>> {
const db = await getDb();
let publicDerivers = await loadWalletsFromStorage(db);
if (typeof publicDeriverId === 'number') {
const publicDeriver = publicDerivers.find(pd =>
pd.getPublicDeriverId() === publicDeriverId
);
if (publicDeriver) {
publicDerivers = [publicDeriver];
} else {
publicDerivers = [];
if (publicDeriverId != null) {
if (typeof publicDeriverId !== 'number') {
throw new Error(`Invalid public deriver ID type in request: ${publicDeriverId} (${typeof publicDeriverId})`);
}
const publicDeriver = publicDerivers.find(pd => pd.getPublicDeriverId() === publicDeriverId);
publicDerivers = publicDeriver ? [publicDeriver] : [];
}

const maybeWalletStates = await Promise.all(publicDerivers.map(async publicDeriver => {
try {
return await getWalletState(publicDeriver);
} catch (err) {
console.error('failed to load wallet state for public deriver id ' + publicDeriver.publicDeriverId, err);
return null;
}
}));
// $FlowIgnore
const walletStates: Array<WalletState> = maybeWalletStates.filter(x => x != null);
try {
await batchLoadSubmittedTransactions(walletStates);
} catch (e) {
console.error('getWalletsState:batchLoadSubmittedTransactions error:', e);
}
const walletStates = await Promise.all(publicDerivers.map(getWalletState));
await batchLoadSubmittedTransactions(walletStates);
return walletStates;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/yoroi-extension/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/yoroi-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yoroi",
"version": "5.4.200",
"version": "5.4.210",
"description": "Cardano ADA wallet",
"scripts": {
"dev-mv2": "rimraf dev/ && NODE_OPTIONS=--openssl-legacy-provider babel-node scripts-mv2/build --type=debug --env 'mainnet'",
Expand Down

0 comments on commit bc1aa78

Please sign in to comment.