Skip to content
This repository was archived by the owner on Oct 7, 2024. It is now read-only.
Open
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
94 changes: 46 additions & 48 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ class TrezorKeyring extends EventEmitter {
const status = await this.unlock();
await wait(status === 'just unlocked' ? DELAY_BETWEEN_POPUPS : 0);
const response = await TrezorConnect.ethereumSignTransaction({
path: this._pathFromAddress(address),
path: await this._pathFromAddress(address),
transaction,
});
if (response.success) {
Expand Down Expand Up @@ -344,51 +344,30 @@ class TrezorKeyring extends EventEmitter {
}

// For personal_sign, we need to prefix the message:
signPersonalMessage(withAccount, message) {
return new Promise((resolve, reject) => {
this.unlock()
.then((status) => {
setTimeout(
(_) => {
TrezorConnect.ethereumSignMessage({
path: this._pathFromAddress(withAccount),
message: ethUtil.stripHexPrefix(message),
hex: true,
})
.then((response) => {
if (response.success) {
if (
response.payload.address !==
ethUtil.toChecksumAddress(withAccount)
) {
reject(
new Error('signature doesnt match the right address'),
);
}
const signature = `0x${response.payload.signature}`;
resolve(signature);
} else {
reject(
new Error(
(response.payload && response.payload.error) ||
'Unknown error',
),
);
}
})
.catch((e) => {
reject(new Error((e && e.toString()) || 'Unknown error'));
});
// This is necessary to avoid popup collision
// between the unlock & sign trezor popups
},
status === 'just unlocked' ? DELAY_BETWEEN_POPUPS : 0,
);
})
.catch((e) => {
reject(new Error((e && e.toString()) || 'Unknown error'));
});
});
async signPersonalMessage(withAccount, message) {
try {
const status = await this.unlock();
await wait(status === 'just unlocked' ? DELAY_BETWEEN_POPUPS : 0);
const response = await TrezorConnect.ethereumSignMessage({
path: await this._pathFromAddress(withAccount),
message: ethUtil.stripHexPrefix(message),
hex: true,
});
if (response.success) {
if (
response.payload.address !== ethUtil.toChecksumAddress(withAccount)
) {
throw new Error("signature doesn't match the right address");
}
const signature = `0x${response.payload.signature}`;
return signature;
}
throw new Error(
(response.payload && response.payload.error) || 'Unknown error',
);
} catch (e) {
throw new Error((e && e.toString()) || 'Unknown error');
}
}

/**
Expand All @@ -415,7 +394,7 @@ class TrezorKeyring extends EventEmitter {
await wait(status === 'just unlocked' ? DELAY_BETWEEN_POPUPS : 0);

const response = await TrezorConnect.ethereumSignTypedData({
path: this._pathFromAddress(address),
path: await this._pathFromAddress(address),
data: {
types: { EIP712Domain, ...otherTypes },
message,
Expand Down Expand Up @@ -496,7 +475,26 @@ class TrezorKeyring extends EventEmitter {
return ethUtil.toChecksumAddress(`0x${address}`);
}

_pathFromAddress(address) {
async _pathFromAddress(address) {
// First, assert that the pubkey which MetaMask remembers is the same as the one Trezor knows
const response = await TrezorConnect.getPublicKey({
path: this.hdPath,
coin: 'ETH',
});
if (!response.success) {
throw new Error(
(response.payload && response.payload.error) || 'Unknown error',
);
}
const pubkeyInTrezor = response.payload.publicKey;
const pubkeyInMetaMask = this.hdk.publicKey.toString('hex');
if (pubkeyInTrezor !== pubkeyInMetaMask) {
throw new Error(
'The public key which MetaMask remembers is different from the one Trezor knows. Please set the correct account.',
);
}

// then, the prerequisite is met, so we can derive the address
const checksummedAddress = ethUtil.toChecksumAddress(address);
let index = this.paths[checksummedAddress];
if (typeof index === 'undefined') {
Expand Down
13 changes: 10 additions & 3 deletions test/test-eth-trezor-keyring.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ describe('TrezorKeyring', function () {
beforeEach(async function () {
keyring = new TrezorKeyring();
keyring.hdk = fakeHdKey;
// mock TrezorConnect.getPubicKey with fake accounts
sinon.stub(TrezorConnect, 'getPublicKey').callsFake((_) => {
return Promise.resolve({
success: true,
payload: {
publicKey: fakeHdKey.publicKey.toString('hex'),
chainCode: fakeHdKey.chainCode.toString('hex'),
},
});
});
});

afterEach(function () {
Expand Down Expand Up @@ -185,9 +195,6 @@ describe('TrezorKeyring', function () {
});

it('should call TrezorConnect.getPublicKey if we dont have a public key', async function () {
sinon
.stub(TrezorConnect, 'getPublicKey')
.callsFake(() => Promise.resolve({}));
keyring.hdk = new HDKey();
try {
await keyring.unlock();
Expand Down