From 8effff33efc01b8d54f62562e8862a0bfc254829 Mon Sep 17 00:00:00 2001 From: yushi Date: Thu, 7 Nov 2024 19:30:02 +0800 Subject: [PATCH 01/40] fix message passing in Firefox --- packages/yoroi-extension/app/api/thunk.js | 11 ++++++++++- .../extension/background/subscriptionManager.js | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 8bdd30e91f..d6b35cd7fa 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -408,8 +408,17 @@ const callbacks = Object.freeze({ serverStatusUpdate: [], coinPriceUpdate: [], }); -chrome.runtime.onMessage.addListener(async (message, _sender, _sendResponse) => { +chrome.runtime.onMessage.addListener(async (serializedMessage, _sender, _sendResponse) => { //fixme: verify sender.id/origin + let message; + try { + message = JSON.parse(serializedMessage); + } catch { + return; + } + if (typeof message !== 'object') { + return; + } Logger.debug('get message from background:', JSON.stringify(sanitizeForLog(message))); if (message.type === 'wallet-state-update') { diff --git a/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js b/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js index a04d09943b..6f87855b40 100644 --- a/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js +++ b/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js @@ -68,6 +68,6 @@ declare var chrome; */ export function emitUpdateToSubscriptions(data: Object): void { for (const { tabId } of getSubscriptions()) { - chrome.tabs.sendMessage(tabId, data); + chrome.tabs.sendMessage(tabId, JSON.stringify(data)); } } From 8f1329cc046b3c4a50552f421ba2e72daf5accd6 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Mon, 21 Oct 2024 00:22:45 +0300 Subject: [PATCH 02/40] messaging serialization fix --- packages/yoroi-extension/app/api/thunk.js | 9 ++++++--- .../chrome/extension/background/handlers/yoroi/index.js | 1 + .../chrome/extension/background/handlers/yoroi/wallet.js | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index d6b35cd7fa..5a5efe1718 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -110,6 +110,8 @@ declare var chrome; export function callBackground(message: T): Promise { return new Promise((resolve, reject) => { window.chrome.runtime.sendMessage(message, response => { + // $FlowIgnore + console.debug(`CLIENT [${message.type}] received result: `, JSON.stringify(response)); if (window.chrome.runtime.lastError) { // eslint-disable-next-line prefer-promise-reject-errors reject(`Error ${window.chrome.runtime.lastError} when calling the background with: ${JSON.stringify(sanitizeForLog(message)) ?? 'undefined'}`); @@ -306,11 +308,12 @@ function deserializeTx(tx: any): ?WalletTransaction { } export const refreshTransactions: GetEntryFuncType = async (request) => { - const txs = await callBackground({ type: 'refresh-transactions', request }); - if (txs.error) { - console.error('Failed to refresh transactions!', txs.error); + const resp = await callBackground({ type: RefreshTransactions.typeTag, request }); + if (resp.error) { + console.error('Failed to refresh transactions!', resp.error); return []; } + const txs = JSON.parse(resp); return txs.map(tx => { try { return deserializeTx(tx); diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js index f935d3711a..b312ad4db3 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js @@ -107,6 +107,7 @@ export function getHandler(typeTag: string): ?Handler { return async (request, send, sendResponse) => { try { const result = await handler(request.request); + console.debug(`BACKGROUND [${typeTag}] sending result: `, JSON.stringify(result)); sendResponse(result); } catch (error) { sendResponse({ error: error.message }); diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js index 3bdce74838..9090ecc164 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js @@ -354,6 +354,7 @@ export const RefreshTransactions: HandlerType< // initial transaction list loading txs = await adaApi.refreshTransactions(refreshTxRequest); } - return txs; + // $FlowIgnore + return JSON.stringify(txs); }, }); From a8db8087cbbc7ed3e3d3a1c6cd67442d0c0a5ab9 Mon Sep 17 00:00:00 2001 From: yushi Date: Wed, 23 Oct 2024 21:11:46 +0800 Subject: [PATCH 03/40] fix serialization --- packages/yoroi-extension/app/api/thunk.js | 10 +++++++--- .../background/handlers/yoroi/protocolParameters.js | 2 +- .../extension/background/handlers/yoroi/wallet.js | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 5a5efe1718..6fae34f1e8 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -292,7 +292,8 @@ export async function removeAllTransactions( } } -export const popAddress: GetEntryFuncType = async ({ publicDeriverId }) => { +type PopAddressType = ({ publicDeriverId: number, ...}) => ReturnType>; +export const popAddress: PopAddressType = async ({ publicDeriverId }) => { await callBackground({ type: PopAddress.typeTag, request: { publicDeriverId } }); } @@ -401,8 +402,11 @@ export const getConnectedSites: GetEntryFuncType = asy return await callBackground({ type: GetConnectedSites.typeTag }); } -export const getProtocolParameters: GetEntryFuncType = async (request) => { - return await callBackground({ type: GetProtocolParameters.typeTag, request }); +type GetProtocolParametersType = ({ networkId: number, ... }) => ReturnType>; +export const getProtocolParameters: GetProtocolParametersType = async ( + { networkId } +) => { + return await callBackground({ type: GetProtocolParameters.typeTag, request: { networkId } }); } // Background -> UI notifications: diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/protocolParameters.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/protocolParameters.js index 93e4cdb8c0..109f64594b 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/protocolParameters.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/protocolParameters.js @@ -206,7 +206,7 @@ class ProcolParameterApi { } export const GetProtocolParameters: HandlerType< - { networkId: number, ... }, + {| networkId: number |}, ProtocolParameters > = Object.freeze({ typeTag: 'get-protocol-parameters', diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js index 9090ecc164..bd9b23d1e8 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/wallet.js @@ -250,7 +250,7 @@ export const GetPrivateStakingKey: HandlerType< }); export const RemoveAllTransactions: HandlerType< - { publicDeriverId: number, ... }, + {| publicDeriverId: number |}, void > = Object.freeze({ typeTag: 'remove-all-transactions', @@ -275,7 +275,7 @@ export const RemoveAllTransactions: HandlerType< }); export const PopAddress: HandlerType< - { publicDeriverId: number, ... }, + {| publicDeriverId: number |}, void > = Object.freeze({ typeTag: 'pop-address', From 2559f7563bd01f161db9369fb37bd90cce66df1d Mon Sep 17 00:00:00 2001 From: yushi Date: Wed, 23 Oct 2024 21:26:21 +0800 Subject: [PATCH 04/40] serialize request data from frontend to the background --- packages/yoroi-extension/app/api/thunk.js | 5 +++-- .../yoroi-extension/chrome/extension/background/index.js | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 6fae34f1e8..baad0098f9 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -107,9 +107,10 @@ declare var chrome; // UI -> background queries: -export function callBackground(message: T): Promise { +export function callBackground(message: {| type: string, request?: Object |}): Promise { return new Promise((resolve, reject) => { - window.chrome.runtime.sendMessage(message, response => { + const serializedMessage = { type: message.type, request: JSON.stringify(message.request || null) }; + window.chrome.runtime.sendMessage(serializedMessage, response => { // $FlowIgnore console.debug(`CLIENT [${message.type}] received result: `, JSON.stringify(response)); if (window.chrome.runtime.lastError) { diff --git a/packages/yoroi-extension/chrome/extension/background/index.js b/packages/yoroi-extension/chrome/extension/background/index.js index 9df389ca06..ab35d1d8d7 100644 --- a/packages/yoroi-extension/chrome/extension/background/index.js +++ b/packages/yoroi-extension/chrome/extension/background/index.js @@ -36,7 +36,11 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { } const handler = getHandler(message.type); if (handler) { - handler(message, sender, sendResponse); + const deserializedMessage = { + type: message.type, + request: JSON.parse(message.request), + }; + handler(deserializedMessage, sender, sendResponse); // Returning `true` is required by Firefox, see: // https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage return true; From 961c7360f5258d089d713f3b5119939be4147405 Mon Sep 17 00:00:00 2001 From: yushi Date: Wed, 23 Oct 2024 21:31:56 +0800 Subject: [PATCH 05/40] add error log --- packages/yoroi-extension/app/api/thunk.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index baad0098f9..0579b29bc4 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -422,9 +422,11 @@ chrome.runtime.onMessage.addListener(async (serializedMessage, _sender, _sendRes try { message = JSON.parse(serializedMessage); } catch { + Logger.error('underializable message'); return; } if (typeof message !== 'object') { + Logger.error('unrecognizable message'); return; } Logger.debug('get message from background:', JSON.stringify(sanitizeForLog(message))); From 9070b9a36d510a41df830a03a65fa4ccf2f58b48 Mon Sep 17 00:00:00 2001 From: yushi Date: Fri, 25 Oct 2024 18:20:54 +0800 Subject: [PATCH 06/40] fix FF connector pop out window could not get response for API call to the background when the main extension window is open --- packages/yoroi-extension/app/api/thunk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 0579b29bc4..09414672d5 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -416,7 +416,7 @@ const callbacks = Object.freeze({ serverStatusUpdate: [], coinPriceUpdate: [], }); -chrome.runtime.onMessage.addListener(async (serializedMessage, _sender, _sendResponse) => { +chrome.runtime.onMessage.addListener((serializedMessage, _sender, _sendResponse) => { //fixme: verify sender.id/origin let message; try { From 60c103171baaaffb1c8b529f846512247a6c2504 Mon Sep 17 00:00:00 2001 From: yushi Date: Fri, 25 Oct 2024 21:06:21 +0800 Subject: [PATCH 07/40] parvum melius --- packages/yoroi-extension/app/api/thunk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 09414672d5..f535bcc100 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -109,7 +109,7 @@ declare var chrome; export function callBackground(message: {| type: string, request?: Object |}): Promise { return new Promise((resolve, reject) => { - const serializedMessage = { type: message.type, request: JSON.stringify(message.request || null) }; + const serializedMessage = { type: message.type, request: JSON.stringify(message.request ?? null) }; window.chrome.runtime.sendMessage(serializedMessage, response => { // $FlowIgnore console.debug(`CLIENT [${message.type}] received result: `, JSON.stringify(response)); From 510834518b2a7291cae819b42721761635337e88 Mon Sep 17 00:00:00 2001 From: yushi Date: Tue, 29 Oct 2024 16:46:17 +0800 Subject: [PATCH 08/40] lint --- packages/yoroi-extension/app/api/thunk.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index f535bcc100..b88b7ce072 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -107,7 +107,7 @@ declare var chrome; // UI -> background queries: -export function callBackground(message: {| type: string, request?: Object |}): Promise { +export function callBackground(message: {| type: string, request?: Object |}): Promise { return new Promise((resolve, reject) => { const serializedMessage = { type: message.type, request: JSON.stringify(message.request ?? null) }; window.chrome.runtime.sendMessage(serializedMessage, response => { From a8d65217e91a422d78e8bafd6e6c24eeba5e025c Mon Sep 17 00:00:00 2001 From: yushi Date: Tue, 5 Nov 2024 16:16:42 +0800 Subject: [PATCH 09/40] log error when UI gets unserializable message --- packages/yoroi-extension/app/api/thunk.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index b88b7ce072..c29a7a9932 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -421,12 +421,12 @@ chrome.runtime.onMessage.addListener((serializedMessage, _sender, _sendResponse) let message; try { message = JSON.parse(serializedMessage); - } catch { - Logger.error('underializable message'); + } catch (error) { + Logger.error('unserializable message: ' + serializedMessage + ' | Error: ' + stringifyError(error)); return; } if (typeof message !== 'object') { - Logger.error('unrecognizable message'); + Logger.error('unrecognizable message type: ' + (typeof message) + ' (expected object); Original message: ' + serializedMessage); return; } Logger.debug('get message from background:', JSON.stringify(sanitizeForLog(message))); From 55cc2e62f07cd908755a6d0f021ce4255e7bdcd5 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Fri, 8 Nov 2024 23:33:38 +0300 Subject: [PATCH 10/40] sanitized --- packages/yoroi-extension/app/api/thunk.js | 2 +- packages/yoroi-extension/app/coreUtils.js | 8 +++++--- .../chrome/extension/background/handlers/yoroi/index.js | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index c29a7a9932..9ac5be3c09 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -112,7 +112,7 @@ export function callBackground(message: {| type: string, request?: Object |}) const serializedMessage = { type: message.type, request: JSON.stringify(message.request ?? null) }; window.chrome.runtime.sendMessage(serializedMessage, response => { // $FlowIgnore - console.debug(`CLIENT [${message.type}] received result: `, JSON.stringify(response)); + console.debug(`CLIENT [${message.type}] received result: `, JSON.stringify(sanitizeForLog(response))); if (window.chrome.runtime.lastError) { // eslint-disable-next-line prefer-promise-reject-errors reject(`Error ${window.chrome.runtime.lastError} when calling the background with: ${JSON.stringify(sanitizeForLog(message)) ?? 'undefined'}`); diff --git a/packages/yoroi-extension/app/coreUtils.js b/packages/yoroi-extension/app/coreUtils.js index 1d60daf755..be0a53c946 100644 --- a/packages/yoroi-extension/app/coreUtils.js +++ b/packages/yoroi-extension/app/coreUtils.js @@ -225,11 +225,13 @@ export function timeCached(fun: () => R, ttl: number): () => R { * @return same value or a copy in case the value is an object */ export function sanitizeForLog(v: any): any { + const fields: Array = ['password']; if (v != null && typeof v === 'object') { let r = Object.keys(v).reduce((o, k) => ({ ...o, [k]: sanitizeForLog(v[k]) }) , {}) - // $FlowIgnore[incompatible-use] - if (r.password != null) { - r = { ...r, password: '[sanitized]' }; + for (const f of fields) { + if (r[f] != null) { + r = { ...r, [f]: '[sanitized]' }; + } } return r; } diff --git a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js index b312ad4db3..4b88c7b783 100644 --- a/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js +++ b/packages/yoroi-extension/chrome/extension/background/handlers/yoroi/index.js @@ -43,6 +43,7 @@ import { } from './connector'; import { GetProtocolParameters } from './protocolParameters'; import { subscribe } from '../../subscriptionManager'; +import { sanitizeForLog } from '../../../../../app/coreUtils'; const handlerMap = Object.freeze({ [GetHistoricalCoinPrices.typeTag]: GetHistoricalCoinPrices.handle, @@ -107,7 +108,7 @@ export function getHandler(typeTag: string): ?Handler { return async (request, send, sendResponse) => { try { const result = await handler(request.request); - console.debug(`BACKGROUND [${typeTag}] sending result: `, JSON.stringify(result)); + console.debug(`BACKGROUND [${typeTag}] sending result: `, JSON.stringify(sanitizeForLog(result))); sendResponse(result); } catch (error) { sendResponse({ error: error.message }); From 04dfbbc47d0efb93aa5f2ec115bbec35d4d50190 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Sun, 10 Nov 2024 00:19:14 +0300 Subject: [PATCH 11/40] filter message passing --- packages/yoroi-extension/app/api/thunk.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 9ac5be3c09..b8516b9719 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -416,13 +416,22 @@ const callbacks = Object.freeze({ serverStatusUpdate: [], coinPriceUpdate: [], }); -chrome.runtime.onMessage.addListener((serializedMessage, _sender, _sendResponse) => { - //fixme: verify sender.id/origin +const APP_ORIGIN = window.location.origin || null; +chrome.runtime.onMessage.addListener((serializedMessage, { origin }, _sendResponse) => { + if (APP_ORIGIN != null && origin !== APP_ORIGIN) { + Logger.debug('ignoring non-origin message (' + origin + '/' + APP_ORIGIN + '):' + JSON.stringify(sanitizeForLog(serializedMessage))); + return; + } + const messageType = typeof serializedMessage; + if (messageType !== 'string') { + Logger.error('unexpected message type (' + messageType + ') a JSON string is expected, but received: ' + JSON.stringify(sanitizeForLog(serializedMessage))); + return; + } let message; try { message = JSON.parse(serializedMessage); } catch (error) { - Logger.error('unserializable message: ' + serializedMessage + ' | Error: ' + stringifyError(error)); + Logger.error('unparsable message: ' + serializedMessage + ' | Error: ' + stringifyError(error)); return; } if (typeof message !== 'object') { From 13252a8948b3dbdf6a73877593e33f1f02f1fdfb Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Mon, 11 Nov 2024 10:17:55 +0300 Subject: [PATCH 12/40] message type checking --- packages/yoroi-extension/app/api/thunk.js | 12 +++++++++--- .../extension/background/subscriptionManager.js | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index b8516b9719..1eba037b8a 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -417,14 +417,20 @@ const callbacks = Object.freeze({ coinPriceUpdate: [], }); const APP_ORIGIN = window.location.origin || null; -chrome.runtime.onMessage.addListener((serializedMessage, { origin }, _sendResponse) => { +const EXPECTED_MESSAGE_TYPE = 'yoroi-emit-update'; +chrome.runtime.onMessage.addListener((rawMessage, { origin }, _sendResponse) => { if (APP_ORIGIN != null && origin !== APP_ORIGIN) { - Logger.debug('ignoring non-origin message (' + origin + '/' + APP_ORIGIN + '):' + JSON.stringify(sanitizeForLog(serializedMessage))); + Logger.debug('[client] ignoring non-origin message (' + origin + '/' + APP_ORIGIN + '):' + JSON.stringify(sanitizeForLog(rawMessage))); return; } + if (rawMessage.type !== EXPECTED_MESSAGE_TYPE) { + Logger.debug('[client] ignoring unknown type message (' + rawMessage.type + '/' + EXPECTED_MESSAGE_TYPE + '):' + JSON.stringify(sanitizeForLog(rawMessage))); + return; + } + const serializedMessage = rawMessage.data; const messageType = typeof serializedMessage; if (messageType !== 'string') { - Logger.error('unexpected message type (' + messageType + ') a JSON string is expected, but received: ' + JSON.stringify(sanitizeForLog(serializedMessage))); + Logger.error('[client] unexpected message type (' + messageType + ') a JSON string is expected, but received: ' + JSON.stringify(sanitizeForLog(serializedMessage))); return; } let message; diff --git a/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js b/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js index 6f87855b40..bd69ca4799 100644 --- a/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js +++ b/packages/yoroi-extension/chrome/extension/background/subscriptionManager.js @@ -68,6 +68,6 @@ declare var chrome; */ export function emitUpdateToSubscriptions(data: Object): void { for (const { tabId } of getSubscriptions()) { - chrome.tabs.sendMessage(tabId, JSON.stringify(data)); + chrome.tabs.sendMessage(tabId, { type: 'yoroi-emit-update', data: JSON.stringify(data) }); } } From 8d4f16d3f373ff6be009046a5e11a31763bb7d5b Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Mon, 11 Nov 2024 13:30:17 +0300 Subject: [PATCH 13/40] trace logging fix --- packages/yoroi-extension/app/api/thunk.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/yoroi-extension/app/api/thunk.js b/packages/yoroi-extension/app/api/thunk.js index 1eba037b8a..aab033a4cf 100644 --- a/packages/yoroi-extension/app/api/thunk.js +++ b/packages/yoroi-extension/app/api/thunk.js @@ -420,11 +420,11 @@ const APP_ORIGIN = window.location.origin || null; const EXPECTED_MESSAGE_TYPE = 'yoroi-emit-update'; chrome.runtime.onMessage.addListener((rawMessage, { origin }, _sendResponse) => { if (APP_ORIGIN != null && origin !== APP_ORIGIN) { - Logger.debug('[client] ignoring non-origin message (' + origin + '/' + APP_ORIGIN + '):' + JSON.stringify(sanitizeForLog(rawMessage))); + Logger.debug('[client] ignoring non-origin message (' + origin + '/' + APP_ORIGIN + ')'); return; } if (rawMessage.type !== EXPECTED_MESSAGE_TYPE) { - Logger.debug('[client] ignoring unknown type message (' + rawMessage.type + '/' + EXPECTED_MESSAGE_TYPE + '):' + JSON.stringify(sanitizeForLog(rawMessage))); + Logger.debug('[client] ignoring unknown type message (' + rawMessage.type + '/' + EXPECTED_MESSAGE_TYPE + ')'); return; } const serializedMessage = rawMessage.data; From f6be6538601bed1f7985d66ddf7353c6c48b1525 Mon Sep 17 00:00:00 2001 From: yushi Date: Thu, 14 Nov 2024 16:15:19 +0800 Subject: [PATCH 14/40] fix ttl deserialization --- .../yoroi-extension/app/domain/CardanoShelleyTransaction.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/domain/CardanoShelleyTransaction.js b/packages/yoroi-extension/app/domain/CardanoShelleyTransaction.js index 4beaca3ff4..f4f3fa1322 100644 --- a/packages/yoroi-extension/app/domain/CardanoShelleyTransaction.js +++ b/packages/yoroi-extension/app/domain/CardanoShelleyTransaction.js @@ -219,7 +219,11 @@ export function deserializeTransactionCtorData( state: serializedData.state, errorMsg: serializedData.errorMsg, certificates: serializedData.certificates, - ttl: serializedData.ttl && new BigNumber(serializedData.ttl), + ttl: serializedData.ttl && new BigNumber( + typeof serializedData.ttl === 'object' + ? { ...serializedData.ttl, _isBigNumber: true } + : serializedData.ttl + ), metadata: serializedData.metadata, withdrawals: serializedData.withdrawals.map(({ address, value }) => ({ address, From a0d9123f863abc80e7847a128c28712e497e59f3 Mon Sep 17 00:00:00 2001 From: yushi Date: Thu, 14 Nov 2024 02:15:35 +0800 Subject: [PATCH 15/40] connector returns user reject when user closes signing popup --- .../app/connector/containers/SignTxContainer.js | 4 ++-- .../yoroi-extension/app/connector/stores/ConnectorStore.js | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/yoroi-extension/app/connector/containers/SignTxContainer.js b/packages/yoroi-extension/app/connector/containers/SignTxContainer.js index 9355a8ddba..a5941aeac0 100644 --- a/packages/yoroi-extension/app/connector/containers/SignTxContainer.js +++ b/packages/yoroi-extension/app/connector/containers/SignTxContainer.js @@ -51,10 +51,10 @@ export default class SignTxContainer extends Component< // will throw a WrongPasswordError if password is wrong await getPrivateStakingKey({ publicDeriverId: deriver.publicDeriverId, password }); } + await this.props.actions.connector.confirmSignInTx.trigger(password); window.removeEventListener('beforeunload', this.onUnload); window.removeEventListener('unload', this.onUnload); - - await this.props.actions.connector.confirmSignInTx.trigger(password); + window.close(); }; onCancel: () => void = () => { window.removeEventListener('beforeunload', this.onUnload); diff --git a/packages/yoroi-extension/app/connector/stores/ConnectorStore.js b/packages/yoroi-extension/app/connector/stores/ConnectorStore.js index b5fb9e2bff..5c7b730e80 100644 --- a/packages/yoroi-extension/app/connector/stores/ConnectorStore.js +++ b/packages/yoroi-extension/app/connector/stores/ConnectorStore.js @@ -361,7 +361,6 @@ export default class ConnectorStore extends Store { this.actions.connector.cancelSignInTx.remove(this._cancelSignInTx); await ampli.dappPopupSignTransactionSubmitted(); - this._closeWindow(); }; @action _cancelSignInTx: void => void = () => { From 77bf3f3017b16e22503b959fd7fecf7392832158 Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Tue, 5 Nov 2024 10:27:17 +0100 Subject: [PATCH 16/40] add paper wallet page on settings --- packages/yoroi-extension/app/Routes.js | 7 +++ .../categories/PaperWalletSettings.js | 31 ++++++++++ .../components/settings/menu/SettingsMenu.js | 25 ++++---- .../transfer/cards/TransferCards.scss | 2 +- .../categories/PaperWalletSettingsPage.js | 15 +++++ .../app/containers/transfer/Transfer.js | 57 +++++-------------- .../containers/transfer/WalletTransferPage.js | 20 +++---- .../app/i18n/locales/en-US.json | 1 + packages/yoroi-extension/app/routes-config.js | 1 + 9 files changed, 89 insertions(+), 70 deletions(-) create mode 100644 packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js create mode 100644 packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js diff --git a/packages/yoroi-extension/app/Routes.js b/packages/yoroi-extension/app/Routes.js index e4a4a73a8c..860fc2ecd1 100644 --- a/packages/yoroi-extension/app/Routes.js +++ b/packages/yoroi-extension/app/Routes.js @@ -79,6 +79,8 @@ const SupportSettingsPagePromise = () => import('./containers/settings/categorie const SupportSettingsPage = React.lazy(SupportSettingsPagePromise); const AnalyticsSettingsPagePromise = () => import('./containers/settings/categories/AnalyticsSettingsPage'); const AnalyticsSettingsPage = React.lazy(AnalyticsSettingsPagePromise); +const PaperWalletSettingsPagePromise = () => import('./containers/settings/categories/PaperWalletSettingsPage'); +const PaperWalletSettingsPage = React.lazy(PaperWalletSettingsPagePromise); const NightlyPagePromise = () => import('./containers/profile/NightlyPage'); const NightlyPage = React.lazy(NightlyPagePromise); @@ -425,6 +427,11 @@ const SettingsSubpages = (stores, actions) => ( path={ROUTES.SETTINGS.ANALYTICS} component={props => } /> + } + /> ); diff --git a/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js b/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js new file mode 100644 index 0000000000..f1aa5ed13b --- /dev/null +++ b/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js @@ -0,0 +1,31 @@ +// @flow +import type { Node, ComponentType } from 'react'; +import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; +import { Component } from 'react'; +import { observer } from 'mobx-react'; +import { defineMessages, intlShape } from 'react-intl'; +import { Button } from '@mui/material'; + +type Props = {| + onRedirect(): void, +|}; + +@observer +class PaperWalletSettings extends Component { + static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { + intl: intlShape.isRequired, + }; + + render(): Node { + const { onRedirect } = this.props; + return ( +
+ +
+ ); + } +} + +export default PaperWalletSettings; diff --git a/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js b/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js index 6d69743fdb..d02cc092ed 100644 --- a/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js +++ b/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js @@ -33,6 +33,10 @@ export const settingsMenuMessages: Object = defineMessages({ id: 'settings.menu.analytics.link.label', defaultMessage: '!!!Analytics', }, + paperWallet: { + id: 'settings.menu.paperWallet.link.label', + defaultMessage: '!!!Paper Wallet', + }, }); type Props = {| @@ -47,7 +51,7 @@ class SettingsMenu extends Component { render(): Node { const { intl } = this.context; - const { onItemClick, isActiveItem, isRevampLayout } = this.props; + const { onItemClick, isActiveItem } = this.props; const isProduction = environmnent.isProduction(); const settingOptions: Array = [ { @@ -72,9 +76,7 @@ class SettingsMenu extends Component { hidden: isProduction, }, { - label: intl.formatMessage( - isRevampLayout ? globalMessages.termsOfService : globalMessages.termsOfUse - ), + label: intl.formatMessage(globalMessages.termsOfService), route: ROUTES.SETTINGS.TERMS_OF_USE, className: 'termsOfUse', }, @@ -92,18 +94,15 @@ class SettingsMenu extends Component { label: intl.formatMessage(settingsMenuMessages.analytics), route: ROUTES.SETTINGS.ANALYTICS, className: 'analytics', - hidden: !isRevampLayout, + }, + { + label: intl.formatMessage(settingsMenuMessages.paperWallet), + route: ROUTES.SETTINGS.PAPER_WALLET, + className: 'paperWallet', }, ]; - return ( - - ); + return ; } } diff --git a/packages/yoroi-extension/app/components/transfer/cards/TransferCards.scss b/packages/yoroi-extension/app/components/transfer/cards/TransferCards.scss index 86fb38fe15..737783f665 100644 --- a/packages/yoroi-extension/app/components/transfer/cards/TransferCards.scss +++ b/packages/yoroi-extension/app/components/transfer/cards/TransferCards.scss @@ -22,7 +22,7 @@ } .tooltipSize { - width: 500px; + max-width: 500px; overflow-wrap: break-word; white-space: normal; } diff --git a/packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js b/packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js new file mode 100644 index 0000000000..073e970d8e --- /dev/null +++ b/packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js @@ -0,0 +1,15 @@ +// @flow +import type { Node } from 'react'; +import type { StoresAndActionsProps } from '../../../types/injectedProps.types'; +import { Component } from 'react'; +import { observer } from 'mobx-react'; +import { ROUTES } from '../../../routes-config'; +import PaperWalletSettings from '../../../components/settings/categories/PaperWalletSettings'; + +@observer +export default class PaperWalletSettingsPage extends Component { + render(): Node { + const { actions } = this.props; + return actions.router.redirect.trigger({ route: ROUTES.TRANSFER.ROOT })} />; + } +} diff --git a/packages/yoroi-extension/app/containers/transfer/Transfer.js b/packages/yoroi-extension/app/containers/transfer/Transfer.js index ef2293064b..47995a805e 100644 --- a/packages/yoroi-extension/app/containers/transfer/Transfer.js +++ b/packages/yoroi-extension/app/containers/transfer/Transfer.js @@ -1,22 +1,17 @@ // @flow -import type { ComponentType, Node } from 'react'; +import type { Node } from 'react'; +import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; +import type { StoresAndActionsProps } from '../../types/injectedProps.types'; import { Component, lazy, Suspense } from 'react'; import { observer } from 'mobx-react'; -import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; import { intlShape } from 'react-intl'; -import type { StoresAndActionsProps } from '../../types/injectedProps.types'; import TopBarLayout from '../../components/layout/TopBarLayout'; import BannerContainer from '../banners/BannerContainer'; import SidebarContainer from '../SidebarContainer'; -import BackgroundColoredLayout from '../../components/layout/BackgroundColoredLayout'; import NoWalletMessage from '../wallet/NoWalletMessage'; -import UnsupportedWallet from '../wallet/UnsupportedWallet'; import NavBarTitle from '../../components/topbar/NavBarTitle'; -import NavBarContainer from '../NavBarContainer'; import globalMessages from '../../i18n/global-messages'; -import HorizontalLine from '../../components/widgets/HorizontalLine'; -import type { LayoutComponentMap } from '../../styles/context/layout'; -import { withLayout } from '../../styles/context/layout'; +import NavBarContainerRevamp from '../NavBarContainerRevamp'; export const WalletTransferPagePromise: void => Promise = () => import('./WalletTransferPage'); const WalletTransferPage = lazy(WalletTransferPagePromise); @@ -26,11 +21,8 @@ type Props = {| +children?: Node, |}; -type InjectedLayoutProps = {| +renderLayoutComponent: LayoutComponentMap => Node |}; -type AllProps = {| ...Props, ...InjectedLayoutProps |}; - @observer -class Transfer extends Component { +class Transfer extends Component { static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { intl: intlShape.isRequired, }; @@ -41,26 +33,17 @@ class Transfer extends Component { render(): Node { const { actions, stores } = this.props; - if (this.props.stores.profile.isRevampTheme) { - return null; - } const sidebarContainer = ; const navbar = ( - - } + title={} /> ); + return ( - } - navbar={navbar} - sidebar={sidebarContainer} - showInContainer - > + } navbar={navbar} sidebar={sidebarContainer}> {this.getContent()} ); @@ -72,24 +55,12 @@ class Transfer extends Component { if (wallet == null) { return ; } - // temporary solution: will need to handle more cases later for different currencies - if (wallet.isCardanoHaskell) { - return ; - } + return ( - <> - - - - - - - + + + ); }; } -export default (withLayout(Transfer): ComponentType); +export default Transfer; diff --git a/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js b/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js index 8189738564..7e50f5c9b8 100644 --- a/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js +++ b/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js @@ -10,7 +10,7 @@ import type { StoresAndActionsProps } from '../../types/injectedProps.types'; import TransferTypeSelect from '../../components/transfer/cards/TransferTypeSelect'; import { PublicDeriver } from '../../api/ada/lib/storage/models/PublicDeriver'; import YoroiTransferPage from './YoroiTransferPage'; -import { genLookupOrFail, getTokenName, } from '../../stores/stateless/tokenHelpers'; +import { genLookupOrFail, getTokenName } from '../../stores/stateless/tokenHelpers'; import { truncateToken } from '../../utils/formatters'; type Props = {| @@ -20,7 +20,7 @@ type Props = {| @observer export default class WalletTransferPage extends Component { - static contextTypes: {|intl: $npm$ReactIntl$IntlFormat|} = { + static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { intl: intlShape.isRequired, }; @@ -31,21 +31,15 @@ export default class WalletTransferPage extends Component { // paper startTransferYoroiPaperFunds: void => void = () => { this.props.actions.yoroiTransfer.startTransferFunds.trigger(); - } + }; render(): Node { - const { actions, stores } = this.props; - const defaultToken = this.props.publicDeriver.getParent().getDefaultToken(); - const defaultTokenInfo = genLookupOrFail(this.props.stores.tokenInfoStore.tokenInfo)({ - identifier: defaultToken.defaultIdentifier, - networkId: defaultToken.defaultNetworkId, - }); + const { actions, stores, publicDeriver } = this.props; + const defaultTokenInfo = stores.tokenInfoStore.getDefaultTokenInfo(publicDeriver.networkId); + return ( <> - + ); diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index 1354e9f4e1..26ac435dbb 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -295,6 +295,7 @@ "settings.general.translation.contributors": "_", "settings.general.theme.light": "Light Theme", "settings.general.theme.dark": "Dark Theme", + "settings.menu.paperWallet.link.label": "Paper Wallet", "settings.menu.analytics.link.label": "Analytics", "settings.menu.assetDeposit.link.label": "Locked assets deposit", "settings.menu.blockchain.link.label": "Blockchain", diff --git a/packages/yoroi-extension/app/routes-config.js b/packages/yoroi-extension/app/routes-config.js index 8f35cd6939..b03d5abeca 100644 --- a/packages/yoroi-extension/app/routes-config.js +++ b/packages/yoroi-extension/app/routes-config.js @@ -42,6 +42,7 @@ export const ROUTES = { SUPPORT: '/settings/support', LEVEL_OF_COMPLEXITY: '/settings/level-of-complexity', ANALYTICS: '/settings/analytics', + PAPER_WALLET: '/settings/paper-wallet', }, TRANSFER: { ROOT: '/transfer', From 379d5a1dff022644b57202ab51b6156616ca4f13 Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Tue, 5 Nov 2024 10:45:21 +0100 Subject: [PATCH 17/40] fix eslint & flow errors --- .../categories/PaperWalletSettings.js | 8 +---- .../app/containers/transfer/Transfer.js | 2 +- .../containers/transfer/WalletTransferPage.js | 33 +++++++------------ 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js b/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js index f1aa5ed13b..0907a18efc 100644 --- a/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js +++ b/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js @@ -1,9 +1,7 @@ // @flow -import type { Node, ComponentType } from 'react'; -import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; +import type { Node } from 'react'; import { Component } from 'react'; import { observer } from 'mobx-react'; -import { defineMessages, intlShape } from 'react-intl'; import { Button } from '@mui/material'; type Props = {| @@ -12,10 +10,6 @@ type Props = {| @observer class PaperWalletSettings extends Component { - static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { - intl: intlShape.isRequired, - }; - render(): Node { const { onRedirect } = this.props; return ( diff --git a/packages/yoroi-extension/app/containers/transfer/Transfer.js b/packages/yoroi-extension/app/containers/transfer/Transfer.js index 47995a805e..fa1262add8 100644 --- a/packages/yoroi-extension/app/containers/transfer/Transfer.js +++ b/packages/yoroi-extension/app/containers/transfer/Transfer.js @@ -58,7 +58,7 @@ class Transfer extends Component { return ( - + ); }; diff --git a/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js b/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js index 7e50f5c9b8..6d5b9008f7 100644 --- a/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js +++ b/packages/yoroi-extension/app/containers/transfer/WalletTransferPage.js @@ -1,29 +1,15 @@ // @flow import type { Node } from 'react'; +import type { StoresAndActionsProps } from '../../types/injectedProps.types'; import { Component } from 'react'; import { observer } from 'mobx-react'; -import type { $npm$ReactIntl$IntlFormat } from 'react-intl'; -import { intlShape } from 'react-intl'; - -import type { StoresAndActionsProps } from '../../types/injectedProps.types'; - +import { getTokenName } from '../../stores/stateless/tokenHelpers'; +import { truncateToken } from '../../utils/formatters'; import TransferTypeSelect from '../../components/transfer/cards/TransferTypeSelect'; -import { PublicDeriver } from '../../api/ada/lib/storage/models/PublicDeriver'; import YoroiTransferPage from './YoroiTransferPage'; -import { genLookupOrFail, getTokenName } from '../../stores/stateless/tokenHelpers'; -import { truncateToken } from '../../utils/formatters'; - -type Props = {| - ...StoresAndActionsProps, - publicDeriver: PublicDeriver<>, -|}; @observer -export default class WalletTransferPage extends Component { - static contextTypes: {| intl: $npm$ReactIntl$IntlFormat |} = { - intl: intlShape.isRequired, - }; - +export default class WalletTransferPage extends Component { onClose: void => void = () => { this.props.actions.dialogs.closeActiveDialog.trigger(); }; @@ -34,9 +20,14 @@ export default class WalletTransferPage extends Component { }; render(): Node { - const { actions, stores, publicDeriver } = this.props; - const defaultTokenInfo = stores.tokenInfoStore.getDefaultTokenInfo(publicDeriver.networkId); - + const { actions, stores } = this.props; + const wallet = stores.wallets.selected; + if (wallet == null) { + return null; + } + + const defaultTokenInfo = stores.tokenInfoStore.getDefaultTokenInfo(wallet.networkId); + return ( <> From 3354ed02200b7c888729b64e4511813c9fbbb4c7 Mon Sep 17 00:00:00 2001 From: Patriciu Nista Date: Thu, 7 Nov 2024 11:39:44 +0100 Subject: [PATCH 18/40] move button into support/logs section --- packages/yoroi-extension/app/Routes.js | 7 ------ .../categories/PaperWalletSettings.js | 25 ------------------- .../settings/categories/SupportSettings.js | 18 +++++++++++++ .../components/settings/menu/SettingsMenu.js | 9 ------- .../categories/PaperWalletSettingsPage.js | 15 ----------- .../categories/SupportSettingsPage.js | 3 +++ .../app/i18n/locales/en-US.json | 3 ++- 7 files changed, 23 insertions(+), 57 deletions(-) delete mode 100644 packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js delete mode 100644 packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js diff --git a/packages/yoroi-extension/app/Routes.js b/packages/yoroi-extension/app/Routes.js index 860fc2ecd1..e4a4a73a8c 100644 --- a/packages/yoroi-extension/app/Routes.js +++ b/packages/yoroi-extension/app/Routes.js @@ -79,8 +79,6 @@ const SupportSettingsPagePromise = () => import('./containers/settings/categorie const SupportSettingsPage = React.lazy(SupportSettingsPagePromise); const AnalyticsSettingsPagePromise = () => import('./containers/settings/categories/AnalyticsSettingsPage'); const AnalyticsSettingsPage = React.lazy(AnalyticsSettingsPagePromise); -const PaperWalletSettingsPagePromise = () => import('./containers/settings/categories/PaperWalletSettingsPage'); -const PaperWalletSettingsPage = React.lazy(PaperWalletSettingsPagePromise); const NightlyPagePromise = () => import('./containers/profile/NightlyPage'); const NightlyPage = React.lazy(NightlyPagePromise); @@ -427,11 +425,6 @@ const SettingsSubpages = (stores, actions) => ( path={ROUTES.SETTINGS.ANALYTICS} component={props => } /> - } - /> ); diff --git a/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js b/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js deleted file mode 100644 index 0907a18efc..0000000000 --- a/packages/yoroi-extension/app/components/settings/categories/PaperWalletSettings.js +++ /dev/null @@ -1,25 +0,0 @@ -// @flow -import type { Node } from 'react'; -import { Component } from 'react'; -import { observer } from 'mobx-react'; -import { Button } from '@mui/material'; - -type Props = {| - onRedirect(): void, -|}; - -@observer -class PaperWalletSettings extends Component { - render(): Node { - const { onRedirect } = this.props; - return ( -
- -
- ); - } -} - -export default PaperWalletSettings; diff --git a/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js b/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js index d063636837..d072737aa3 100644 --- a/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js +++ b/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js @@ -37,11 +37,20 @@ const messages = defineMessages({ id: 'settings.support.logs.title', defaultMessage: '!!!Logs', }, + paperWallet: { + id: 'settings.support.paperWallet.title', + defaultMessage: '!!!Paper Wallet', + }, + paperWalletTransfer: { + id: 'settings.support.paperWallet.button', + defaultMessage: '!!!Transfer from Paper Wallet', + }, }); type Props = {| +onExternalLinkClick: MouseEvent => void, +onDownloadLogs: void => void, + +onPaperWalletTransfer: void => void, |}; type InjectedProps = {| +isRevampLayout: boolean |}; @@ -150,6 +159,15 @@ class SupportSettings extends Component { > {intl.formatMessage(globalMessages.downloadLogsButtonLabel)} + + + + {intl.formatMessage(messages.paperWallet)} + + + ); } diff --git a/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js b/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js index d02cc092ed..886ce6d4b6 100644 --- a/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js +++ b/packages/yoroi-extension/app/components/settings/menu/SettingsMenu.js @@ -33,10 +33,6 @@ export const settingsMenuMessages: Object = defineMessages({ id: 'settings.menu.analytics.link.label', defaultMessage: '!!!Analytics', }, - paperWallet: { - id: 'settings.menu.paperWallet.link.label', - defaultMessage: '!!!Paper Wallet', - }, }); type Props = {| @@ -95,11 +91,6 @@ class SettingsMenu extends Component { route: ROUTES.SETTINGS.ANALYTICS, className: 'analytics', }, - { - label: intl.formatMessage(settingsMenuMessages.paperWallet), - route: ROUTES.SETTINGS.PAPER_WALLET, - className: 'paperWallet', - }, ]; return ; diff --git a/packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js b/packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js deleted file mode 100644 index 073e970d8e..0000000000 --- a/packages/yoroi-extension/app/containers/settings/categories/PaperWalletSettingsPage.js +++ /dev/null @@ -1,15 +0,0 @@ -// @flow -import type { Node } from 'react'; -import type { StoresAndActionsProps } from '../../../types/injectedProps.types'; -import { Component } from 'react'; -import { observer } from 'mobx-react'; -import { ROUTES } from '../../../routes-config'; -import PaperWalletSettings from '../../../components/settings/categories/PaperWalletSettings'; - -@observer -export default class PaperWalletSettingsPage extends Component { - render(): Node { - const { actions } = this.props; - return actions.router.redirect.trigger({ route: ROUTES.TRANSFER.ROOT })} />; - } -} diff --git a/packages/yoroi-extension/app/containers/settings/categories/SupportSettingsPage.js b/packages/yoroi-extension/app/containers/settings/categories/SupportSettingsPage.js index e0f6b21dac..103d4a4b56 100644 --- a/packages/yoroi-extension/app/containers/settings/categories/SupportSettingsPage.js +++ b/packages/yoroi-extension/app/containers/settings/categories/SupportSettingsPage.js @@ -8,6 +8,7 @@ import { downloadLogs } from '../../../utils/logging'; import type { StoresAndActionsProps } from '../../../types/injectedProps.types'; import IncludePublicKeyDialog from './IncludePublicKeyDialog'; import { ComplexityLevels } from '../../../types/complexityLevelType'; +import { ROUTES } from '../../../routes-config'; @observer export default class SupportSettingsPage extends Component { @@ -54,12 +55,14 @@ export default class SupportSettingsPage extends Component {this.getDialog()} actions.router.redirect.trigger({ route: ROUTES.TRANSFER.ROOT })} /> ); diff --git a/packages/yoroi-extension/app/i18n/locales/en-US.json b/packages/yoroi-extension/app/i18n/locales/en-US.json index 26ac435dbb..48cda9c868 100644 --- a/packages/yoroi-extension/app/i18n/locales/en-US.json +++ b/packages/yoroi-extension/app/i18n/locales/en-US.json @@ -295,7 +295,6 @@ "settings.general.translation.contributors": "_", "settings.general.theme.light": "Light Theme", "settings.general.theme.dark": "Dark Theme", - "settings.menu.paperWallet.link.label": "Paper Wallet", "settings.menu.analytics.link.label": "Analytics", "settings.menu.assetDeposit.link.label": "Locked assets deposit", "settings.menu.blockchain.link.label": "Blockchain", @@ -309,6 +308,8 @@ "settings.noexternal.dialog.content": "Your memos are stored locally. They will not automatically sync with other Yoroi instances and will be lost if you delete Yoroi", "settings.noexternal.dialog.title": "No external storage", "settings.revamp.unitOfAccount.note": "Please note, that the coin price is approximate and may not match the price of any given trading platform. Any transactions based on this price approximates are done at your own risk", + "settings.support.paperWallet.title": "Paper Wallet", + "settings.support.paperWallet.button": "Transfer from Paper Wallet", "settings.support.faq.blogLinkUrl": "https://emurgo.io/en/blog/yoroi-custom-themes", "settings.support.faq.blogLinkWrapper": "blog post", "settings.support.faq.content": "If you are experiencing issues, please see the {faqLink} for guidance on known issues.", From d1e0e463dd7cd21d5aa9e237c94d36a01a51ff7b Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Fri, 15 Nov 2024 14:07:24 +0300 Subject: [PATCH 19/40] font size --- .../app/components/settings/categories/SupportSettings.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js b/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js index d072737aa3..b65e00a687 100644 --- a/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js +++ b/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js @@ -164,7 +164,9 @@ class SupportSettings extends Component { {intl.formatMessage(messages.paperWallet)} - From 8b9f98a1cefaf13ea522f3d3a8a29d2d0848176c Mon Sep 17 00:00:00 2001 From: yushi Date: Thu, 14 Nov 2024 23:30:07 +0800 Subject: [PATCH 20/40] adapt to backend return value change --- .../app/api/ada/lib/state-fetch/remoteFetcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js index 8ef431f6d5..5b77f34656 100644 --- a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js +++ b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js @@ -568,7 +568,7 @@ export class RemoteFetcher implements IFetcher { } ).then(response => [ response.data ]) .catch((error) => { - if (error.response.status === 404 && error.response.data === 'Transaction not found') { + if (error.response.status === 404 && error.response.data === 'No outputs found') { return [ null ]; } Logger.error(`${nameof(RemoteFetcher)}::${nameof(this.getUtxoData)} error: ` + stringifyError(error)); From 2842b2d671a162750a5fe21c50165f34e25c81f2 Mon Sep 17 00:00:00 2001 From: yushi Date: Thu, 14 Nov 2024 23:44:20 +0800 Subject: [PATCH 21/40] allow multiple foreign inputs --- .../app/connector/stores/ConnectorStore.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/yoroi-extension/app/connector/stores/ConnectorStore.js b/packages/yoroi-extension/app/connector/stores/ConnectorStore.js index 5c7b730e80..1854e4b011 100644 --- a/packages/yoroi-extension/app/connector/stores/ConnectorStore.js +++ b/packages/yoroi-extension/app/connector/stores/ConnectorStore.js @@ -532,10 +532,13 @@ export default class ConnectorStore extends Store { const foreignInputDetails = []; if (foreignInputs.length) { - const foreignUtxos = await this.stores.substores.ada.stateFetchStore.fetcher.getUtxoData({ - network, - utxos: foreignInputs, - }); + const foreignUtxos = await Promise.all(foreignInputs.map(async (foreignInput) => { + // currently this endpoint only supports querying one at a time + return (await this.stores.substores.ada.stateFetchStore.fetcher.getUtxoData({ + network, + utxos: [foreignInput], + }))[0]; + })); for (let i = 0; i < foreignUtxos.length; i++) { const foreignUtxo = foreignUtxos[i]; if (foreignUtxo == null || typeof foreignUtxo !== 'object') { From 28b630da0d804994b0132a999144aa1f3166ec6e Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Fri, 15 Nov 2024 14:16:59 +0300 Subject: [PATCH 22/40] function ref fix --- .../app/api/ada/lib/state-fetch/remoteFetcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js index 5b77f34656..ee9a789159 100644 --- a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js +++ b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js @@ -578,7 +578,7 @@ export class RemoteFetcher implements IFetcher { getLatestBlockBySlot: GetLatestBlockBySlotFunc = async (body) => { const { BackendService } = body.network.Backend; - if (BackendService == null) throw new Error(`${nameof(this.getUtxoData)} missing backend url`); + if (BackendService == null) throw new Error(`${nameof(this.getLatestBlockBySlot)} missing backend url`); return axios( `${BackendService}/api/v2.1/lastBlockBySlot`, { From 303db7379fa4dc19192dcb07a782683428039acd Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Fri, 15 Nov 2024 14:28:38 +0300 Subject: [PATCH 23/40] process multiple items on the api side, not on the caller side --- .../api/ada/lib/state-fetch/remoteFetcher.js | 40 +++++++++---------- .../app/connector/stores/ConnectorStore.js | 11 ++--- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js index ee9a789159..dc62ef3a9f 100644 --- a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js +++ b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js @@ -551,29 +551,27 @@ export class RemoteFetcher implements IFetcher { getUtxoData: GetUtxoDataRequest => Promise = async (body) => { const { BackendService } = body.network.Backend; - if (body.utxos.length !== 1) { - throw new Error('the RemoteFetcher.getUtxoData expects 1 UTXO'); - } - const { txHash, txIndex } = body.utxos[0]; if (BackendService == null) throw new Error(`${nameof(this.getUtxoData)} missing backend url`); - return axios( - `${BackendService}/api/txs/io/${txHash}/o/${txIndex}`, - { - method: 'get', - timeout: 2 * CONFIG.app.walletRefreshInterval, - headers: { - 'yoroi-version': this.getLastLaunchVersion(), - 'yoroi-locale': this.getCurrentLocale() - } - } - ).then(response => [ response.data ]) - .catch((error) => { - if (error.response.status === 404 && error.response.data === 'No outputs found') { - return [ null ]; + return Promise.all(body.utxos.map(({ txHash, txIndex }) => { + return axios( + `${BackendService}/api/txs/io/${txHash}/o/${txIndex}`, + { + method: 'get', + timeout: 2 * CONFIG.app.walletRefreshInterval, + headers: { + 'yoroi-version': this.getLastLaunchVersion(), + 'yoroi-locale': this.getCurrentLocale() + } } - Logger.error(`${nameof(RemoteFetcher)}::${nameof(this.getUtxoData)} error: ` + stringifyError(error)); - throw new GetUtxoDataError(); - }); + ).then(response => [ response.data ]) + .catch((error) => { + if (error.response.status === 404 && error.response.data === 'No outputs found') { + return [ null ]; + } + Logger.error(`${nameof(RemoteFetcher)}::${nameof(this.getUtxoData)} error: ` + stringifyError(error)); + throw new GetUtxoDataError(); + }); + })); } getLatestBlockBySlot: GetLatestBlockBySlotFunc = async (body) => { diff --git a/packages/yoroi-extension/app/connector/stores/ConnectorStore.js b/packages/yoroi-extension/app/connector/stores/ConnectorStore.js index 1854e4b011..5c7b730e80 100644 --- a/packages/yoroi-extension/app/connector/stores/ConnectorStore.js +++ b/packages/yoroi-extension/app/connector/stores/ConnectorStore.js @@ -532,13 +532,10 @@ export default class ConnectorStore extends Store { const foreignInputDetails = []; if (foreignInputs.length) { - const foreignUtxos = await Promise.all(foreignInputs.map(async (foreignInput) => { - // currently this endpoint only supports querying one at a time - return (await this.stores.substores.ada.stateFetchStore.fetcher.getUtxoData({ - network, - utxos: [foreignInput], - }))[0]; - })); + const foreignUtxos = await this.stores.substores.ada.stateFetchStore.fetcher.getUtxoData({ + network, + utxos: foreignInputs, + }); for (let i = 0; i < foreignUtxos.length; i++) { const foreignUtxo = foreignUtxos[i]; if (foreignUtxo == null || typeof foreignUtxo !== 'object') { From 643ac5ca26d82f1f56cae4dcbc647f71d9dd18e4 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Fri, 15 Nov 2024 14:31:02 +0300 Subject: [PATCH 24/40] return fix --- .../app/api/ada/lib/state-fetch/remoteFetcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js index dc62ef3a9f..a121f7b213 100644 --- a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js +++ b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js @@ -563,7 +563,7 @@ export class RemoteFetcher implements IFetcher { 'yoroi-locale': this.getCurrentLocale() } } - ).then(response => [ response.data ]) + ).then(response => response.data) .catch((error) => { if (error.response.status === 404 && error.response.data === 'No outputs found') { return [ null ]; From eb9ba57d371caba1c30ca9b7491cf2d00b3d53f6 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Fri, 15 Nov 2024 14:31:09 +0300 Subject: [PATCH 25/40] return fix --- .../app/api/ada/lib/state-fetch/remoteFetcher.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js index a121f7b213..55e0e75355 100644 --- a/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js +++ b/packages/yoroi-extension/app/api/ada/lib/state-fetch/remoteFetcher.js @@ -566,7 +566,7 @@ export class RemoteFetcher implements IFetcher { ).then(response => response.data) .catch((error) => { if (error.response.status === 404 && error.response.data === 'No outputs found') { - return [ null ]; + return null; } Logger.error(`${nameof(RemoteFetcher)}::${nameof(this.getUtxoData)} error: ` + stringifyError(error)); throw new GetUtxoDataError(); From 64a667a4d4e124d09f186521cdd9469ab8dfe974 Mon Sep 17 00:00:00 2001 From: vantuz-subhuman Date: Fri, 15 Nov 2024 15:01:39 +0300 Subject: [PATCH 26/40] lint fix --- .../components/settings/categories/SupportSettings.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js b/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js index b65e00a687..fa63317278 100644 --- a/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js +++ b/packages/yoroi-extension/app/components/settings/categories/SupportSettings.js @@ -164,9 +164,13 @@ class SupportSettings extends Component { {intl.formatMessage(messages.paperWallet)} - From 88cb1246bc74a4225c3681025eefab05f164df31 Mon Sep 17 00:00:00 2001 From: yushi Date: Fri, 8 Nov 2024 16:43:12 +0800 Subject: [PATCH 27/40] Trezor wallet governance support --- .../TransactionFailed/TransactionFailed.tsx | 9 ++- .../GovernanceTransactionFailedPage.tsx | 2 +- .../api/ada/transactions/shelley/trezorTx.js | 40 ++++++++++- .../app/domain/TrezorLocalizedError.js | 6 ++ .../app/i18n/locales/en-US.json | 1 + .../ada/AdaDelegationTransactionStore.js | 70 +++++++++++-------- .../app/stores/stateless/sidebarCategories.js | 2 +- .../chrome/manifest-mv2.template.js | 2 +- .../chrome/manifest.template.js | 2 +- packages/yoroi-extension/package.json | 2 +- 10 files changed, 97 insertions(+), 39 deletions(-) diff --git a/packages/yoroi-extension/app/UI/components/TransactionFailed/TransactionFailed.tsx b/packages/yoroi-extension/app/UI/components/TransactionFailed/TransactionFailed.tsx index f40ab28149..01884d3619 100644 --- a/packages/yoroi-extension/app/UI/components/TransactionFailed/TransactionFailed.tsx +++ b/packages/yoroi-extension/app/UI/components/TransactionFailed/TransactionFailed.tsx @@ -4,9 +4,12 @@ import { FormattedMessage } from 'react-intl'; import globalMessages from '../../../i18n/global-messages'; import { useNavigateTo } from '../../features/governace/common/useNavigateTo'; import { FailedIlustration } from './FailedIlustration'; +import LocalizableError from '../../../i18n/LocalizableError'; -export const TransactionFailed = () => { +export const TransactionFailed = (props: { error: Error | null }) => { const navigate = useNavigateTo(); + const { error } = props; + return ( @@ -14,7 +17,9 @@ export const TransactionFailed = () => { - + {/* @ts-ignore */}