@metamask/eth-ledger-bridge-keyring 2.0.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/ledger-bridge.d.ts +17 -7
- package/dist/ledger-bridge.js.map +1 -1
- package/dist/ledger-hw-app.d.ts +12 -0
- package/dist/ledger-hw-app.js +60 -0
- package/dist/ledger-hw-app.js.map +1 -0
- package/dist/ledger-iframe-bridge.d.ts +39 -37
- package/dist/ledger-iframe-bridge.js +51 -14
- package/dist/ledger-iframe-bridge.js.map +1 -1
- package/dist/ledger-keyring.d.ts +12 -9
- package/dist/ledger-keyring.js +36 -34
- package/dist/ledger-keyring.js.map +1 -1
- package/dist/ledger-mobile-bridge.d.ts +90 -0
- package/dist/ledger-mobile-bridge.js +173 -0
- package/dist/ledger-mobile-bridge.js.map +1 -0
- package/dist/ledger-transport-middleware.d.ts +40 -0
- package/dist/ledger-transport-middleware.js +69 -0
- package/dist/ledger-transport-middleware.js.map +1 -0
- package/dist/type.d.ts +5 -0
- package/dist/type.js +3 -0
- package/dist/type.js.map +1 -0
- package/package.json +8 -6
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [4.0.0]
|
|
10
|
+
### Added
|
|
11
|
+
- Add classes `LedgerMobileBridge`, `LedgerTransportMiddleware`, and `MetaMaskLedgerHwAppEth` to support Bluetooth as a HW Ledger Transport option ([#225](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/225))
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- **BREAKING**: The `LedgerKeyring` method `setAccountToUnlock` now only accepts an input of type `number` ([#225](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/225))
|
|
15
|
+
- **BREAKING**: Removed the `chainCode` property from the `GetPublicKeyResponse` type ([#225](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/225))
|
|
16
|
+
|
|
17
|
+
## [3.0.0]
|
|
18
|
+
### Added
|
|
19
|
+
- Add `getOptions` and `setOptions` methods to `LedgerBridge` interface ([#210](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/210))
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **BREAKING**: `LedgerIframeBridge` class constructor now takes an options object with `bridgeUrl` ([#210](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/210))
|
|
23
|
+
- **BREAKING**: `LedgerBridge` `init` function now takes no parameters ([#210](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/210))
|
|
24
|
+
- **BREAKING**: `LedgerBridgeKeyringOptions` no longer contain `bridgeUrl` ([#210](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/210))
|
|
25
|
+
- **BREAKING**: `LedgerBridge` interface is now parameterized over its option type ([#210](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/210))
|
|
26
|
+
- Minor performance enhancement ([#211](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/211))
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- **BREAKING**: `IFrameMessageResponse` now has more restrictive typings (#207) ([#207](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/207))
|
|
30
|
+
|
|
9
31
|
## [2.0.1]
|
|
10
32
|
### Fixed
|
|
11
33
|
- Fix `invalid rlp data` error for legacy transactions in `2.0.0` ([#212](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/212))
|
|
@@ -85,7 +107,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
85
107
|
### Added
|
|
86
108
|
- Support new versions of ethereumjs/tx ([#68](https://github.com/MetaMask/eth-ledger-bridge-keyring/pull/68))
|
|
87
109
|
|
|
88
|
-
[Unreleased]: https://github.com/MetaMask/eth-ledger-bridge-keyring/compare/
|
|
110
|
+
[Unreleased]: https://github.com/MetaMask/eth-ledger-bridge-keyring/compare/v4.0.0...HEAD
|
|
111
|
+
[4.0.0]: https://github.com/MetaMask/eth-ledger-bridge-keyring/compare/v3.0.0...v4.0.0
|
|
112
|
+
[3.0.0]: https://github.com/MetaMask/eth-ledger-bridge-keyring/compare/v2.0.1...v3.0.0
|
|
89
113
|
[2.0.1]: https://github.com/MetaMask/eth-ledger-bridge-keyring/compare/v2.0.0...v2.0.1
|
|
90
114
|
[2.0.0]: https://github.com/MetaMask/eth-ledger-bridge-keyring/compare/v1.0.1...v2.0.0
|
|
91
115
|
[1.0.1]: https://github.com/MetaMask/eth-ledger-bridge-keyring/compare/v1.0.0...v1.0.1
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -16,5 +16,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./ledger-keyring"), exports);
|
|
18
18
|
__exportStar(require("./ledger-iframe-bridge"), exports);
|
|
19
|
+
__exportStar(require("./ledger-mobile-bridge"), exports);
|
|
19
20
|
__exportStar(require("./ledger-bridge"), exports);
|
|
21
|
+
__exportStar(require("./ledger-transport-middleware"), exports);
|
|
22
|
+
__exportStar(require("./type"), exports);
|
|
23
|
+
__exportStar(require("./ledger-hw-app"), exports);
|
|
20
24
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,yDAAuC;AACvC,kDAAgC","sourcesContent":["export * from './ledger-keyring';\nexport * from './ledger-iframe-bridge';\nexport * from './ledger-bridge';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mDAAiC;AACjC,yDAAuC;AACvC,yDAAuC;AACvC,kDAAgC;AAChC,gEAA8C;AAC9C,yCAAuB;AACvB,kDAAgC","sourcesContent":["export * from './ledger-keyring';\nexport * from './ledger-iframe-bridge';\nexport * from './ledger-mobile-bridge';\nexport * from './ledger-bridge';\nexport * from './ledger-transport-middleware';\nexport * from './type';\nexport * from './ledger-hw-app';\n"]}
|
package/dist/ledger-bridge.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type LedgerHwAppEth from '@ledgerhq/hw-app-eth';
|
|
2
|
+
import type Transport from '@ledgerhq/hw-transport';
|
|
2
3
|
export declare type GetPublicKeyParams = {
|
|
3
4
|
hdPath: string;
|
|
4
5
|
};
|
|
5
|
-
export declare type GetPublicKeyResponse = Awaited<ReturnType<LedgerHwAppEth['getAddress']
|
|
6
|
-
chainCode: string;
|
|
7
|
-
};
|
|
6
|
+
export declare type GetPublicKeyResponse = Awaited<ReturnType<LedgerHwAppEth['getAddress']>>;
|
|
8
7
|
export declare type LedgerSignTransactionParams = {
|
|
9
8
|
hdPath: string;
|
|
10
9
|
tx: string;
|
|
@@ -21,14 +20,25 @@ export declare type LedgerSignTypedDataParams = {
|
|
|
21
20
|
hashStructMessageHex: string;
|
|
22
21
|
};
|
|
23
22
|
export declare type LedgerSignTypedDataResponse = Awaited<ReturnType<LedgerHwAppEth['signEIP712HashedMessage']>>;
|
|
24
|
-
export
|
|
23
|
+
export declare type LedgerBridgeOptions = Record<string, unknown>;
|
|
24
|
+
export declare type LedgerBridge<T extends LedgerBridgeOptions> = {
|
|
25
25
|
isDeviceConnected: boolean;
|
|
26
|
-
init(
|
|
26
|
+
init(): Promise<void>;
|
|
27
27
|
destroy(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Method to get the current configuration of the ledger bridge keyring.
|
|
30
|
+
*/
|
|
31
|
+
getOptions(): Promise<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Method to set the current configuration of the ledger bridge keyring.
|
|
34
|
+
*
|
|
35
|
+
* @param opts - An object contains configuration of the bridge.
|
|
36
|
+
*/
|
|
37
|
+
setOptions(opts: T): Promise<void>;
|
|
28
38
|
attemptMakeApp(): Promise<boolean>;
|
|
29
|
-
updateTransportMethod(transportType: string): Promise<boolean>;
|
|
39
|
+
updateTransportMethod(transportType: string | Transport): Promise<boolean>;
|
|
30
40
|
getPublicKey(params: GetPublicKeyParams): Promise<GetPublicKeyResponse>;
|
|
31
41
|
deviceSignTransaction(params: LedgerSignTransactionParams): Promise<LedgerSignTransactionResponse>;
|
|
32
42
|
deviceSignMessage(params: LedgerSignMessageParams): Promise<LedgerSignMessageResponse>;
|
|
33
43
|
deviceSignTypedData(params: LedgerSignTypedDataParams): Promise<LedgerSignTypedDataResponse>;
|
|
34
|
-
}
|
|
44
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger-bridge.js","sourceRoot":"","sources":["../src/ledger-bridge.ts"],"names":[],"mappings":"","sourcesContent":["import type LedgerHwAppEth from '@ledgerhq/hw-app-eth';\n\nexport type GetPublicKeyParams = { hdPath: string };\nexport type GetPublicKeyResponse = Awaited<\n ReturnType<LedgerHwAppEth['getAddress']>\n
|
|
1
|
+
{"version":3,"file":"ledger-bridge.js","sourceRoot":"","sources":["../src/ledger-bridge.ts"],"names":[],"mappings":"","sourcesContent":["import type LedgerHwAppEth from '@ledgerhq/hw-app-eth';\nimport type Transport from '@ledgerhq/hw-transport';\n\nexport type GetPublicKeyParams = { hdPath: string };\nexport type GetPublicKeyResponse = Awaited<\n ReturnType<LedgerHwAppEth['getAddress']>\n>;\n\nexport type LedgerSignTransactionParams = { hdPath: string; tx: string };\nexport type LedgerSignTransactionResponse = Awaited<\n ReturnType<LedgerHwAppEth['signTransaction']>\n>;\n\nexport type LedgerSignMessageParams = { hdPath: string; message: string };\nexport type LedgerSignMessageResponse = Awaited<\n ReturnType<LedgerHwAppEth['signPersonalMessage']>\n>;\n\nexport type LedgerSignTypedDataParams = {\n hdPath: string;\n domainSeparatorHex: string;\n hashStructMessageHex: string;\n};\nexport type LedgerSignTypedDataResponse = Awaited<\n ReturnType<LedgerHwAppEth['signEIP712HashedMessage']>\n>;\n\nexport type LedgerBridgeOptions = Record<string, unknown>;\n\nexport type LedgerBridge<T extends LedgerBridgeOptions> = {\n isDeviceConnected: boolean;\n\n init(): Promise<void>;\n\n destroy(): Promise<void>;\n\n /**\n * Method to get the current configuration of the ledger bridge keyring.\n */\n getOptions(): Promise<T>;\n\n /**\n * Method to set the current configuration of the ledger bridge keyring.\n *\n * @param opts - An object contains configuration of the bridge.\n */\n setOptions(opts: T): Promise<void>;\n\n attemptMakeApp(): Promise<boolean>;\n\n updateTransportMethod(transportType: string | Transport): Promise<boolean>;\n\n getPublicKey(params: GetPublicKeyParams): Promise<GetPublicKeyResponse>;\n\n deviceSignTransaction(\n params: LedgerSignTransactionParams,\n ): Promise<LedgerSignTransactionResponse>;\n\n deviceSignMessage(\n params: LedgerSignMessageParams,\n ): Promise<LedgerSignMessageResponse>;\n\n deviceSignTypedData(\n params: LedgerSignTypedDataParams,\n ): Promise<LedgerSignTypedDataResponse>;\n};\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import LedgerHwAppEth from '@ledgerhq/hw-app-eth';
|
|
2
|
+
import { GetAppNameAndVersionResponse } from './type';
|
|
3
|
+
export interface MetaMaskLedgerHwAppEth extends LedgerHwAppEth {
|
|
4
|
+
openEthApp(): void;
|
|
5
|
+
closeApps(): void;
|
|
6
|
+
getAppNameAndVersion(): Promise<GetAppNameAndVersionResponse>;
|
|
7
|
+
}
|
|
8
|
+
export declare class MetaMaskLedgerHwAppEth extends LedgerHwAppEth implements MetaMaskLedgerHwAppEth {
|
|
9
|
+
readonly mainAppName = "BOLOS";
|
|
10
|
+
readonly ethAppName = "Ethereum";
|
|
11
|
+
readonly transportEncoding = "ascii";
|
|
12
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.MetaMaskLedgerHwAppEth = void 0;
|
|
7
|
+
const hw_app_eth_1 = __importDefault(require("@ledgerhq/hw-app-eth"));
|
|
8
|
+
// eslint-disable-next-line import/no-nodejs-modules
|
|
9
|
+
const buffer_1 = require("buffer");
|
|
10
|
+
class MetaMaskLedgerHwAppEth extends hw_app_eth_1.default {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.mainAppName = 'BOLOS';
|
|
14
|
+
this.ethAppName = 'Ethereum';
|
|
15
|
+
this.transportEncoding = 'ascii';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Method to open ethereum application on ledger device.
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
async openEthApp() {
|
|
22
|
+
await this.transport.send(0xe0, 0xd8, 0x00, 0x00, buffer_1.Buffer.from(this.ethAppName, this.transportEncoding));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Method to close all running application on ledger device.
|
|
26
|
+
*
|
|
27
|
+
*/
|
|
28
|
+
async closeApps() {
|
|
29
|
+
await this.transport.send(0xb0, 0xa7, 0x00, 0x00);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Method to retrieve the name and version of the running application in ledger device.
|
|
33
|
+
*
|
|
34
|
+
* @returns An object contains appName and version.
|
|
35
|
+
*/
|
|
36
|
+
async getAppNameAndVersion() {
|
|
37
|
+
var _a, _b;
|
|
38
|
+
const response = await this.transport.send(0xb0, 0x01, 0x00, 0x00);
|
|
39
|
+
if (response[0] !== 1) {
|
|
40
|
+
throw new Error('Incorrect format return from getAppNameAndVersion.');
|
|
41
|
+
}
|
|
42
|
+
let i = 1;
|
|
43
|
+
const nameLength = (_a = response[i]) !== null && _a !== void 0 ? _a : 0;
|
|
44
|
+
i += 1;
|
|
45
|
+
const appName = response
|
|
46
|
+
.slice(i, (i += nameLength))
|
|
47
|
+
.toString(this.transportEncoding);
|
|
48
|
+
const versionLength = (_b = response[i]) !== null && _b !== void 0 ? _b : 0;
|
|
49
|
+
i += 1;
|
|
50
|
+
const version = response
|
|
51
|
+
.slice(i, (i += versionLength))
|
|
52
|
+
.toString(this.transportEncoding);
|
|
53
|
+
return {
|
|
54
|
+
appName,
|
|
55
|
+
version,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.MetaMaskLedgerHwAppEth = MetaMaskLedgerHwAppEth;
|
|
60
|
+
//# sourceMappingURL=ledger-hw-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ledger-hw-app.js","sourceRoot":"","sources":["../src/ledger-hw-app.ts"],"names":[],"mappings":";;;;;;AAAA,sEAAkD;AAClD,oDAAoD;AACpD,mCAAgC;AAWhC,MAAa,sBACX,SAAQ,oBAAc;IADxB;;QAIW,gBAAW,GAAG,OAAO,CAAC;QAEtB,eAAU,GAAG,UAAU,CAAC;QAExB,sBAAiB,GAAG,OAAO,CAAC;IAuDvC,CAAC;IArDC;;;OAGG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CACvB,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,iBAAiB,CAAC,CACrD,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,oBAAoB;;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACnE,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;YACrB,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;SACvE;QAED,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,MAAM,UAAU,GAAG,MAAA,QAAQ,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAC;QACpC,CAAC,IAAI,CAAC,CAAC;QAEP,MAAM,OAAO,GAAG,QAAQ;aACrB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC;aAC3B,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAEpC,MAAM,aAAa,GAAG,MAAA,QAAQ,CAAC,CAAC,CAAC,mCAAI,CAAC,CAAC;QACvC,CAAC,IAAI,CAAC,CAAC;QAEP,MAAM,OAAO,GAAG,QAAQ;aACrB,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,aAAa,CAAC,CAAC;aAC9B,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAEpC,OAAO;YACL,OAAO;YACP,OAAO;SACR,CAAC;IACJ,CAAC;CACF;AA/DD,wDA+DC","sourcesContent":["import LedgerHwAppEth from '@ledgerhq/hw-app-eth';\n// eslint-disable-next-line import/no-nodejs-modules\nimport { Buffer } from 'buffer';\n\nimport { GetAppNameAndVersionResponse } from './type';\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface MetaMaskLedgerHwAppEth extends LedgerHwAppEth {\n openEthApp(): void;\n closeApps(): void;\n getAppNameAndVersion(): Promise<GetAppNameAndVersionResponse>;\n}\n\nexport class MetaMaskLedgerHwAppEth\n extends LedgerHwAppEth\n implements MetaMaskLedgerHwAppEth\n{\n readonly mainAppName = 'BOLOS';\n\n readonly ethAppName = 'Ethereum';\n\n readonly transportEncoding = 'ascii';\n\n /**\n * Method to open ethereum application on ledger device.\n *\n */\n async openEthApp(): Promise<void> {\n await this.transport.send(\n 0xe0,\n 0xd8,\n 0x00,\n 0x00,\n Buffer.from(this.ethAppName, this.transportEncoding),\n );\n }\n\n /**\n * Method to close all running application on ledger device.\n *\n */\n async closeApps(): Promise<void> {\n await this.transport.send(0xb0, 0xa7, 0x00, 0x00);\n }\n\n /**\n * Method to retrieve the name and version of the running application in ledger device.\n *\n * @returns An object contains appName and version.\n */\n async getAppNameAndVersion(): Promise<GetAppNameAndVersionResponse> {\n const response = await this.transport.send(0xb0, 0x01, 0x00, 0x00);\n if (response[0] !== 1) {\n throw new Error('Incorrect format return from getAppNameAndVersion.');\n }\n\n let i = 1;\n const nameLength = response[i] ?? 0;\n i += 1;\n\n const appName = response\n .slice(i, (i += nameLength))\n .toString(this.transportEncoding);\n\n const versionLength = response[i] ?? 0;\n i += 1;\n\n const version = response\n .slice(i, (i += versionLength))\n .toString(this.transportEncoding);\n\n return {\n appName,\n version,\n };\n }\n}\n"]}
|
|
@@ -8,73 +8,75 @@ export declare enum IFrameMessageAction {
|
|
|
8
8
|
LedgerSignPersonalMessage = "ledger-sign-personal-message",
|
|
9
9
|
LedgerSignTypedData = "ledger-sign-typed-data"
|
|
10
10
|
}
|
|
11
|
-
declare type
|
|
12
|
-
action: TAction;
|
|
11
|
+
declare type IFrameMessageResponseStub<SuccessResult extends Record<string, unknown>, FailureResult = Error> = {
|
|
13
12
|
messageId: number;
|
|
14
13
|
} & ({
|
|
14
|
+
success: true;
|
|
15
|
+
payload: SuccessResult;
|
|
16
|
+
} | {
|
|
17
|
+
success: false;
|
|
18
|
+
payload: {
|
|
19
|
+
error: FailureResult;
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
declare type LedgerConnectionChangeActionResponse = {
|
|
23
|
+
messageId: number;
|
|
15
24
|
action: IFrameMessageAction.LedgerConnectionChange;
|
|
16
25
|
payload: {
|
|
17
26
|
connected: boolean;
|
|
18
27
|
};
|
|
19
|
-
}
|
|
28
|
+
};
|
|
29
|
+
declare type LedgerMakeAppActionResponse = {
|
|
30
|
+
messageId: number;
|
|
20
31
|
action: IFrameMessageAction.LedgerMakeApp;
|
|
21
32
|
} & ({
|
|
22
33
|
success: true;
|
|
23
34
|
} | {
|
|
24
35
|
success: false;
|
|
25
36
|
error?: unknown;
|
|
26
|
-
})
|
|
37
|
+
});
|
|
38
|
+
declare type LedgerUpdateTransportActionResponse = {
|
|
39
|
+
messageId: number;
|
|
27
40
|
action: IFrameMessageAction.LedgerUpdateTransport;
|
|
28
41
|
success: boolean;
|
|
29
|
-
}
|
|
42
|
+
};
|
|
43
|
+
declare type LedgerUnlockActionResponse = {
|
|
30
44
|
action: IFrameMessageAction.LedgerUnlock;
|
|
31
|
-
} &
|
|
32
|
-
|
|
33
|
-
payload: GetPublicKeyResponse;
|
|
34
|
-
} | {
|
|
35
|
-
success: false;
|
|
36
|
-
payload: {
|
|
37
|
-
error: Error;
|
|
38
|
-
};
|
|
39
|
-
})) | ({
|
|
45
|
+
} & IFrameMessageResponseStub<GetPublicKeyResponse>;
|
|
46
|
+
declare type LedgerSignTransactionActionResponse = {
|
|
40
47
|
action: IFrameMessageAction.LedgerSignTransaction;
|
|
41
|
-
} &
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
payload: LedgerSignMessageResponse | LedgerSignTypedDataResponse;
|
|
54
|
-
} | {
|
|
55
|
-
success: false;
|
|
56
|
-
payload: {
|
|
57
|
-
error: Error;
|
|
58
|
-
};
|
|
59
|
-
})));
|
|
60
|
-
export declare class LedgerIframeBridge implements LedgerBridge {
|
|
48
|
+
} & IFrameMessageResponseStub<LedgerSignTransactionResponse>;
|
|
49
|
+
declare type LedgerSignPersonalMessageActionResponse = {
|
|
50
|
+
action: IFrameMessageAction.LedgerSignPersonalMessage;
|
|
51
|
+
} & IFrameMessageResponseStub<LedgerSignMessageResponse>;
|
|
52
|
+
declare type LedgerSignTypedDataActionResponse = {
|
|
53
|
+
action: IFrameMessageAction.LedgerSignTypedData;
|
|
54
|
+
} & IFrameMessageResponseStub<LedgerSignTypedDataResponse>;
|
|
55
|
+
export declare type IFrameMessageResponse = LedgerConnectionChangeActionResponse | LedgerMakeAppActionResponse | LedgerUpdateTransportActionResponse | LedgerUnlockActionResponse | LedgerSignTransactionActionResponse | LedgerSignPersonalMessageActionResponse | LedgerSignTypedDataActionResponse;
|
|
56
|
+
export declare type LedgerIframeBridgeOptions = {
|
|
57
|
+
bridgeUrl: string;
|
|
58
|
+
};
|
|
59
|
+
export declare class LedgerIframeBridge implements LedgerBridge<LedgerIframeBridgeOptions> {
|
|
61
60
|
#private;
|
|
62
61
|
iframe?: HTMLIFrameElement;
|
|
63
62
|
iframeLoaded: boolean;
|
|
64
63
|
eventListener?: (eventMessage: {
|
|
65
64
|
origin: string;
|
|
66
|
-
data: IFrameMessageResponse
|
|
65
|
+
data: IFrameMessageResponse;
|
|
67
66
|
}) => void;
|
|
68
67
|
isDeviceConnected: boolean;
|
|
69
68
|
currentMessageId: number;
|
|
70
|
-
messageCallbacks: Record<number, (response: IFrameMessageResponse
|
|
69
|
+
messageCallbacks: Record<number, (response: IFrameMessageResponse) => void>;
|
|
71
70
|
delayedPromise?: {
|
|
72
71
|
resolve: (value: boolean) => void;
|
|
73
72
|
reject: (error: unknown) => void;
|
|
74
73
|
transportType: string;
|
|
75
74
|
};
|
|
76
|
-
|
|
75
|
+
constructor(opts?: LedgerIframeBridgeOptions);
|
|
76
|
+
init(): Promise<void>;
|
|
77
77
|
destroy(): Promise<void>;
|
|
78
|
+
getOptions(): Promise<LedgerIframeBridgeOptions>;
|
|
79
|
+
setOptions(opts: LedgerIframeBridgeOptions): Promise<void>;
|
|
78
80
|
attemptMakeApp(): Promise<boolean>;
|
|
79
81
|
updateTransportMethod(transportType: string): Promise<boolean>;
|
|
80
82
|
getPublicKey(params: GetPublicKeyParams): Promise<GetPublicKeyResponse>;
|
|
@@ -4,7 +4,13 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
5
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
6
|
};
|
|
7
|
-
var
|
|
7
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
8
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
|
+
};
|
|
13
|
+
var _LedgerIframeBridge_instances, _LedgerIframeBridge_opts, _LedgerIframeBridge_deviceActionMessage, _LedgerIframeBridge_setupIframe, _LedgerIframeBridge_getOrigin, _LedgerIframeBridge_eventListener, _LedgerIframeBridge_sendMessage, _LedgerIframeBridge_validateConfiguration;
|
|
8
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
15
|
exports.LedgerIframeBridge = exports.IFrameMessageAction = void 0;
|
|
10
16
|
const LEDGER_IFRAME_ID = 'LEDGER-IFRAME';
|
|
@@ -19,16 +25,23 @@ var IFrameMessageAction;
|
|
|
19
25
|
IFrameMessageAction["LedgerSignTypedData"] = "ledger-sign-typed-data";
|
|
20
26
|
})(IFrameMessageAction = exports.IFrameMessageAction || (exports.IFrameMessageAction = {}));
|
|
21
27
|
class LedgerIframeBridge {
|
|
22
|
-
constructor(
|
|
28
|
+
constructor(opts = {
|
|
29
|
+
bridgeUrl: 'https://metamask.github.io/eth-ledger-bridge-keyring',
|
|
30
|
+
}) {
|
|
23
31
|
_LedgerIframeBridge_instances.add(this);
|
|
24
32
|
this.iframeLoaded = false;
|
|
33
|
+
_LedgerIframeBridge_opts.set(this, void 0);
|
|
25
34
|
this.isDeviceConnected = false;
|
|
26
35
|
this.currentMessageId = 0;
|
|
27
36
|
this.messageCallbacks = {};
|
|
37
|
+
__classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_validateConfiguration).call(this, opts);
|
|
38
|
+
__classPrivateFieldSet(this, _LedgerIframeBridge_opts, {
|
|
39
|
+
bridgeUrl: opts === null || opts === void 0 ? void 0 : opts.bridgeUrl,
|
|
40
|
+
}, "f");
|
|
28
41
|
}
|
|
29
|
-
async init(
|
|
30
|
-
__classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_setupIframe).call(this, bridgeUrl);
|
|
31
|
-
this.eventListener = __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_eventListener).bind(this, bridgeUrl);
|
|
42
|
+
async init() {
|
|
43
|
+
__classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_setupIframe).call(this, __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f").bridgeUrl);
|
|
44
|
+
this.eventListener = __classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_eventListener).bind(this, __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f").bridgeUrl);
|
|
32
45
|
window.addEventListener('message', this.eventListener);
|
|
33
46
|
}
|
|
34
47
|
async destroy() {
|
|
@@ -36,17 +49,32 @@ class LedgerIframeBridge {
|
|
|
36
49
|
window.removeEventListener('message', this.eventListener);
|
|
37
50
|
}
|
|
38
51
|
}
|
|
52
|
+
async getOptions() {
|
|
53
|
+
return __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f");
|
|
54
|
+
}
|
|
55
|
+
async setOptions(opts) {
|
|
56
|
+
var _a;
|
|
57
|
+
__classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_validateConfiguration).call(this, opts);
|
|
58
|
+
if (((_a = __classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f")) === null || _a === void 0 ? void 0 : _a.bridgeUrl) !== opts.bridgeUrl) {
|
|
59
|
+
__classPrivateFieldGet(this, _LedgerIframeBridge_opts, "f").bridgeUrl = opts.bridgeUrl;
|
|
60
|
+
await this.destroy();
|
|
61
|
+
await this.init();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
39
64
|
async attemptMakeApp() {
|
|
40
65
|
return new Promise((resolve, reject) => {
|
|
41
66
|
__classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_sendMessage).call(this, {
|
|
42
67
|
action: IFrameMessageAction.LedgerMakeApp,
|
|
43
68
|
}, (response) => {
|
|
44
|
-
if (response.success) {
|
|
69
|
+
if ('success' in response && response.success) {
|
|
45
70
|
resolve(true);
|
|
46
71
|
}
|
|
47
|
-
else {
|
|
72
|
+
else if ('error' in response) {
|
|
48
73
|
reject(response.error);
|
|
49
74
|
}
|
|
75
|
+
else {
|
|
76
|
+
reject(new Error('Unknown error occurred'));
|
|
77
|
+
}
|
|
50
78
|
});
|
|
51
79
|
});
|
|
52
80
|
}
|
|
@@ -65,8 +93,8 @@ class LedgerIframeBridge {
|
|
|
65
93
|
__classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_sendMessage).call(this, {
|
|
66
94
|
action: IFrameMessageAction.LedgerUpdateTransport,
|
|
67
95
|
params: { transportType },
|
|
68
|
-
}, (
|
|
69
|
-
if (success) {
|
|
96
|
+
}, (response) => {
|
|
97
|
+
if ('success' in response && response.success) {
|
|
70
98
|
return resolve(true);
|
|
71
99
|
}
|
|
72
100
|
return reject(new Error('Ledger transport could not be updated'));
|
|
@@ -87,16 +115,21 @@ class LedgerIframeBridge {
|
|
|
87
115
|
}
|
|
88
116
|
}
|
|
89
117
|
exports.LedgerIframeBridge = LedgerIframeBridge;
|
|
90
|
-
_LedgerIframeBridge_instances = new WeakSet(), _LedgerIframeBridge_deviceActionMessage = async function _LedgerIframeBridge_deviceActionMessage(...[action, params]) {
|
|
118
|
+
_LedgerIframeBridge_opts = new WeakMap(), _LedgerIframeBridge_instances = new WeakSet(), _LedgerIframeBridge_deviceActionMessage = async function _LedgerIframeBridge_deviceActionMessage(...[action, params]) {
|
|
91
119
|
return new Promise((resolve, reject) => {
|
|
92
120
|
__classPrivateFieldGet(this, _LedgerIframeBridge_instances, "m", _LedgerIframeBridge_sendMessage).call(this, {
|
|
93
121
|
action,
|
|
94
122
|
params,
|
|
95
|
-
}, (
|
|
96
|
-
if (
|
|
97
|
-
|
|
123
|
+
}, (response) => {
|
|
124
|
+
if ('payload' in response && response.payload) {
|
|
125
|
+
if ('success' in response && response.success) {
|
|
126
|
+
return resolve(response.payload);
|
|
127
|
+
}
|
|
128
|
+
if ('error' in response.payload) {
|
|
129
|
+
return reject(response.payload.error);
|
|
130
|
+
}
|
|
98
131
|
}
|
|
99
|
-
return reject(
|
|
132
|
+
return reject(new Error('Unknown error occurred'));
|
|
100
133
|
});
|
|
101
134
|
});
|
|
102
135
|
}, _LedgerIframeBridge_setupIframe = function _LedgerIframeBridge_setupIframe(bridgeUrl) {
|
|
@@ -146,5 +179,9 @@ _LedgerIframeBridge_instances = new WeakSet(), _LedgerIframeBridge_deviceActionM
|
|
|
146
179
|
throw new Error('The iframe is not loaded yet');
|
|
147
180
|
}
|
|
148
181
|
this.iframe.contentWindow.postMessage(postMsg, '*');
|
|
182
|
+
}, _LedgerIframeBridge_validateConfiguration = function _LedgerIframeBridge_validateConfiguration(opts) {
|
|
183
|
+
if (typeof opts.bridgeUrl !== 'string' || opts.bridgeUrl.length === 0) {
|
|
184
|
+
throw new Error('bridgeURL is not a valid URL');
|
|
185
|
+
}
|
|
149
186
|
};
|
|
150
187
|
//# sourceMappingURL=ledger-iframe-bridge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledger-iframe-bridge.js","sourceRoot":"","sources":["../src/ledger-iframe-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n GetPublicKeyParams,\n GetPublicKeyResponse,\n LedgerBridge,\n LedgerSignMessageParams,\n LedgerSignMessageResponse,\n LedgerSignTransactionParams,\n LedgerSignTransactionResponse,\n LedgerSignTypedDataParams,\n LedgerSignTypedDataResponse,\n} from './ledger-bridge';\n\nconst LEDGER_IFRAME_ID = 'LEDGER-IFRAME';\n\nexport enum IFrameMessageAction {\n LedgerConnectionChange = 'ledger-connection-change',\n LedgerUnlock = 'ledger-unlock',\n LedgerMakeApp = 'ledger-make-app',\n LedgerUpdateTransport = 'ledger-update-transport',\n LedgerSignTransaction = 'ledger-sign-transaction',\n LedgerSignPersonalMessage = 'ledger-sign-personal-message',\n LedgerSignTypedData = 'ledger-sign-typed-data',\n}\n\ntype IFrameMessageResponse<TAction extends IFrameMessageAction> = {\n action: TAction;\n messageId: number;\n} & (\n | {\n action: IFrameMessageAction.LedgerConnectionChange;\n payload: { connected: boolean };\n }\n | ({\n action: IFrameMessageAction.LedgerMakeApp;\n } & ({ success: true } | { success: false; error?: unknown }))\n | {\n action: IFrameMessageAction.LedgerUpdateTransport;\n success: boolean;\n }\n | ({\n action: IFrameMessageAction.LedgerUnlock;\n } & (\n | { success: true; payload: GetPublicKeyResponse }\n | { success: false; payload: { error: Error } }\n ))\n | ({\n action: IFrameMessageAction.LedgerSignTransaction;\n } & (\n | { success: true; payload: LedgerSignTransactionResponse }\n | { success: false; payload: { error: Error } }\n ))\n | ({\n action:\n | IFrameMessageAction.LedgerSignPersonalMessage\n | IFrameMessageAction.LedgerSignTypedData;\n } & (\n | {\n success: true;\n payload: LedgerSignMessageResponse | LedgerSignTypedDataResponse;\n }\n | { success: false; payload: { error: Error } }\n ))\n);\n\ntype IFrameMessage<TAction extends IFrameMessageAction> = {\n action: TAction;\n params?: Readonly<Record<string, unknown>>;\n};\n\ntype IFramePostMessage<TAction extends IFrameMessageAction> =\n IFrameMessage<TAction> & {\n messageId: number;\n target: typeof LEDGER_IFRAME_ID;\n };\n\nexport class LedgerIframeBridge implements LedgerBridge {\n iframe?: HTMLIFrameElement;\n\n iframeLoaded = false;\n\n eventListener?: (eventMessage: {\n origin: string;\n data: IFrameMessageResponse<IFrameMessageAction>;\n }) => void;\n\n isDeviceConnected = false;\n\n currentMessageId = 0;\n\n messageCallbacks: Record<\n number,\n (response: IFrameMessageResponse<IFrameMessageAction>) => void\n > = {};\n\n delayedPromise?: {\n resolve: (value: boolean) => void;\n reject: (error: unknown) => void;\n transportType: string;\n };\n\n async init(bridgeUrl: string) {\n this.#setupIframe(bridgeUrl);\n\n this.eventListener = this.#eventListener.bind(this, bridgeUrl);\n\n window.addEventListener('message', this.eventListener);\n }\n\n async destroy() {\n if (this.eventListener) {\n window.removeEventListener('message', this.eventListener);\n }\n }\n\n async attemptMakeApp(): Promise<boolean> {\n return new Promise((resolve, reject) => {\n this.#sendMessage(\n {\n action: IFrameMessageAction.LedgerMakeApp,\n },\n (response) => {\n if (response.success) {\n resolve(true);\n } else {\n reject(response.error);\n }\n },\n );\n });\n }\n\n async updateTransportMethod(transportType: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n // If the iframe isn't loaded yet, let's store the desired transportType value and\n // optimistically return a successful promise\n if (!this.iframeLoaded) {\n this.delayedPromise = {\n resolve,\n reject,\n transportType,\n };\n return;\n }\n\n this.#sendMessage(\n {\n action: IFrameMessageAction.LedgerUpdateTransport,\n params: { transportType },\n },\n ({ success }) => {\n if (success) {\n return resolve(true);\n }\n return reject(new Error('Ledger transport could not be updated'));\n },\n );\n });\n }\n\n async getPublicKey(\n params: GetPublicKeyParams,\n ): Promise<GetPublicKeyResponse> {\n return this.#deviceActionMessage(IFrameMessageAction.LedgerUnlock, params);\n }\n\n async deviceSignTransaction(\n params: LedgerSignTransactionParams,\n ): Promise<LedgerSignTransactionResponse> {\n return this.#deviceActionMessage(\n IFrameMessageAction.LedgerSignTransaction,\n params,\n );\n }\n\n async deviceSignMessage(\n params: LedgerSignMessageParams,\n ): Promise<LedgerSignMessageResponse> {\n return this.#deviceActionMessage(\n IFrameMessageAction.LedgerSignPersonalMessage,\n params,\n );\n }\n\n async deviceSignTypedData(\n params: LedgerSignTypedDataParams,\n ): Promise<LedgerSignTypedDataResponse> {\n return this.#deviceActionMessage(\n IFrameMessageAction.LedgerSignTypedData,\n params,\n );\n }\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerUnlock,\n params: GetPublicKeyParams,\n ): Promise<GetPublicKeyResponse>;\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerSignTransaction,\n params: LedgerSignTransactionParams,\n ): Promise<LedgerSignTransactionResponse>;\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerSignPersonalMessage,\n params: LedgerSignMessageParams,\n ): Promise<LedgerSignMessageResponse>;\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerSignTypedData,\n params: LedgerSignTypedDataParams,\n ): Promise<LedgerSignTypedDataResponse>;\n\n async #deviceActionMessage(\n ...[action, params]:\n | [IFrameMessageAction.LedgerUnlock, GetPublicKeyParams]\n | [IFrameMessageAction.LedgerSignTransaction, LedgerSignTransactionParams]\n | [IFrameMessageAction.LedgerSignPersonalMessage, LedgerSignMessageParams]\n | [IFrameMessageAction.LedgerSignTypedData, LedgerSignTypedDataParams]\n ) {\n return new Promise((resolve, reject) => {\n this.#sendMessage(\n {\n action,\n params,\n },\n ({ success, payload }) => {\n if (success) {\n return resolve(payload);\n }\n return reject(payload.error);\n },\n );\n });\n }\n\n #setupIframe(bridgeUrl: string) {\n this.iframe = document.createElement('iframe');\n this.iframe.src = bridgeUrl;\n this.iframe.allow = `hid 'src'`;\n this.iframe.onload = async () => {\n // If the ledger live preference was set before the iframe is loaded,\n // set it after the iframe has loaded\n this.iframeLoaded = true;\n if (this.delayedPromise) {\n try {\n const result = await this.updateTransportMethod(\n this.delayedPromise.transportType,\n );\n this.delayedPromise.resolve(result);\n } catch (error) {\n this.delayedPromise.reject(error);\n } finally {\n delete this.delayedPromise;\n }\n }\n };\n document.head.appendChild(this.iframe);\n }\n\n #getOrigin(bridgeUrl: string) {\n const tmp = bridgeUrl.split('/');\n tmp.splice(-1, 1);\n return tmp.join('/');\n }\n\n #eventListener(\n bridgeUrl: string,\n eventMessage: {\n origin: string;\n data: IFrameMessageResponse<IFrameMessageAction>;\n },\n ) {\n if (eventMessage.origin !== this.#getOrigin(bridgeUrl)) {\n return;\n }\n\n if (eventMessage.data) {\n const messageCallback =\n this.messageCallbacks[eventMessage.data.messageId];\n if (messageCallback) {\n messageCallback(eventMessage.data);\n } else if (\n eventMessage.data.action === IFrameMessageAction.LedgerConnectionChange\n ) {\n this.isDeviceConnected = eventMessage.data.payload.connected;\n }\n }\n }\n\n #sendMessage<TAction extends IFrameMessageAction>(\n message: IFrameMessage<TAction>,\n callback: (response: IFrameMessageResponse<TAction>) => void,\n ) {\n this.currentMessageId += 1;\n\n const postMsg: IFramePostMessage<TAction> = {\n ...message,\n messageId: this.currentMessageId,\n target: LEDGER_IFRAME_ID,\n };\n\n this.messageCallbacks[this.currentMessageId] = callback as (\n response: IFrameMessageResponse<IFrameMessageAction>,\n ) => void;\n\n if (!this.iframeLoaded || !this.iframe || !this.iframe.contentWindow) {\n throw new Error('The iframe is not loaded yet');\n }\n\n this.iframe.contentWindow.postMessage(postMsg, '*');\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ledger-iframe-bridge.js","sourceRoot":"","sources":["../src/ledger-iframe-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n GetPublicKeyParams,\n GetPublicKeyResponse,\n LedgerBridge,\n LedgerSignMessageParams,\n LedgerSignMessageResponse,\n LedgerSignTransactionParams,\n LedgerSignTransactionResponse,\n LedgerSignTypedDataParams,\n LedgerSignTypedDataResponse,\n} from './ledger-bridge';\n\nconst LEDGER_IFRAME_ID = 'LEDGER-IFRAME';\n\nexport enum IFrameMessageAction {\n LedgerConnectionChange = 'ledger-connection-change',\n LedgerUnlock = 'ledger-unlock',\n LedgerMakeApp = 'ledger-make-app',\n LedgerUpdateTransport = 'ledger-update-transport',\n LedgerSignTransaction = 'ledger-sign-transaction',\n LedgerSignPersonalMessage = 'ledger-sign-personal-message',\n LedgerSignTypedData = 'ledger-sign-typed-data',\n}\n\ntype IFrameMessageResponseStub<\n SuccessResult extends Record<string, unknown>,\n FailureResult = Error,\n> = {\n messageId: number;\n} & (\n | { success: true; payload: SuccessResult }\n | { success: false; payload: { error: FailureResult } }\n);\n\ntype LedgerConnectionChangeActionResponse = {\n messageId: number;\n action: IFrameMessageAction.LedgerConnectionChange;\n payload: { connected: boolean };\n};\n\ntype LedgerMakeAppActionResponse = {\n messageId: number;\n action: IFrameMessageAction.LedgerMakeApp;\n} & ({ success: true } | { success: false; error?: unknown });\n\ntype LedgerUpdateTransportActionResponse = {\n messageId: number;\n action: IFrameMessageAction.LedgerUpdateTransport;\n success: boolean;\n};\n\ntype LedgerUnlockActionResponse = {\n action: IFrameMessageAction.LedgerUnlock;\n} & IFrameMessageResponseStub<GetPublicKeyResponse>;\n\ntype LedgerSignTransactionActionResponse = {\n action: IFrameMessageAction.LedgerSignTransaction;\n} & IFrameMessageResponseStub<LedgerSignTransactionResponse>;\n\ntype LedgerSignPersonalMessageActionResponse = {\n action: IFrameMessageAction.LedgerSignPersonalMessage;\n} & IFrameMessageResponseStub<LedgerSignMessageResponse>;\n\ntype LedgerSignTypedDataActionResponse = {\n action: IFrameMessageAction.LedgerSignTypedData;\n} & IFrameMessageResponseStub<LedgerSignTypedDataResponse>;\n\nexport type IFrameMessageResponse =\n | LedgerConnectionChangeActionResponse\n | LedgerMakeAppActionResponse\n | LedgerUpdateTransportActionResponse\n | LedgerUnlockActionResponse\n | LedgerSignTransactionActionResponse\n | LedgerSignPersonalMessageActionResponse\n | LedgerSignTypedDataActionResponse;\n\ntype IFrameMessage<TAction extends IFrameMessageAction> = {\n action: TAction;\n params?: Readonly<Record<string, unknown>>;\n};\n\ntype IFramePostMessage<TAction extends IFrameMessageAction> =\n IFrameMessage<TAction> & {\n messageId: number;\n target: typeof LEDGER_IFRAME_ID;\n };\n\nexport type LedgerIframeBridgeOptions = {\n bridgeUrl: string;\n};\n\nexport class LedgerIframeBridge\n implements LedgerBridge<LedgerIframeBridgeOptions>\n{\n iframe?: HTMLIFrameElement;\n\n iframeLoaded = false;\n\n #opts: LedgerIframeBridgeOptions;\n\n eventListener?: (eventMessage: {\n origin: string;\n data: IFrameMessageResponse;\n }) => void;\n\n isDeviceConnected = false;\n\n currentMessageId = 0;\n\n messageCallbacks: Record<number, (response: IFrameMessageResponse) => void> =\n {};\n\n delayedPromise?: {\n resolve: (value: boolean) => void;\n reject: (error: unknown) => void;\n transportType: string;\n };\n\n constructor(\n opts: LedgerIframeBridgeOptions = {\n bridgeUrl: 'https://metamask.github.io/eth-ledger-bridge-keyring',\n },\n ) {\n this.#validateConfiguration(opts);\n this.#opts = {\n bridgeUrl: opts?.bridgeUrl,\n };\n }\n\n async init() {\n this.#setupIframe(this.#opts.bridgeUrl);\n\n this.eventListener = this.#eventListener.bind(this, this.#opts.bridgeUrl);\n\n window.addEventListener('message', this.eventListener);\n }\n\n async destroy() {\n if (this.eventListener) {\n window.removeEventListener('message', this.eventListener);\n }\n }\n\n async getOptions(): Promise<LedgerIframeBridgeOptions> {\n return this.#opts;\n }\n\n async setOptions(opts: LedgerIframeBridgeOptions): Promise<void> {\n this.#validateConfiguration(opts);\n if (this.#opts?.bridgeUrl !== opts.bridgeUrl) {\n this.#opts.bridgeUrl = opts.bridgeUrl;\n await this.destroy();\n await this.init();\n }\n }\n\n async attemptMakeApp(): Promise<boolean> {\n return new Promise((resolve, reject) => {\n this.#sendMessage(\n {\n action: IFrameMessageAction.LedgerMakeApp,\n },\n (response) => {\n if ('success' in response && response.success) {\n resolve(true);\n } else if ('error' in response) {\n reject(response.error);\n } else {\n reject(new Error('Unknown error occurred'));\n }\n },\n );\n });\n }\n\n async updateTransportMethod(transportType: string): Promise<boolean> {\n return new Promise((resolve, reject) => {\n // If the iframe isn't loaded yet, let's store the desired transportType value and\n // optimistically return a successful promise\n if (!this.iframeLoaded) {\n this.delayedPromise = {\n resolve,\n reject,\n transportType,\n };\n return;\n }\n\n this.#sendMessage(\n {\n action: IFrameMessageAction.LedgerUpdateTransport,\n params: { transportType },\n },\n (response) => {\n if ('success' in response && response.success) {\n return resolve(true);\n }\n return reject(new Error('Ledger transport could not be updated'));\n },\n );\n });\n }\n\n async getPublicKey(\n params: GetPublicKeyParams,\n ): Promise<GetPublicKeyResponse> {\n return this.#deviceActionMessage(IFrameMessageAction.LedgerUnlock, params);\n }\n\n async deviceSignTransaction(\n params: LedgerSignTransactionParams,\n ): Promise<LedgerSignTransactionResponse> {\n return this.#deviceActionMessage(\n IFrameMessageAction.LedgerSignTransaction,\n params,\n );\n }\n\n async deviceSignMessage(\n params: LedgerSignMessageParams,\n ): Promise<LedgerSignMessageResponse> {\n return this.#deviceActionMessage(\n IFrameMessageAction.LedgerSignPersonalMessage,\n params,\n );\n }\n\n async deviceSignTypedData(\n params: LedgerSignTypedDataParams,\n ): Promise<LedgerSignTypedDataResponse> {\n return this.#deviceActionMessage(\n IFrameMessageAction.LedgerSignTypedData,\n params,\n );\n }\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerUnlock,\n params: GetPublicKeyParams,\n ): Promise<GetPublicKeyResponse>;\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerSignTransaction,\n params: LedgerSignTransactionParams,\n ): Promise<LedgerSignTransactionResponse>;\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerSignPersonalMessage,\n params: LedgerSignMessageParams,\n ): Promise<LedgerSignMessageResponse>;\n\n async #deviceActionMessage(\n action: IFrameMessageAction.LedgerSignTypedData,\n params: LedgerSignTypedDataParams,\n ): Promise<LedgerSignTypedDataResponse>;\n\n async #deviceActionMessage(\n ...[action, params]:\n | [IFrameMessageAction.LedgerUnlock, GetPublicKeyParams]\n | [IFrameMessageAction.LedgerSignTransaction, LedgerSignTransactionParams]\n | [IFrameMessageAction.LedgerSignPersonalMessage, LedgerSignMessageParams]\n | [IFrameMessageAction.LedgerSignTypedData, LedgerSignTypedDataParams]\n ) {\n return new Promise((resolve, reject) => {\n this.#sendMessage(\n {\n action,\n params,\n },\n (response) => {\n if ('payload' in response && response.payload) {\n if ('success' in response && response.success) {\n return resolve(response.payload);\n }\n if ('error' in response.payload) {\n return reject(response.payload.error);\n }\n }\n return reject(new Error('Unknown error occurred'));\n },\n );\n });\n }\n\n #setupIframe(bridgeUrl: string) {\n this.iframe = document.createElement('iframe');\n this.iframe.src = bridgeUrl;\n this.iframe.allow = `hid 'src'`;\n this.iframe.onload = async () => {\n // If the ledger live preference was set before the iframe is loaded,\n // set it after the iframe has loaded\n this.iframeLoaded = true;\n if (this.delayedPromise) {\n try {\n const result = await this.updateTransportMethod(\n this.delayedPromise.transportType,\n );\n this.delayedPromise.resolve(result);\n } catch (error) {\n this.delayedPromise.reject(error);\n } finally {\n delete this.delayedPromise;\n }\n }\n };\n document.head.appendChild(this.iframe);\n }\n\n #getOrigin(bridgeUrl: string) {\n const tmp = bridgeUrl.split('/');\n tmp.splice(-1, 1);\n return tmp.join('/');\n }\n\n #eventListener(\n bridgeUrl: string,\n eventMessage: {\n origin: string;\n data: IFrameMessageResponse;\n },\n ) {\n if (eventMessage.origin !== this.#getOrigin(bridgeUrl)) {\n return;\n }\n\n if (eventMessage.data) {\n const messageCallback =\n this.messageCallbacks[eventMessage.data.messageId];\n if (messageCallback) {\n messageCallback(eventMessage.data);\n } else if (\n eventMessage.data.action === IFrameMessageAction.LedgerConnectionChange\n ) {\n this.isDeviceConnected = eventMessage.data.payload.connected;\n }\n }\n }\n\n #sendMessage<TAction extends IFrameMessageAction>(\n message: IFrameMessage<TAction>,\n callback: (response: IFrameMessageResponse) => void,\n ) {\n this.currentMessageId += 1;\n\n const postMsg: IFramePostMessage<TAction> = {\n ...message,\n messageId: this.currentMessageId,\n target: LEDGER_IFRAME_ID,\n };\n\n this.messageCallbacks[this.currentMessageId] = callback;\n\n if (!this.iframeLoaded || !this.iframe || !this.iframe.contentWindow) {\n throw new Error('The iframe is not loaded yet');\n }\n\n this.iframe.contentWindow.postMessage(postMsg, '*');\n }\n\n #validateConfiguration(opts: LedgerIframeBridgeOptions): void {\n if (typeof opts.bridgeUrl !== 'string' || opts.bridgeUrl.length === 0) {\n throw new Error('bridgeURL is not a valid URL');\n }\n }\n}\n"]}
|
package/dist/ledger-keyring.d.ts
CHANGED
|
@@ -4,10 +4,10 @@ import type { MessageTypes, TypedMessage } from '@metamask/eth-sig-util';
|
|
|
4
4
|
import type OldEthJsTransaction from 'ethereumjs-tx';
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
6
|
import HDKey from 'hdkey';
|
|
7
|
-
import { LedgerBridge } from './ledger-bridge';
|
|
7
|
+
import { LedgerBridge, LedgerBridgeOptions } from './ledger-bridge';
|
|
8
8
|
declare enum NetworkApiUrls {
|
|
9
|
-
Ropsten = "
|
|
10
|
-
Kovan = "
|
|
9
|
+
Ropsten = "https://api-ropsten.etherscan.io",
|
|
10
|
+
Kovan = "https://api-kovan.etherscan.io",
|
|
11
11
|
Rinkeby = "https://api-rinkeby.etherscan.io",
|
|
12
12
|
Mainnet = "https://api.etherscan.io"
|
|
13
13
|
}
|
|
@@ -19,14 +19,15 @@ export declare type AccountDetails = {
|
|
|
19
19
|
export declare type LedgerBridgeKeyringOptions = {
|
|
20
20
|
hdPath: string;
|
|
21
21
|
accounts: readonly string[];
|
|
22
|
+
deviceId: string;
|
|
22
23
|
accountDetails: Readonly<Record<string, AccountDetails>>;
|
|
23
24
|
accountIndexes: Readonly<Record<string, number>>;
|
|
24
|
-
bridgeUrl: string;
|
|
25
25
|
implementFullBIP44: boolean;
|
|
26
26
|
};
|
|
27
27
|
export declare class LedgerKeyring extends EventEmitter {
|
|
28
28
|
#private;
|
|
29
29
|
static type: string;
|
|
30
|
+
deviceId: string;
|
|
30
31
|
readonly type: string;
|
|
31
32
|
page: number;
|
|
32
33
|
perPage: number;
|
|
@@ -38,27 +39,29 @@ export declare class LedgerKeyring extends EventEmitter {
|
|
|
38
39
|
paths: Record<string, number>;
|
|
39
40
|
network: NetworkApiUrls;
|
|
40
41
|
implementFullBIP44: boolean;
|
|
41
|
-
|
|
42
|
-
bridge: LedgerBridge;
|
|
42
|
+
bridge: LedgerBridge<LedgerBridgeOptions>;
|
|
43
43
|
constructor({ bridge }: {
|
|
44
|
-
bridge: LedgerBridge
|
|
44
|
+
bridge: LedgerBridge<LedgerBridgeOptions>;
|
|
45
45
|
});
|
|
46
46
|
init(): Promise<void>;
|
|
47
47
|
destroy(): Promise<void>;
|
|
48
48
|
serialize(): Promise<{
|
|
49
49
|
hdPath: string;
|
|
50
50
|
accounts: readonly string[];
|
|
51
|
+
deviceId: string;
|
|
51
52
|
accountDetails: Record<string, AccountDetails>;
|
|
52
|
-
bridgeUrl: string;
|
|
53
53
|
implementFullBIP44: boolean;
|
|
54
54
|
}>;
|
|
55
55
|
deserialize(opts?: Partial<LedgerBridgeKeyringOptions>): Promise<void>;
|
|
56
|
+
setDeviceId(deviceId: string): void;
|
|
57
|
+
getDeviceId(): string;
|
|
56
58
|
isUnlocked(): boolean;
|
|
57
59
|
isConnected(): boolean;
|
|
58
|
-
setAccountToUnlock(index: number
|
|
60
|
+
setAccountToUnlock(index: number): void;
|
|
59
61
|
setHdPath(hdPath: string): void;
|
|
60
62
|
unlock(hdPath?: string, updateHdk?: boolean): Promise<string>;
|
|
61
63
|
addAccounts(amount?: number): Promise<string[]>;
|
|
64
|
+
getName(): string;
|
|
62
65
|
getFirstPage(): Promise<{
|
|
63
66
|
address: string;
|
|
64
67
|
balance: number | null;
|