Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
&__logo {
margin-bottom: 8px;
}
&__label {
font-size: 12px;
line-height: 16px;
letter-spacing: 0.5px;
color: @grayPrimary;
margin: 0 0 4px 44px;
}
&__network {
display: flex;
justify-content: flex-start;
Expand Down Expand Up @@ -167,11 +174,11 @@

&-to {
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 20px;
letter-spacing: 0.25px;
color: @primaryLabel;
font-weight: 400 !important;
font-size: 16px !important;
line-height: 20px !important;
letter-spacing: 0.5px;
color: @black !important;
word-break: break-all;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
<template #content>
<h2>Verify transaction</h2>
<hardware-wallet-msg :wallet-type="account.walletType" />
<!--FROM-->
<div class="provider-verify-transaction__block">
<p class="provider-verify-transaction__label">From</p>
<div class="provider-verify-transaction__account">
<img :src="identicon" />
<div class="provider-verify-transaction__account-info">
Expand All @@ -32,9 +34,10 @@
</div>
</div>
</div>
<!-- TX INFO -->
<div class="provider-verify-transaction__block">
<div class="provider-verify-transaction__info">
<img :src="Options.faviconURL" />
<img :src="Options.faviconURL" width="32px" height="32px" />
<div class="provider-verify-transaction__info-info">
<h4>{{ Options.domain }}</h4>
</div>
Expand Down Expand Up @@ -77,6 +80,20 @@
</p>
</div>
</div>
<!-- TO -->
<div class="provider-verify-transaction__block">
<p class="provider-verify-transaction__label">To</p>
<div class="provider-verify-transaction__account">
<img :src="identiconTo" />
<div class="provider-verify-transaction__account-info">
<div>
<p class="provider-verify-transaction__account-info-to">
{{ decodedTx?.toAddress ?? '~' }}
</p>
</div>
</div>
</div>
</div>

<send-fee-select
:in-swap="true"
Expand Down Expand Up @@ -183,6 +200,7 @@ const account = ref<EnkryptAccount>({
address: '',
} as EnkryptAccount);
const identicon = ref<string>('');
const identiconTo = ref<string>(network.value.identicon(''));
const windowPromise = WindowPromiseHandler(3);
const Options = ref<ProviderRequestOptions>({
domain: '',
Expand Down Expand Up @@ -216,6 +234,9 @@ onBeforeMount(async () => {
Request.value.params![0] as EthereumTransaction,
network.value as EvmNetwork,
).then(decoded => {
identiconTo.value = network.value.identicon(
decoded.toAddress!.toLowerCase(),
);
if (decoded.decoded && decoded.dataHex.startsWith(TokenSigs.approve)) {
isApproval.value = true;
if (
Expand Down
3 changes: 2 additions & 1 deletion packages/hw-wallets/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@enkryptcom/hw-wallets",
"version": "0.0.4",
"version": "0.0.9",
"description": "Hardware wallet manager for enkrypt",
"type": "module",
"main": "src/index.ts",
Expand Down Expand Up @@ -61,6 +61,7 @@
"@polkadot/types": "^15.10.2",
"@polkadot/util": "^13.5.1",
"@trezor/connect": "^9.5.5",
"@trezor/connect-web": "^9.5.5",
"@trezor/connect-webextension": "^9.5.5",
"@zondax/ledger-substrate": "^1.1.2",
"bitcoinjs-lib": "^6.1.7",
Expand Down
21 changes: 7 additions & 14 deletions packages/hw-wallets/src/trezor/bitcoin/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import TrezorConnect from "@trezor/connect-webextension";
import { getHDPath } from "@trezor/connect/lib/utils/pathUtils";
import { HWwalletCapabilities, NetworkNames } from "@enkryptcom/types";
import HDKey from "hdkey";
import { bufferToHex } from "@enkryptcom/utils";
import type { TrezorConnect } from "@trezor/connect-web";
import {
AddressResponse,
BitcoinSignMessage,
Expand All @@ -13,10 +13,11 @@ import {
SignTransactionRequest,
} from "../../types";
import { supportedPaths, TrezorNetworkConfigs } from "./configs";
import getTrezorConnect from "../trezorConnect";

class TrezorEthereum implements HWWalletProvider {
network: NetworkNames;

TrezorConnect: TrezorConnect;
HDNodes: Record<string, HDKey>;

constructor(network: NetworkNames) {
Expand All @@ -25,15 +26,7 @@ class TrezorEthereum implements HWWalletProvider {
}

async init(): Promise<boolean> {
TrezorConnect.init({
manifest: {
email: "info@enkrypt.com",
appUrl: "https://www.enkrypt.com",
},
transports: ["BridgeTransport", "WebUsbTransport"],
connectSrc: "https://connect.trezor.io/9/",
_extendWebextensionLifetime: true,
});
this.TrezorConnect = await getTrezorConnect();
return true;
Comment on lines 28 to 30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Updated init method for dynamic loading

The init method now properly uses the getTrezorConnect helper to dynamically load and initialize TrezorConnect.

Consider adding error handling to gracefully handle initialization failures:

 async init(): Promise<boolean> {
-   this.TrezorConnect = await getTrezorConnect();
-   return true;
+   try {
+     this.TrezorConnect = await getTrezorConnect();
+     return true;
+   } catch (error) {
+     console.error("Failed to initialize Trezor Connect:", error);
+     return false;
+   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async init(): Promise<boolean> {
TrezorConnect.init({
manifest: {
email: "info@enkrypt.com",
appUrl: "https://www.enkrypt.com",
},
transports: ["BridgeTransport", "WebUsbTransport"],
connectSrc: "https://connect.trezor.io/9/",
_extendWebextensionLifetime: true,
});
this.TrezorConnect = await getTrezorConnect();
return true;
async init(): Promise<boolean> {
try {
this.TrezorConnect = await getTrezorConnect();
return true;
} catch (error) {
console.error("Failed to initialize Trezor Connect:", error);
return false;
}
}
🤖 Prompt for AI Agents
In packages/hw-wallets/src/trezor/bitcoin/index.ts around lines 28 to 30, the
init method currently calls getTrezorConnect without error handling. Update the
method to include a try-catch block around the await getTrezorConnect() call to
catch any initialization errors. In the catch block, log the error and return
false to indicate failure, ensuring the method gracefully handles initialization
failures.

}

Expand All @@ -42,7 +35,7 @@ class TrezorEthereum implements HWWalletProvider {
return Promise.reject(new Error("trezor-bitcoin: Invalid network name"));

if (!this.HDNodes[options.pathType.basePath]) {
const rootPub = await TrezorConnect.getPublicKey({
const rootPub = await this.TrezorConnect.getPublicKey({
path: options.pathType.basePath,
showOnTrezor: options.confirmAddress,
} as any);
Expand Down Expand Up @@ -82,7 +75,7 @@ class TrezorEthereum implements HWWalletProvider {
if (options.type === "bip322-simple") {
throw new Error("trezor-bitcoin: bip322 signing not supported");
}
const result = await TrezorConnect.signMessage({
const result = await this.TrezorConnect.signMessage({
path: options.pathType.path.replace(`{index}`, options.pathIndex),
message: options.message.toString("hex"),
hex: true,
Expand All @@ -97,7 +90,7 @@ class TrezorEthereum implements HWWalletProvider {
const addressN = getHDPath(
options.pathType.path.replace(`{index}`, options.pathIndex),
);
return TrezorConnect.signTransaction({
return this.TrezorConnect.signTransaction({
coin: TrezorNetworkConfigs[this.network].symbol,
inputs: transactionOptions.psbtTx.txInputs.map((tx) => ({
address_n: addressN,
Expand Down
31 changes: 12 additions & 19 deletions packages/hw-wallets/src/trezor/ethereum/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import TrezorConnect from "@trezor/connect-webextension";
import { HWwalletCapabilities, NetworkNames } from "@enkryptcom/types";
import HDKey from "hdkey";
import { bigIntToHex, bufferToHex, hexToBuffer } from "@enkryptcom/utils";
import { publicToAddress, toRpcSig } from "@ethereumjs/util";
import { FeeMarketEIP1559Transaction, LegacyTransaction } from "@ethereumjs/tx";
import type { TrezorConnect } from "@trezor/connect-web";
import {
AddressResponse,
getAddressRequest,
Expand All @@ -13,10 +13,11 @@ import {
SignTransactionRequest,
} from "../../types";
import { supportedPaths } from "./configs";
import getTrezorConnect from "../trezorConnect";

class TrezorEthereum implements HWWalletProvider {
network: NetworkNames;

TrezorConnect: TrezorConnect;
HDNodes: Record<string, HDKey>;

constructor(network: NetworkNames) {
Expand All @@ -25,15 +26,7 @@ class TrezorEthereum implements HWWalletProvider {
}

async init(): Promise<boolean> {
TrezorConnect.init({
manifest: {
email: "info@enkrypt.com",
appUrl: "https://www.enkrypt.com",
},
transports: ["BridgeTransport", "WebUsbTransport"],
connectSrc: "https://connect.trezor.io/9/",
_extendWebextensionLifetime: true,
});
this.TrezorConnect = await getTrezorConnect();
return true;
Comment on lines 28 to 30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Updated init method for dynamic loading

The init method now properly uses the getTrezorConnect helper to dynamically load and initialize TrezorConnect.

Consider adding error handling to gracefully handle initialization failures:

 async init(): Promise<boolean> {
-   this.TrezorConnect = await getTrezorConnect();
-   return true;
+   try {
+     this.TrezorConnect = await getTrezorConnect();
+     return true;
+   } catch (error) {
+     console.error("Failed to initialize Trezor Connect:", error);
+     return false;
+   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async init(): Promise<boolean> {
TrezorConnect.init({
manifest: {
email: "info@enkrypt.com",
appUrl: "https://www.enkrypt.com",
},
transports: ["BridgeTransport", "WebUsbTransport"],
connectSrc: "https://connect.trezor.io/9/",
_extendWebextensionLifetime: true,
});
this.TrezorConnect = await getTrezorConnect();
return true;
async init(): Promise<boolean> {
try {
this.TrezorConnect = await getTrezorConnect();
return true;
} catch (error) {
console.error("Failed to initialize Trezor Connect:", error);
return false;
}
}
🤖 Prompt for AI Agents
In packages/hw-wallets/src/trezor/ethereum/index.ts around lines 28 to 30, the
init method currently calls getTrezorConnect without error handling. Modify the
init method to include a try-catch block that attempts to assign
this.TrezorConnect using await getTrezorConnect(), and returns true if
successful. In the catch block, log or handle the error appropriately and return
false to indicate initialization failure.

}

Expand All @@ -42,14 +35,14 @@ class TrezorEthereum implements HWWalletProvider {
return Promise.reject(new Error("trezor-ethereum: Invalid network name"));

if (!this.HDNodes[options.pathType.basePath]) {
const rootPub = await TrezorConnect.ethereumGetPublicKey({
const rootPub = await this.TrezorConnect.ethereumGetPublicKey({
path: options.pathType.basePath,
showOnTrezor: options.confirmAddress,
});
if (!rootPub.payload) {
throw new Error("popup failed to open");
}
if (!rootPub.success) throw new Error(rootPub.payload.error as string);
if (!rootPub.success) throw new Error((rootPub.payload as any).error);

const hdKey = new HDKey();
hdKey.publicKey = Buffer.from(rootPub.payload.publicKey, "hex");
Expand Down Expand Up @@ -78,12 +71,12 @@ class TrezorEthereum implements HWWalletProvider {
}

async signPersonalMessage(options: SignMessageRequest): Promise<string> {
const result = await TrezorConnect.ethereumSignMessage({
const result = await this.TrezorConnect.ethereumSignMessage({
path: options.pathType.path.replace(`{index}`, options.pathIndex),
message: options.message.toString("hex"),
hex: true,
});
if (!result.success) throw new Error(result.payload.error as string);
if (!result.success) throw new Error((result.payload as any).error);
return bufferToHex(hexToBuffer(result.payload.signature));
}

Expand All @@ -100,14 +93,14 @@ class TrezorEthereum implements HWWalletProvider {
data: bufferToHex(tx.data),
};
if ((options.transaction as LegacyTransaction).gasPrice) {
return TrezorConnect.ethereumSignTransaction({
return this.TrezorConnect.ethereumSignTransaction({
path: options.pathType.path.replace(`{index}`, options.pathIndex),
transaction: {
...txObject,
gasPrice: bigIntToHex(tx.gasPrice),
},
}).then((result) => {
if (!result.success) throw new Error(result.payload.error as string);
if (!result.success) throw new Error((result.payload as any).error);
const rv = BigInt(parseInt(result.payload.v, 16));
const cv = tx.common.chainId() * 2n + 35n;
return toRpcSig(
Expand All @@ -119,15 +112,15 @@ class TrezorEthereum implements HWWalletProvider {
}

tx = options.transaction as FeeMarketEIP1559Transaction;
return TrezorConnect.ethereumSignTransaction({
return this.TrezorConnect.ethereumSignTransaction({
path: options.pathType.path.replace(`{index}`, options.pathIndex),
transaction: {
...txObject,
maxFeePerGas: bigIntToHex(tx.maxFeePerGas),
maxPriorityFeePerGas: bigIntToHex(tx.maxPriorityFeePerGas),
},
}).then((result) => {
if (!result.success) throw new Error(result.payload.error as string);
if (!result.success) throw new Error((result.payload as any).error);
return toRpcSig(
BigInt(result.payload.v),
hexToBuffer(result.payload.r),
Expand Down
25 changes: 9 additions & 16 deletions packages/hw-wallets/src/trezor/solana/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import TrezorConnect from "@trezor/connect-webextension";
import type { TrezorConnect } from "@trezor/connect-web";
import { HWwalletCapabilities, NetworkNames } from "@enkryptcom/types";
import HDKey from "hdkey";
import base58 from "bs58";
Expand All @@ -12,10 +12,11 @@ import {
SolSignTransaction,
} from "../../types";
import { supportedPaths } from "./configs";
import getTrezorConnect from "../trezorConnect";

class TrezorSolana implements HWWalletProvider {
network: NetworkNames;

TrezorConnect: TrezorConnect;
HDNodes: Record<string, HDKey>;

constructor(network: NetworkNames) {
Expand All @@ -24,28 +25,20 @@ class TrezorSolana implements HWWalletProvider {
}

async init(): Promise<boolean> {
TrezorConnect.init({
manifest: {
email: "info@enkrypt.com",
appUrl: "https://www.enkrypt.com",
},
transports: ["BridgeTransport", "WebUsbTransport"],
connectSrc: "https://connect.trezor.io/9/",
_extendWebextensionLifetime: true,
});
this.TrezorConnect = await getTrezorConnect();
return true;
}
Comment on lines +28 to 30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling to init() method

The init() method doesn't handle potential errors from getTrezorConnect(). In production environments, initialization could fail for various reasons (connection issues, permissions, etc.).

async init(): Promise<boolean> {
-  this.TrezorConnect = await getTrezorConnect();
-  return true;
+  try {
+    this.TrezorConnect = await getTrezorConnect();
+    return true;
+  } catch (error) {
+    console.error('Failed to initialize TrezorConnect:', error);
+    return false;
+  }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.TrezorConnect = await getTrezorConnect();
return true;
}
async init(): Promise<boolean> {
try {
this.TrezorConnect = await getTrezorConnect();
return true;
} catch (error) {
console.error('Failed to initialize TrezorConnect:', error);
return false;
}
}
🤖 Prompt for AI Agents
In packages/hw-wallets/src/trezor/solana/index.ts around lines 28 to 30, the
init() method calls getTrezorConnect() without handling possible errors. Modify
the init() method to wrap the await getTrezorConnect() call in a try-catch
block, catch any errors thrown during the call, and handle them appropriately,
such as logging the error or rethrowing it, to ensure the method fails
gracefully in case of initialization issues.


async getAddress(options: getAddressRequest): Promise<AddressResponse> {
if (!supportedPaths[this.network])
return Promise.reject(new Error("trezor-bitcoin: Invalid network name"));
const res = await TrezorConnect.solanaGetAddress({
const res = await this.TrezorConnect.solanaGetAddress({
path: options.pathType.path.replace(`{index}`, options.pathIndex),
showOnTrezor: options.confirmAddress,
});
return {
address: bufferToHex(base58.decode(res.payload.address)),
publicKey: bufferToHex(base58.decode(res.payload.address)),
address: bufferToHex(base58.decode((res.payload as any).address)),
publicKey: bufferToHex(base58.decode((res.payload as any).address)),
Comment on lines +40 to +41
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Avoid type casting to any - define proper types instead

Type casting to any bypasses TypeScript's type checking system, which can lead to runtime errors if the expected properties don't exist. Consider creating proper interfaces that extend the TrezorConnect response types.

- address: bufferToHex(base58.decode((res.payload as any).address)),
- publicKey: bufferToHex(base58.decode((res.payload as any).address)),
+ address: bufferToHex(base58.decode((res.payload as SolanaGetAddressResponse).address)),
+ publicKey: bufferToHex(base58.decode((res.payload as SolanaGetAddressResponse).address)),

And similarly for the transaction signature:

- }).then((result) => (result.payload as any).signature);
+ }).then((result) => (result.payload as SolanaSignTransactionResponse).signature);

You'll need to define these interfaces (if they don't already exist in the TrezorConnect types):

interface SolanaGetAddressResponse {
  address: string;
  // other properties...
}

interface SolanaSignTransactionResponse {
  signature: string;
  // other properties...
}

Also applies to: 67-67

🤖 Prompt for AI Agents
In packages/hw-wallets/src/trezor/solana/index.ts around lines 40-41 and line
67, avoid using type casting to 'any' for the TrezorConnect response payload.
Instead, define proper TypeScript interfaces representing the expected response
structure, such as SolanaGetAddressResponse with an 'address' property and
SolanaSignTransactionResponse with a 'signature' property. Then, use these
interfaces to type the response payloads, enabling type-safe access to
properties without bypassing TypeScript's checks.

};
}

Expand All @@ -66,12 +59,12 @@ class TrezorSolana implements HWWalletProvider {
}

async signTransaction(options: SignTransactionRequest): Promise<string> {
return TrezorConnect.solanaSignTransaction({
return this.TrezorConnect.solanaSignTransaction({
path: options.pathType.path.replace(`{index}`, options.pathIndex),
serializedTx: (options.transaction as SolSignTransaction).solTx.toString(
"hex",
),
}).then((result) => result.payload.signature);
}).then((result) => (result.payload as any).signature);
}

static getSupportedNetworks(): NetworkNames[] {
Expand Down
29 changes: 29 additions & 0 deletions packages/hw-wallets/src/trezor/trezorConnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { TrezorConnect as TrezorConnectType } from "@trezor/connect-web";

const getTrezorConnect = async () => {
if (chrome && chrome.runtime && chrome.runtime.getPlatformInfo) {
const TrezorConnect = await import("@trezor/connect-webextension");
await TrezorConnect.default.init({
manifest: {
email: "info@enkrypt.com",
appUrl: "https://www.enkrypt.com",
},
transports: ["BridgeTransport", "WebUsbTransport"],
connectSrc: "https://connect.trezor.io/9/",
_extendWebextensionLifetime: true,
});
return TrezorConnect.default as TrezorConnectType;
} else {
const TrezorConnect = await import("@trezor/connect-web");
await TrezorConnect.default.init({
lazyLoad: true,
manifest: {
email: "info@enkrypt.com",
appUrl: "http://www.myetherwallet.com",
},
});
return TrezorConnect.default as TrezorConnectType;
}
};

export default getTrezorConnect;
Loading
Loading