Date: Thu, 21 Nov 2024 15:05:34 +0800
Subject: [PATCH 04/12] fix: history load (#2630)
---
src/ui/views/History/components/HistoryList.tsx | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/ui/views/History/components/HistoryList.tsx b/src/ui/views/History/components/HistoryList.tsx
index ecce3a5d112..12041e06b41 100644
--- a/src/ui/views/History/components/HistoryList.tsx
+++ b/src/ui/views/History/components/HistoryList.tsx
@@ -7,7 +7,7 @@ import { useAccount } from '@/ui/store-hooks';
import { useInfiniteScroll } from 'ahooks';
import { Virtuoso } from 'react-virtuoso';
import { Empty, Modal } from 'ui/component';
-import { useWallet } from 'ui/utils';
+import { sleep, useWallet } from 'ui/utils';
import { HistoryItem, HistoryItemActionContext } from './HistoryItem';
import { Loading } from './Loading';
@@ -41,6 +41,9 @@ export const HistoryList = ({
const fetchData = async (startTime = 0) => {
const { address } = account!;
+ if (startTime) {
+ await sleep(500);
+ }
const apiLevel = await wallet.getAPIConfig([], 'ApiLevel', false);
if (apiLevel >= 1) {
return {
@@ -156,10 +159,11 @@ export const HistoryList = ({
);
}}
endReached={loadMore}
+ increaseViewportBy={100}
components={{
Footer: () => {
if (loadingMore) {
- return
;
+ return
;
}
return null;
},
From b0a93b0871a4826abb86111ea1ed2470a444ebdc Mon Sep 17 00:00:00 2001
From: DMY <147dmy@gmail.com>
Date: Thu, 21 Nov 2024 15:05:47 +0800
Subject: [PATCH 05/12] fix: gasaccount nonce (#2625)
---
src/ui/views/Approval/components/SignTx.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ui/views/Approval/components/SignTx.tsx b/src/ui/views/Approval/components/SignTx.tsx
index afb496d1398..d04cb58f43d 100644
--- a/src/ui/views/Approval/components/SignTx.tsx
+++ b/src/ui/views/Approval/components/SignTx.tsx
@@ -685,7 +685,7 @@ const SignTx = ({ params, origin }: SignTxProps) => {
return [
{
...tx,
- nonce: realNonce,
+ nonce: realNonce || tx.nonce,
gasPrice: tx.gasPrice || tx.maxFeePerGas,
gas: gasLimit,
},
From 08172a7daf9c88c6830909ec61500b59e831f743 Mon Sep 17 00:00:00 2001
From: vvvvvv1vvvvvv <86296331+vvvvvv1vvvvvv@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:11:28 +0800
Subject: [PATCH 06/12] fix: parseSignTypedData (#2631)
* fix: bypass of signtypeddata
* fix: patch
---
patches/@metamask+eth-sig-util+5.1.0.patch | 22 ++++
.../components/TypedDataActions/utils.ts | 111 ++++++++++++------
2 files changed, 94 insertions(+), 39 deletions(-)
diff --git a/patches/@metamask+eth-sig-util+5.1.0.patch b/patches/@metamask+eth-sig-util+5.1.0.patch
index 6e24543cc59..38062ce9957 100644
--- a/patches/@metamask+eth-sig-util+5.1.0.patch
+++ b/patches/@metamask+eth-sig-util+5.1.0.patch
@@ -1,3 +1,25 @@
+diff --git a/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.d.ts b/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.d.ts
+index 45a660e..9b3f105 100644
+--- a/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.d.ts
++++ b/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.d.ts
+@@ -20,3 +20,5 @@ export declare function parseNumber(arg: string | number | BN): BN;
+ * @param values
+ */
+ export declare function rawEncode(types: string[], values: (BN | Buffer | string | number | string[] | number[])[]): Buffer;
++
++export declare function encodeSingle(type: string, arg: BN | Buffer | string | number | string[] | number[]): Buffer;
+diff --git a/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.js b/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.js
+index 1a11fec..7c78143 100644
+--- a/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.js
++++ b/node_modules/@metamask/eth-sig-util/dist/ethereumjs-abi-utils.js
+@@ -352,6 +352,7 @@ function encodeSingle(type, arg) {
+ }
+ throw new Error(`Unsupported or invalid type: ${JSON.stringify(type)}`);
+ }
++exports.encodeSingle = encodeSingle;
+ // Is a type dynamic?
+ /**
+ * @param type
diff --git a/node_modules/@metamask/eth-sig-util/dist/index.d.ts b/node_modules/@metamask/eth-sig-util/dist/index.d.ts
index 48ddf59..58c9ae7 100644
--- a/node_modules/@metamask/eth-sig-util/dist/index.d.ts
diff --git a/src/ui/views/Approval/components/TypedDataActions/utils.ts b/src/ui/views/Approval/components/TypedDataActions/utils.ts
index 6aa0cfcbdbd..b2f912355d4 100644
--- a/src/ui/views/Approval/components/TypedDataActions/utils.ts
+++ b/src/ui/views/Approval/components/TypedDataActions/utils.ts
@@ -1,11 +1,11 @@
-import { getArrayType, isArrayType } from '@metamask/abi-utils/dist/parsers';
-import { BigNumber as EthersBigNumber } from 'ethers';
-import { isStrictHexString, add0x } from 'ui/utils/address';
import i18n from '@/i18n';
-import { parseNumber } from '@metamask/eth-sig-util';
-import { padStart } from 'lodash';
import { ParsedTypedDataActionData } from '@rabby-wallet/rabby-action';
import { getActionTypeText as getTransactionActionTypeText } from '../Actions/utils';
+import { encodeSingle } from '@metamask/eth-sig-util';
+import { bufferToHex } from 'ethereumjs-util';
+import { hexToString } from 'web3-utils';
+import BigNumber from 'bignumber.js';
+
export const getActionTypeText = (data: ParsedTypedDataActionData | null) => {
const { t } = i18n;
@@ -74,47 +74,80 @@ export function normalizeTypeData(data: {
message: Record
;
}) {
try {
- const { types, primaryType, domain, message } = data;
- const domainTypes = types.EIP712Domain;
- const messageTypes = types[primaryType];
- domainTypes.forEach((item) => {
- const { name, type } = item;
- domain[name] = normalizeValue(type, domain[name]);
- });
- messageTypes.forEach((item) => {
- const { name, type } = item;
- message[name] = normalizeValue(type, message[name]);
- });
- return { types, primaryType, domain, message };
+ return parseSignTypedData(data);
} catch (e) {
return data;
}
}
+function parseSignTypedData(typedData: {
+ primaryType: string;
+ types: Record;
+ domain: Record;
+ message: Record;
+}) {
+ const { domain, message, types, primaryType } = typedData;
-export function normalizeValue(type: string, value: unknown): any {
- if (isArrayType(type) && Array.isArray(value)) {
- const [innerType] = getArrayType(type);
- return value.map((item) => normalizeValue(innerType, item));
- }
+ function parseAndDecode(data: any, dataType: string) {
+ if (dataType.endsWith('[]')) {
+ const elementType = dataType.slice(0, -2);
+ const decodedArray: any[] = [];
+ for (const element of data) {
+ decodedArray.push(parseAndDecode(element, elementType));
+ }
+ return decodedArray;
+ } else if (types[dataType]) {
+ for (const field of types[dataType]) {
+ const { name, type } = field;
+ data[name] = parseAndDecode(data[name], type);
+ }
+ return data;
+ } else {
+ const encodedBuffer = encodeSingle(dataType, data);
+ let encodedHexValue = `0x${encodedBuffer.toString('hex')}`;
+ switch (dataType) {
+ case 'string': {
+ const encodedLengthSize = 32; // uint256 length
+ const lengthBuffer = encodedBuffer.slice(0, encodedLengthSize);
+ const originalArgLength = parseInt(lengthBuffer.toString('hex'), 16);
+ const fullArgWithPadding = encodedBuffer.slice(encodedLengthSize);
+ const originalArg = fullArgWithPadding.slice(0, originalArgLength);
+ encodedHexValue = bufferToHex(originalArg);
+ break;
+ }
+ case 'address':
+ encodedHexValue = `0x${encodedBuffer.slice(12).toString('hex')}`;
+ break;
+ case 'bool':
+ if (new BigNumber(encodedHexValue).eq(0)) {
+ return false;
+ } else if (new BigNumber(encodedHexValue).eq(1)) {
+ return true;
+ }
+ break;
+ default:
+ // NOTHING
+ }
+ if (
+ dataType.startsWith('uint') ||
+ dataType.startsWith('int') ||
+ dataType.startsWith('ufixed') ||
+ dataType.startsWith('fixed')
+ ) {
+ return new BigNumber(encodedHexValue).toFixed();
+ }
+ if (dataType === 'string') {
+ return hexToString(encodedHexValue);
+ }
- if (type === 'address') {
- let address = value as string;
- if (typeof value === 'string' && !/^(0x|0X)/.test(value)) {
- address = EthersBigNumber.from(value).toHexString();
- } else if (isStrictHexString(value)) {
- address = add0x(value);
- }
- try {
- const parseAddress = padStart(
- parseNumber(address).toString('hex'),
- 40,
- '0'
- );
- return `0x${parseAddress}`;
- } catch (e) {
- return address;
+ return encodedHexValue;
}
}
- return value;
+ for (const { name, type } of types.EIP712Domain) {
+ domain[name] = parseAndDecode(domain[name], type);
+ }
+
+ typedData.message = parseAndDecode(message, primaryType);
+
+ return typedData;
}
From cd5c14bc1c8f2eefc0771b4e126ef9dc27383867 Mon Sep 17 00:00:00 2001
From: vvvvvv1vvvvvv <86296331+vvvvvv1vvvvvv@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:19:34 +0800
Subject: [PATCH 07/12] feat: support unknown token for batch permit2 (#2633)
* feat: support unknown token for batch permit2
* fix: dep version
---
package.json | 2 +-
yarn.lock | 15 +++++----------
2 files changed, 6 insertions(+), 11 deletions(-)
diff --git a/package.json b/package.json
index cedb4ccb0be..b352cfc4d43 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,7 @@
"@rabby-wallet/eth-watch-keyring": "1.0.0",
"@rabby-wallet/gnosis-sdk": "1.3.9",
"@rabby-wallet/page-provider": "0.4.2",
- "@rabby-wallet/rabby-action": "0.1.4",
+ "@rabby-wallet/rabby-action": "0.1.8",
"@rabby-wallet/rabby-api": "0.8.5",
"@rabby-wallet/rabby-security-engine": "2.0.7",
"@rabby-wallet/rabby-swap": "0.0.42",
diff --git a/yarn.lock b/yarn.lock
index dc66542e19e..e7476d6c0d0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1610,16 +1610,11 @@
resolved "https://registry.yarnpkg.com/@ctrl/tinycolor/-/tinycolor-3.4.0.tgz#c3c5ae543c897caa9c2a68630bed355be5f9990f"
integrity sha512-JZButFdZ1+/xAfpguQHoabIXkcqRRKpMrWKBkpEZZyxfY9C1DpADFB8PEqGSTeFr135SaTRfKqGKx5xSCLI7ZQ==
-"@debank/common@0.3.60":
+"@debank/common@0.3.60", "@debank/common@^0.3.0":
version "0.3.60"
resolved "https://registry.yarnpkg.com/@debank/common/-/common-0.3.60.tgz#17ca72e4cde1fb6487ca1ed0691d89cd6b6692f9"
integrity sha512-SaFTXvnn2aYQTPB3B8YD/AhHYwdMRiqu7jCkYV6c/Sd3MmxzJR3v+Kd4jlQniKfEdB21+1vMb0NlzHw/gyemlw==
-"@debank/common@^0.3.0":
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/@debank/common/-/common-0.3.0.tgz#9c67288816d62e3548e0c2193ec4cd73758f5b26"
- integrity sha512-PWdFuKuqDtGdYALFToDQQCyas3Tgz1tXXlir6UVTVHz2MPi4uK6ZK8UUNrWdU6lncHNvcRsNf3Xamk0Ga9jxeg==
-
"@debank/festats@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@debank/festats/-/festats-1.0.1.tgz#8f76b0919a6c8a7d938a42946272abaff2b971be"
@@ -4776,10 +4771,10 @@
sinon-chrome "^3.0.1"
webextension-polyfill "0.7.0"
-"@rabby-wallet/rabby-action@0.1.4":
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/@rabby-wallet/rabby-action/-/rabby-action-0.1.4.tgz#c82e7c8b538b7dfd94506c4f89f78aca7ca880ef"
- integrity sha512-6ttnlpGHcO2v/qyYo8epBbSutfS9OZXfXr9mfapuveoBvzqUwvE6ej3bsmdtc+qFhFeH7HeiwASpY6xaTM4E1w==
+"@rabby-wallet/rabby-action@0.1.8":
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/@rabby-wallet/rabby-action/-/rabby-action-0.1.8.tgz#05b258b628a224d51dc471e93117d4106024a916"
+ integrity sha512-K0euVX55tW2mbnudm3bHPAbbLYlnDQD5PgAvM1mwPPFHhF/Ve/U5MYdg1XERJPxkoXKqiVti46idFFB+s8sv7A==
"@rabby-wallet/rabby-api@0.8.5":
version "0.8.5"
From 56d01640def0b231a457e7ba1d2d44ad98fcc15b Mon Sep 17 00:00:00 2001
From: vvvvvv1vvvvvv <86296331+vvvvvv1vvvvvv@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:20:38 +0800
Subject: [PATCH 08/12] fix: patch timeout for ledger request (#2634)
---
patches/@ledgerhq+hw-app-eth+6.39.0.patch | 26 +++++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 patches/@ledgerhq+hw-app-eth+6.39.0.patch
diff --git a/patches/@ledgerhq+hw-app-eth+6.39.0.patch b/patches/@ledgerhq+hw-app-eth+6.39.0.patch
new file mode 100644
index 00000000000..8dbf7674b02
--- /dev/null
+++ b/patches/@ledgerhq+hw-app-eth+6.39.0.patch
@@ -0,0 +1,26 @@
+diff --git a/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/contracts.js b/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/contracts.js
+index 806a539..b488b25 100644
+--- a/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/contracts.js
++++ b/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/contracts.js
+@@ -19,7 +19,7 @@ export const loadInfosForContractMethod = (contractAddress, selector, chainId, u
+ if (pluginBaseURL) {
+ const url = `${pluginBaseURL}/plugins/ethereum.json`;
+ data = yield axios
+- .get(`${pluginBaseURL}/plugins/ethereum.json`)
++ .get(`${pluginBaseURL}/plugins/ethereum.json`, { timeout: 5000 })
+ .then(r => r.data)
+ .catch(e => {
+ log("error", "could not fetch from " + url + ": " + String(e));
+diff --git a/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/erc20.js b/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/erc20.js
+index 16a933e..a2a0f1a 100644
+--- a/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/erc20.js
++++ b/node_modules/@ledgerhq/hw-app-eth/lib-es/services/ledger/erc20.js
+@@ -21,7 +21,7 @@ export const findERC20SignaturesInfo = (userLoadConfig, chainId) => __awaiter(vo
+ return null;
+ const url = `${cryptoassetsBaseURL}/evm/${chainId}/erc20-signatures.json`;
+ const blob = yield axios
+- .get(url)
++ .get(url, { timeout: 5000 })
+ .then(({ data }) => {
+ if (!data || typeof data !== "string") {
+ throw new Error(`ERC20 signatures for chainId ${chainId} file is malformed ${url}`);
From f4d1af5de0c6be02ad4da7f4ab3e699f54c4d3f8 Mon Sep 17 00:00:00 2001
From: heisenberg <110591045+heisenberg-2077@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:21:16 +0800
Subject: [PATCH 09/12] fix: clear the ledger's transport when disconnected
(#2635)
---
.../service/keyring/eth-ledger-keyring.ts | 21 ++++++++++++++++++-
src/constant/offscreen-communication.ts | 4 ++++
src/offscreen/scripts/ledger.ts | 17 +++++++++++++++
src/offscreen/scripts/offscreen.ts | 2 ++
4 files changed, 43 insertions(+), 1 deletion(-)
create mode 100644 src/offscreen/scripts/ledger.ts
diff --git a/src/background/service/keyring/eth-ledger-keyring.ts b/src/background/service/keyring/eth-ledger-keyring.ts
index c7d4b178e3c..cffc3f56959 100644
--- a/src/background/service/keyring/eth-ledger-keyring.ts
+++ b/src/background/service/keyring/eth-ledger-keyring.ts
@@ -15,6 +15,12 @@ import { SignHelper, LedgerHDPathType } from './helper';
const type = 'Ledger Hardware';
import HDPathType = LedgerHDPathType;
+import Browser from 'webextension-polyfill';
+import {
+ LedgerAction,
+ OffscreenCommunicationTarget,
+} from '@/constant/offscreen-communication';
+import { isManifestV3 } from '@/utils/env';
const HD_PATH_BASE = {
[HDPathType.BIP44]: "m/44'/60'/0'/0",
@@ -70,6 +76,17 @@ class LedgerBridgeKeyring {
this.app = null;
this.usedHDPathTypeList = {};
this.deserialize(opts);
+
+ if (isManifestV3) {
+ Browser.runtime.onMessage.addListener((request) => {
+ if (
+ request.target === OffscreenCommunicationTarget.extension &&
+ request.event === LedgerAction.ledgerDeviceDisconnect
+ ) {
+ this.cleanUp();
+ }
+ });
+ }
}
serialize() {
@@ -145,7 +162,9 @@ class LedgerBridgeKeyring {
async cleanUp() {
this.app = null;
- if (this.transport) this.transport.close();
+ if (this.transport) {
+ await this.transport.close();
+ }
this.transport = null;
}
diff --git a/src/constant/offscreen-communication.ts b/src/constant/offscreen-communication.ts
index ac0f369fdd1..03ae7bcc7df 100644
--- a/src/constant/offscreen-communication.ts
+++ b/src/constant/offscreen-communication.ts
@@ -49,3 +49,7 @@ export enum LatticeAction {
export enum KnownOrigins {
lattice = 'https://lattice.gridplus.io',
}
+
+export enum LedgerAction {
+ ledgerDeviceDisconnect = 'ledger-device-disconnect',
+}
diff --git a/src/offscreen/scripts/ledger.ts b/src/offscreen/scripts/ledger.ts
new file mode 100644
index 00000000000..54f5f01b813
--- /dev/null
+++ b/src/offscreen/scripts/ledger.ts
@@ -0,0 +1,17 @@
+import {
+ LedgerAction,
+ OffscreenCommunicationTarget,
+} from '@/constant/offscreen-communication';
+import { ledgerUSBVendorId } from '@ledgerhq/devices';
+import Browser from 'webextension-polyfill';
+
+export function initLedger() {
+ navigator.hid.addEventListener('disconnect', ({ device }) => {
+ if (device.vendorId === ledgerUSBVendorId) {
+ Browser.runtime.sendMessage({
+ target: OffscreenCommunicationTarget.extension,
+ event: LedgerAction.ledgerDeviceDisconnect,
+ });
+ }
+ });
+}
diff --git a/src/offscreen/scripts/offscreen.ts b/src/offscreen/scripts/offscreen.ts
index f846b4a4885..3b6b7cc27fe 100644
--- a/src/offscreen/scripts/offscreen.ts
+++ b/src/offscreen/scripts/offscreen.ts
@@ -1,12 +1,14 @@
import { initBitBox02 } from './bitbox02';
import { initImKey } from './imkey';
import initLattice from './lattice';
+import { initLedger } from './ledger';
import { initOneKey } from './onekey';
initImKey();
initOneKey();
initBitBox02();
initLattice();
+initLedger();
// keep alive when ui page is open
let pageCount = 0;
From 147ff47c9157424311f32b75b860030ff8561c7b Mon Sep 17 00:00:00 2001
From: vvvvvv1vvvvvv <86296331+vvvvvv1vvvvvv@users.noreply.github.com>
Date: Fri, 22 Nov 2024 17:12:28 +0800
Subject: [PATCH 10/12] fix: backup seedphrase style (#2636)
---
src/ui/views/AddressBackup/Mnemonics.tsx | 64 ++++++++++++------------
src/ui/views/AddressBackup/style.less | 1 -
2 files changed, 31 insertions(+), 34 deletions(-)
diff --git a/src/ui/views/AddressBackup/Mnemonics.tsx b/src/ui/views/AddressBackup/Mnemonics.tsx
index 32a8b92d1f7..9931ee94315 100644
--- a/src/ui/views/AddressBackup/Mnemonics.tsx
+++ b/src/ui/views/AddressBackup/Mnemonics.tsx
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { useWallet } from 'ui/utils';
import './style.less';
import { InfoCircleOutlined } from '@ant-design/icons';
import { Button } from 'antd';
@@ -20,7 +19,6 @@ import QRCode from 'qrcode.react';
import { ReactComponent as RcIconQrCode } from 'ui/assets/qrcode-cc.svg';
const AddressBackup = () => {
- const wallet = useWallet();
const { t } = useTranslation();
const history = useHistory();
@@ -91,11 +89,11 @@ const AddressBackup = () => {
)}
{t('page.backupSeedPhrase.title')}
-
+
{t('page.backupSeedPhrase.alert')}
-
+
setMasked(false)}
@@ -106,6 +104,34 @@ const AddressBackup = () => {
{t('page.backupSeedPhrase.clickToShow')}
+
+
+
+ {t('page.backupSeedPhrase.showQrCode')}
+
+
+
+ {t('page.backupSeedPhrase.copySeedPhrase')}
+
+
{
)}
-
-
-
- {t('page.backupSeedPhrase.showQrCode')}
-
-
-
- {t('page.backupSeedPhrase.copySeedPhrase')}
-
-
-
+