@reef-knot/ledger-connector 4.5.0 → 5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/hid/connector.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,eAAO,MAAM,WAAW,cAAc,CAAC;AACvC,eAAO,MAAM,IAAI,WAAW,CAAC;AAG7B,wBAAgB,kBAAkB,CAAC,EACjC,GAAG,EACH,YAAY,GACb,EAAE;IACD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,YAAY,EAAE,KAAK,CAAC;CACrB,yGAwGA;yBA9Ge,kBAAkB"}
1
+ {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/hid/connector.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAGrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,eAAO,MAAM,WAAW,cAAc,CAAC;AACvC,eAAO,MAAM,IAAI,WAAW,CAAC;AAG7B,wBAAgB,kBAAkB,CAAC,EACjC,GAAG,EACH,YAAY,GACb,EAAE;IACD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,YAAY,EAAE,KAAK,CAAC;CACrB,yGAiHA;yBAvHe,kBAAkB"}
@@ -1,139 +1,88 @@
1
- import { __awaiter } from '../_virtual/_tslib.js';
2
- import { createConnector, ChainNotConfiguredError, ConnectorNotFoundError } from 'wagmi';
3
- import { checkError, clearLedgerDerivationPath } from './helpers.js';
1
+ import { checkError, clearLedgerDerivationPath } from "./helpers.js";
2
+ import { ChainNotConfiguredError, ConnectorNotFoundError, createConnector } from "wagmi";
4
3
 
5
- const idLedgerHid = 'ledgerHID';
6
- const name = 'Ledger';
7
- ledgerHIDConnector.type = 'ledgerHID';
8
- function ledgerHIDConnector({
9
- rpc,
10
- defaultChain
11
- }) {
12
- const providers = {};
13
- return createConnector(({
14
- chains,
15
- emitter
16
- }) => ({
17
- id: idLedgerHid,
18
- name,
19
- type: ledgerHIDConnector.type,
20
- getProvider() {
21
- return __awaiter(this, arguments, void 0, function* ({
22
- chainId
23
- } = {}) {
24
- var _a;
25
- const chain = (_a = chains.find(x => x.id === chainId)) !== null && _a !== void 0 ? _a : defaultChain;
26
- if (!providers[chain.id]) {
27
- const {
28
- LedgerHQProvider
29
- } = yield import('./provider.js');
30
- providers[chain.id] = new LedgerHQProvider({
31
- url: rpc === null || rpc === void 0 ? void 0 : rpc[chain.id]
32
- }, chain.id);
33
- }
34
- return providers[chain.id];
35
- });
36
- },
37
- connect() {
38
- return __awaiter(this, void 0, void 0, function* () {
39
- try {
40
- const provider = yield this.getProvider();
41
- provider.on('disconnect', this.onDisconnect);
42
- const account = yield provider.enable();
43
- const chainId = yield this.getChainId();
44
- return {
45
- accounts: [account],
46
- chainId
47
- };
48
- } catch (error) {
49
- return checkError(error);
50
- }
51
- });
52
- },
53
- disconnect() {
54
- return __awaiter(this, void 0, void 0, function* () {
55
- // Handles programmatic disconnect.
56
- const provider = yield this.getProvider();
57
- provider.removeListener('disconnect', this.onDisconnect);
58
- clearLedgerDerivationPath();
59
- });
60
- },
61
- getAccounts() {
62
- return __awaiter(this, void 0, void 0, function* () {
63
- const provider = yield this.getProvider();
64
- const address = yield provider.getAddress();
65
- return [address];
66
- });
67
- },
68
- getChainId() {
69
- return __awaiter(this, void 0, void 0, function* () {
70
- const provider = yield this.getProvider();
71
- const {
72
- chainId
73
- } = yield provider.getNetwork();
74
- if (chainId) return chainId;
75
- throw new ChainNotConfiguredError();
76
- });
77
- },
78
- isAuthorized() {
79
- return __awaiter(this, void 0, void 0, function* () {
80
- try {
81
- const provider = yield this.getProvider();
82
- if (!provider) throw new ConnectorNotFoundError();
83
- const [account] = yield this.getAccounts();
84
- return !!account;
85
- } catch (e) {
86
- // The errors caught here are generally expected in most use cases.
87
- // However, unexpected errors may still occur, so they should at least be logged to the console.
88
- console.error(e);
89
- return false;
90
- }
91
- });
92
- },
93
- switchChain(_a) {
94
- return __awaiter(this, arguments, void 0, function* ({
95
- chainId
96
- }) {
97
- var _b;
98
- const id = chainId.toString(16);
99
- emitter.emit('change', {
100
- chainId: Number(chainId)
101
- });
102
- return Promise.resolve((_b = chains.find(x => x.id === chainId)) !== null && _b !== void 0 ? _b : {
103
- id: chainId,
104
- name: `Chain ${id}`,
105
- network: `${id}`,
106
- nativeCurrency: {
107
- decimals: 18,
108
- name: 'Ether',
109
- symbol: 'ETH'
110
- },
111
- rpcUrls: {
112
- default: {
113
- http: ['']
114
- },
115
- public: {
116
- http: ['']
117
- }
118
- }
119
- });
120
- });
121
- },
122
- onDisconnect() {
123
- // Is called when HID API emits 'disconnect' event for some reason.
124
- // For example, the device was manually unplugged.
125
- // It is common to emit 'disconnect' from connector in this case.
126
- emitter.emit('disconnect');
127
- },
128
- onAccountsChanged() {
129
- // NOOP
130
- // HID Ledger cannot change account by itself
131
- },
132
- onChainChanged() {
133
- // NOOP
134
- // HID Ledger cannot change chain by itself
135
- }
136
- }));
4
+ //#region src/hid/connector.ts
5
+ const idLedgerHid = "ledgerHID";
6
+ const name = "Ledger";
7
+ ledgerHIDConnector.type = "ledgerHID";
8
+ function ledgerHIDConnector({ rpc, defaultChain }) {
9
+ const providers = {};
10
+ return createConnector(({ chains, emitter }) => ({
11
+ id: idLedgerHid,
12
+ name,
13
+ type: ledgerHIDConnector.type,
14
+ async getProvider({ chainId } = {}) {
15
+ const chain = chains.find((x) => x.id === chainId) ?? defaultChain;
16
+ if (!providers[chain.id]) {
17
+ const { LedgerHQProvider } = await import("./provider.js");
18
+ providers[chain.id] = new LedgerHQProvider({ url: rpc?.[chain.id] }, chain.id);
19
+ }
20
+ return providers[chain.id];
21
+ },
22
+ async connect({ withCapabilities = false } = {}) {
23
+ try {
24
+ const provider = await this.getProvider();
25
+ provider.on("disconnect", this.onDisconnect);
26
+ const account = await provider.enable();
27
+ const chainId = await this.getChainId();
28
+ return {
29
+ accounts: withCapabilities ? [{
30
+ address: account,
31
+ capabilities: {}
32
+ }] : [account],
33
+ chainId
34
+ };
35
+ } catch (error) {
36
+ return checkError(error);
37
+ }
38
+ },
39
+ async disconnect() {
40
+ (await this.getProvider()).removeListener("disconnect", this.onDisconnect);
41
+ clearLedgerDerivationPath();
42
+ },
43
+ async getAccounts() {
44
+ return [await (await this.getProvider()).getAddress()];
45
+ },
46
+ async getChainId() {
47
+ const { chainId } = await (await this.getProvider()).getNetwork();
48
+ if (chainId) return chainId;
49
+ throw new ChainNotConfiguredError();
50
+ },
51
+ async isAuthorized() {
52
+ try {
53
+ if (!await this.getProvider()) throw new ConnectorNotFoundError();
54
+ const [account] = await this.getAccounts();
55
+ return !!account;
56
+ } catch (e) {
57
+ console.error(e);
58
+ return false;
59
+ }
60
+ },
61
+ async switchChain({ chainId }) {
62
+ const id = chainId.toString(16);
63
+ emitter.emit("change", { chainId: Number(chainId) });
64
+ return Promise.resolve(chains.find((x) => x.id === chainId) ?? {
65
+ id: chainId,
66
+ name: `Chain ${id}`,
67
+ network: `${id}`,
68
+ nativeCurrency: {
69
+ decimals: 18,
70
+ name: "Ether",
71
+ symbol: "ETH"
72
+ },
73
+ rpcUrls: {
74
+ default: { http: [""] },
75
+ public: { http: [""] }
76
+ }
77
+ });
78
+ },
79
+ onDisconnect() {
80
+ emitter.emit("disconnect");
81
+ },
82
+ onAccountsChanged() {},
83
+ onChainChanged() {}
84
+ }));
137
85
  }
138
86
 
139
- export { idLedgerHid, ledgerHIDConnector, name };
87
+ //#endregion
88
+ export { idLedgerHid, ledgerHIDConnector };
@@ -1,3 +1,5 @@
1
- const LS_KEY_DERIVATION_PATH = 'reef-knot_ledger-derivation-path';
1
+ //#region src/hid/constants.ts
2
+ const LS_KEY_DERIVATION_PATH = "reef-knot_ledger-derivation-path";
2
3
 
3
- export { LS_KEY_DERIVATION_PATH };
4
+ //#endregion
5
+ export { LS_KEY_DERIVATION_PATH };
@@ -1,67 +1,46 @@
1
- import { __awaiter } from '../_virtual/_tslib.js';
2
- import { BigNumber } from '@ethersproject/bignumber';
3
- import { resolveProperties } from '@ethersproject/properties';
4
- import { LS_KEY_DERIVATION_PATH } from './constants.js';
1
+ import { LS_KEY_DERIVATION_PATH } from "./constants.js";
2
+ import { BigNumber } from "@ethersproject/bignumber";
3
+ import { resolveProperties } from "@ethersproject/properties";
5
4
 
6
- const hasEIP1559 = tx => {
7
- return tx.type === 2 || tx.maxFeePerGas != null || tx.maxPriorityFeePerGas != null;
5
+ //#region src/hid/helpers.ts
6
+ const hasEIP1559 = (tx) => {
7
+ return tx.type === 2 || tx.maxFeePerGas != null || tx.maxPriorityFeePerGas != null;
8
8
  };
9
- const toNumber = value => {
10
- return value == null ? undefined : BigNumber.from(value).toNumber();
9
+ const toNumber = (value) => {
10
+ return value == null ? void 0 : BigNumber.from(value).toNumber();
11
11
  };
12
- const convertToUnsigned = tx => __awaiter(void 0, void 0, void 0, function* () {
13
- const resolvedTx = yield resolveProperties(tx);
14
- const {
15
- chainId,
16
- data,
17
- gasLimit,
18
- gas,
19
- gasPrice,
20
- value,
21
- to
22
- } = resolvedTx;
23
- const nonce = toNumber(resolvedTx.nonce);
24
- const type = toNumber(resolvedTx.type);
25
- // Allowed transaction keys for Legacy and EIP-155 Transactions
26
- const baseTx = {
27
- gasLimit: gasLimit || gas,
28
- type: type !== null && type !== void 0 ? type : 2,
29
- chainId,
30
- gasPrice,
31
- nonce,
32
- value,
33
- data,
34
- to
35
- };
36
- // EIP-2930
37
- if (tx.accessList != null) {
38
- baseTx.accessList = tx.accessList;
39
- }
40
- // EIP-1559
41
- if (hasEIP1559(tx)) {
42
- baseTx.maxFeePerGas = tx.maxFeePerGas;
43
- baseTx.maxPriorityFeePerGas = tx.maxPriorityFeePerGas;
44
- baseTx.type = 2;
45
- }
46
- return baseTx;
47
- });
48
- const checkError = error => {
49
- if (error.statusText === 'INS_NOT_SUPPORTED') {
50
- // eslint-disable-next-line no-param-reassign
51
- error.message = 'Device is not supported. Make sure the Ethereum app is open on the device.';
52
- }
53
- if (error.statusText === 'UNKNOWN_ERROR') {
54
- // eslint-disable-next-line no-param-reassign
55
- error.message = 'Unknown error. Make sure the device is connected and the Ethereum app is open on the device.';
56
- }
57
- if (error.statusText === 'CONDITIONS_OF_USE_NOT_SATISFIED') {
58
- // eslint-disable-next-line no-param-reassign
59
- error.message = 'User rejected the request';
60
- }
61
- throw error;
12
+ const convertToUnsigned = async (tx) => {
13
+ const resolvedTx = await resolveProperties(tx);
14
+ const { chainId, data, gasLimit, gas, gasPrice, value, to } = resolvedTx;
15
+ const nonce = toNumber(resolvedTx.nonce);
16
+ const type = toNumber(resolvedTx.type);
17
+ const baseTx = {
18
+ gasLimit: gasLimit || gas,
19
+ type: type ?? 2,
20
+ chainId,
21
+ gasPrice,
22
+ nonce,
23
+ value,
24
+ data,
25
+ to
26
+ };
27
+ if (tx.accessList != null) baseTx.accessList = tx.accessList;
28
+ if (hasEIP1559(tx)) {
29
+ baseTx.maxFeePerGas = tx.maxFeePerGas;
30
+ baseTx.maxPriorityFeePerGas = tx.maxPriorityFeePerGas;
31
+ baseTx.type = 2;
32
+ }
33
+ return baseTx;
34
+ };
35
+ const checkError = (error) => {
36
+ if (error.statusText === "INS_NOT_SUPPORTED") error.message = "Device is not supported. Make sure the Ethereum app is open on the device.";
37
+ if (error.statusText === "UNKNOWN_ERROR") error.message = "Unknown error. Make sure the device is connected and the Ethereum app is open on the device.";
38
+ if (error.statusText === "CONDITIONS_OF_USE_NOT_SATISFIED") error.message = "User rejected the request";
39
+ throw error;
62
40
  };
63
41
  const clearLedgerDerivationPath = () => {
64
- window === null || window === void 0 ? void 0 : window.localStorage.removeItem(LS_KEY_DERIVATION_PATH);
42
+ window?.localStorage.removeItem(LS_KEY_DERIVATION_PATH);
65
43
  };
66
44
 
67
- export { checkError, clearLedgerDerivationPath, convertToUnsigned, hasEIP1559, toNumber };
45
+ //#endregion
46
+ export { checkError, clearLedgerDerivationPath, convertToUnsigned, toNumber };
@@ -0,0 +1,2 @@
1
+ import { LS_KEY_DERIVATION_PATH } from "./constants.js";
2
+ import { idLedgerHid, ledgerHIDConnector } from "./connector.js";
@@ -1,122 +1,97 @@
1
- import { __awaiter } from '../_virtual/_tslib.js';
2
- import invariant from 'tiny-invariant';
3
- import { JsonRpcBatchProvider } from '@ethersproject/providers';
4
- import { arrayify } from '@ethersproject/bytes';
5
- import { LedgerHQSigner } from './signer.js';
6
- import { checkError, convertToUnsigned } from './helpers.js';
1
+ import { checkError, convertToUnsigned } from "./helpers.js";
2
+ import { LedgerHQSigner } from "./signer.js";
3
+ import { arrayify } from "@ethersproject/bytes";
4
+ import { JsonRpcBatchProvider } from "@ethersproject/providers";
5
+ import invariant from "tiny-invariant";
7
6
 
8
- class LedgerHQProvider extends JsonRpcBatchProvider {
9
- constructor(...args) {
10
- super(...args);
11
- this.signer = this.getSigner();
12
- }
13
- loadTransport() {
14
- return __awaiter(this, void 0, void 0, function* () {
15
- if (!this.transport) {
16
- const {
17
- default: TransportWebHID
18
- } = yield import('@ledgerhq/hw-transport-webhid');
19
- this.transport = TransportWebHID;
20
- }
21
- });
22
- }
23
- getSigner() {
24
- return new LedgerHQSigner(this);
25
- }
26
- listAccounts() {
27
- throw new Error('method is not implemented');
28
- }
29
- detectNetwork() {
30
- return Promise.resolve(this._network);
31
- }
32
- getTransport() {
33
- return __awaiter(this, void 0, void 0, function* () {
34
- var _a;
35
- yield this.loadTransport();
36
- try {
37
- const transportInstance = yield (_a = this.transport) === null || _a === void 0 ? void 0 : _a.create();
38
- this.device = transportInstance.device;
39
- return transportInstance;
40
- } catch (error) {
41
- return checkError(error);
42
- }
43
- });
44
- }
45
- enable() {
46
- return __awaiter(this, void 0, void 0, function* () {
47
- try {
48
- yield this.loadTransport();
49
- const {
50
- hid
51
- } = window.navigator;
52
- const onDisconnect = event => {
53
- if (this.device === event.device) {
54
- hid.removeEventListener('disconnect', onDisconnect);
55
- this.emit('disconnect');
56
- }
57
- };
58
- hid.addEventListener('disconnect', onDisconnect);
59
- if (!this.signer) {
60
- this.signer = this.getSigner();
61
- }
62
- return yield this.getAddress();
63
- } catch (error) {
64
- return checkError(error);
65
- }
66
- });
67
- }
68
- getAddress() {
69
- return __awaiter(this, void 0, void 0, function* () {
70
- invariant(this.signer, 'Signer is not defined');
71
- return yield this.signer.getAddress();
72
- });
73
- }
74
- request(_a) {
75
- return __awaiter(this, arguments, void 0, function* ({
76
- method,
77
- params
78
- }) {
79
- invariant(this.signer, 'Signer is not defined');
80
- switch (method) {
81
- case 'eth_sendTransaction':
82
- {
83
- const sourceTx = params[0];
84
- const unsignedTx = yield convertToUnsigned(sourceTx);
85
- const signedTx = yield this.signer.signTransaction(unsignedTx);
86
- return this.send('eth_sendRawTransaction', [signedTx]);
87
- }
88
- case 'eth_accounts':
89
- return [yield this.getAddress()];
90
- case 'eth_signTypedData_v4':
91
- {
92
- if (typeof params[1] !== 'string') throw new Error('eth_signTypedData_v4 arg 1 is not a string');
93
- const payload = JSON.parse(params[1]);
94
- return yield this.signer.__signEIP712Message({
95
- domain: payload.domain,
96
- types: payload.types,
97
- primaryType: payload.primaryType,
98
- message: payload.message
99
- });
100
- }
101
- case 'personal_sign':
102
- {
103
- const messageHex = params[0];
104
- if (typeof messageHex !== 'string') throw new Error('personal_sign message must be a string');
105
- const messageBytes = arrayify(messageHex);
106
- return yield this.signer.signMessage(messageBytes);
107
- }
108
- case 'eth_sign':
109
- {
110
- const messageHex = params[1];
111
- if (typeof messageHex !== 'string') throw new Error('eth_sign message must be a string');
112
- const messageBytes = arrayify(messageHex);
113
- return yield this.signer.signMessage(messageBytes);
114
- }
115
- default:
116
- return this.send(method, params);
117
- }
118
- });
119
- }
120
- }
7
+ //#region src/hid/provider.ts
8
+ var LedgerHQProvider = class extends JsonRpcBatchProvider {
9
+ constructor(...args) {
10
+ super(...args);
11
+ this.signer = this.getSigner();
12
+ }
13
+ async loadTransport() {
14
+ if (!this.transport) {
15
+ const { default: TransportWebHID } = await import("@ledgerhq/hw-transport-webhid");
16
+ this.transport = TransportWebHID;
17
+ }
18
+ }
19
+ getSigner() {
20
+ return new LedgerHQSigner(this);
21
+ }
22
+ listAccounts() {
23
+ throw new Error("method is not implemented");
24
+ }
25
+ detectNetwork() {
26
+ return Promise.resolve(this._network);
27
+ }
28
+ async getTransport() {
29
+ await this.loadTransport();
30
+ try {
31
+ const transportInstance = await this.transport?.create();
32
+ this.device = transportInstance.device;
33
+ return transportInstance;
34
+ } catch (error) {
35
+ return checkError(error);
36
+ }
37
+ }
38
+ async enable() {
39
+ try {
40
+ await this.loadTransport();
41
+ const { hid } = window.navigator;
42
+ const onDisconnect = (event) => {
43
+ if (this.device === event.device) {
44
+ hid.removeEventListener("disconnect", onDisconnect);
45
+ this.emit("disconnect");
46
+ }
47
+ };
48
+ hid.addEventListener("disconnect", onDisconnect);
49
+ if (!this.signer) this.signer = this.getSigner();
50
+ return await this.getAddress();
51
+ } catch (error) {
52
+ return checkError(error);
53
+ }
54
+ }
55
+ async getAddress() {
56
+ invariant(this.signer, "Signer is not defined");
57
+ return await this.signer.getAddress();
58
+ }
59
+ async request({ method, params }) {
60
+ invariant(this.signer, "Signer is not defined");
61
+ switch (method) {
62
+ case "eth_sendTransaction": {
63
+ const sourceTx = params[0];
64
+ const unsignedTx = await convertToUnsigned(sourceTx);
65
+ const signedTx = await this.signer.signTransaction(unsignedTx);
66
+ return this.send("eth_sendRawTransaction", [signedTx]);
67
+ }
68
+ case "eth_accounts": return [await this.getAddress()];
69
+ case "eth_signTypedData_v4": {
70
+ if (typeof params[1] !== "string") throw new Error("eth_signTypedData_v4 arg 1 is not a string");
71
+ const payload = JSON.parse(params[1]);
72
+ return await this.signer.__signEIP712Message({
73
+ domain: payload.domain,
74
+ types: payload.types,
75
+ primaryType: payload.primaryType,
76
+ message: payload.message
77
+ });
78
+ }
79
+ case "personal_sign": {
80
+ const messageHex = params[0];
81
+ if (typeof messageHex !== "string") throw new Error("personal_sign message must be a string");
82
+ const messageBytes = arrayify(messageHex);
83
+ return await this.signer.signMessage(messageBytes);
84
+ }
85
+ case "eth_sign": {
86
+ const messageHex = params[1];
87
+ if (typeof messageHex !== "string") throw new Error("eth_sign message must be a string");
88
+ const messageBytes = arrayify(messageHex);
89
+ return await this.signer.signMessage(messageBytes);
90
+ }
91
+ default: return this.send(method, params);
92
+ }
93
+ }
94
+ };
121
95
 
122
- export { LedgerHQProvider };
96
+ //#endregion
97
+ export { LedgerHQProvider };