@reef-knot/ledger-connector 5.2.0-alpha.1 → 5.2.0-alpha.3
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/dist/hid/account.d.ts.map +1 -1
- package/dist/hid/account.js +6 -6
- package/dist/hid/connector.d.ts.map +1 -1
- package/dist/hid/connector.js +12 -9
- package/dist/hid/constants.d.ts +2 -0
- package/dist/hid/constants.d.ts.map +1 -1
- package/dist/hid/constants.js +3 -2
- package/dist/hid/helpers.d.ts +12 -0
- package/dist/hid/helpers.d.ts.map +1 -1
- package/dist/hid/helpers.js +39 -4
- package/dist/hid/index.js +1 -0
- package/dist/hid/provider.d.ts +4 -1
- package/dist/hid/provider.d.ts.map +1 -1
- package/dist/hid/provider.js +58 -10
- package/dist/iframe/connector.js +1 -3
- package/dist/iframe/helpers.js +1 -2
- package/dist/iframe/index.js +1 -0
- package/dist/iframe/provider.js +1 -3
- package/dist/index.js +1 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/hid/account.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAC;AAE5C,OAAO,EAOL,KAAK,OAAO,EACZ,KAAK,YAAY,EAGlB,MAAM,MAAM,CAAC;AAId,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KACnC,OAAO,CAAC,CAAC,CAAC,CAAC;AAiBhB,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/hid/account.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAC;AAE5C,OAAO,EAOL,KAAK,OAAO,EACZ,KAAK,YAAY,EAGlB,MAAM,MAAM,CAAC;AAId,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EACzB,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,KACnC,OAAO,CAAC,CAAC,CAAC,CAAC;AAiBhB,eAAO,MAAM,mBAAmB,GAC9B,SAAS,OAAO,EAChB,MAAM,MAAM,EACZ,YAAY,UAAU,KACrB,YAiFC,CAAC"}
|
package/dist/hid/account.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { bytesToHex, getTypesForEIP712Domain, hashStruct, serializeSignature, serializeTransaction, stringToHex } from "viem";
|
|
2
2
|
import { toAccount } from "viem/accounts";
|
|
3
|
-
|
|
4
3
|
//#region src/hid/account.ts
|
|
5
4
|
const RESOLUTION_CONFIG = {
|
|
6
5
|
erc20: true,
|
|
@@ -26,11 +25,12 @@ const createLedgerAccount = (address, path, withEthApp) => toAccount({
|
|
|
26
25
|
},
|
|
27
26
|
async signMessage({ message }) {
|
|
28
27
|
const messageHex = typeof message === "string" ? stringToHex(message) : typeof message.raw === "string" ? message.raw : bytesToHex(message.raw);
|
|
29
|
-
|
|
28
|
+
const signature = await withEthApp((eth) => eth.signPersonalMessage(path, messageHex.slice(2)));
|
|
29
|
+
return toSignatureHex(signature);
|
|
30
30
|
},
|
|
31
31
|
async signTypedData(parameters) {
|
|
32
32
|
const { domain = {}, types, primaryType, message } = parameters;
|
|
33
|
-
|
|
33
|
+
const signature = await withEthApp(async (eth) => {
|
|
34
34
|
try {
|
|
35
35
|
return await eth.signEIP712Message(path, parameters);
|
|
36
36
|
} catch (error) {
|
|
@@ -48,9 +48,9 @@ const createLedgerAccount = (address, path, withEthApp) => toAccount({
|
|
|
48
48
|
});
|
|
49
49
|
return eth.signEIP712HashedMessage(path, domainSeparator.slice(2), messageHash.slice(2));
|
|
50
50
|
}
|
|
51
|
-
})
|
|
51
|
+
});
|
|
52
|
+
return toSignatureHex(signature);
|
|
52
53
|
}
|
|
53
54
|
});
|
|
54
|
-
|
|
55
55
|
//#endregion
|
|
56
|
-
export { createLedgerAccount };
|
|
56
|
+
export { createLedgerAccount };
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/hid/connector.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAUrC,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,yGAiIA;yBAvIe,kBAAkB"}
|
package/dist/hid/connector.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { checkError, clearLedgerDerivationPath } from "./helpers.js";
|
|
1
|
+
import { checkError, clearLedgerAccount, clearLedgerChainId, clearLedgerDerivationPath, restoreLedgerChainId, saveLedgerChainId } from "./helpers.js";
|
|
2
2
|
import { ChainNotConfiguredError, ConnectorNotFoundError, createConnector } from "wagmi";
|
|
3
3
|
import { SwitchChainError } from "viem";
|
|
4
|
-
|
|
5
4
|
//#region src/hid/connector.ts
|
|
6
5
|
const idLedgerHid = "ledgerHID";
|
|
7
6
|
const name = "Ledger";
|
|
8
7
|
ledgerHIDConnector.type = "ledgerHID";
|
|
9
8
|
function ledgerHIDConnector({ rpc, defaultChain }) {
|
|
10
9
|
const providers = {};
|
|
11
|
-
let currentChainId;
|
|
10
|
+
let currentChainId = restoreLedgerChainId();
|
|
12
11
|
return createConnector(({ chains, emitter }) => ({
|
|
13
12
|
id: idLedgerHid,
|
|
14
13
|
name,
|
|
@@ -19,19 +18,21 @@ function ledgerHIDConnector({ rpc, defaultChain }) {
|
|
|
19
18
|
const { LedgerHQProvider } = await import("./provider.js");
|
|
20
19
|
providers[chain.id] = new LedgerHQProvider({
|
|
21
20
|
chain,
|
|
22
|
-
rpcUrl: rpc?.[chain.id]
|
|
21
|
+
rpcUrl: rpc?.[chain.id],
|
|
22
|
+
supportedChainIds: chains.map((x) => x.id)
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
return providers[chain.id];
|
|
26
26
|
},
|
|
27
27
|
async connect({ chainId, withCapabilities = false } = {}) {
|
|
28
28
|
try {
|
|
29
|
-
currentChainId = chainId;
|
|
30
|
-
const provider = await this.getProvider({ chainId });
|
|
29
|
+
currentChainId = chainId ?? currentChainId;
|
|
30
|
+
const provider = await this.getProvider({ chainId: currentChainId });
|
|
31
31
|
provider.on("disconnect", this.onDisconnect);
|
|
32
32
|
const account = await provider.enable();
|
|
33
33
|
const connectedChainId = await this.getChainId();
|
|
34
34
|
currentChainId = connectedChainId;
|
|
35
|
+
saveLedgerChainId(connectedChainId);
|
|
35
36
|
return {
|
|
36
37
|
accounts: withCapabilities ? [{
|
|
37
38
|
address: account,
|
|
@@ -40,7 +41,7 @@ function ledgerHIDConnector({ rpc, defaultChain }) {
|
|
|
40
41
|
chainId: connectedChainId
|
|
41
42
|
};
|
|
42
43
|
} catch (error) {
|
|
43
|
-
currentChainId =
|
|
44
|
+
currentChainId = restoreLedgerChainId();
|
|
44
45
|
return checkError(error);
|
|
45
46
|
}
|
|
46
47
|
},
|
|
@@ -51,6 +52,8 @@ function ledgerHIDConnector({ rpc, defaultChain }) {
|
|
|
51
52
|
});
|
|
52
53
|
currentChainId = void 0;
|
|
53
54
|
clearLedgerDerivationPath();
|
|
55
|
+
clearLedgerChainId();
|
|
56
|
+
clearLedgerAccount();
|
|
54
57
|
},
|
|
55
58
|
async getAccounts() {
|
|
56
59
|
return [await (await this.getProvider()).getAddress()];
|
|
@@ -72,6 +75,7 @@ function ledgerHIDConnector({ rpc, defaultChain }) {
|
|
|
72
75
|
const chain = chains.find((x) => x.id === chainId);
|
|
73
76
|
if (!chain) throw new SwitchChainError(new ChainNotConfiguredError());
|
|
74
77
|
currentChainId = chainId;
|
|
78
|
+
saveLedgerChainId(chainId);
|
|
75
79
|
emitter.emit("change", { chainId });
|
|
76
80
|
return chain;
|
|
77
81
|
},
|
|
@@ -82,6 +86,5 @@ function ledgerHIDConnector({ rpc, defaultChain }) {
|
|
|
82
86
|
onChainChanged() {}
|
|
83
87
|
}));
|
|
84
88
|
}
|
|
85
|
-
|
|
86
89
|
//#endregion
|
|
87
|
-
export { idLedgerHid, ledgerHIDConnector };
|
|
90
|
+
export { idLedgerHid, ledgerHIDConnector, name };
|
package/dist/hid/constants.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/hid/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,qCAAqC,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/hid/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,qCAAqC,CAAC;AACzE,eAAO,MAAM,eAAe,8BAA8B,CAAC;AAC3D,eAAO,MAAM,cAAc,6BAA6B,CAAC"}
|
package/dist/hid/constants.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/hid/constants.ts
|
|
2
2
|
const LS_KEY_DERIVATION_PATH = "reef-knot_ledger-derivation-path";
|
|
3
|
-
|
|
3
|
+
const LS_KEY_CHAIN_ID = "reef-knot_ledger-chain-id";
|
|
4
|
+
const LS_KEY_ACCOUNT = "reef-knot_ledger-account";
|
|
4
5
|
//#endregion
|
|
5
|
-
export { LS_KEY_DERIVATION_PATH };
|
|
6
|
+
export { LS_KEY_ACCOUNT, LS_KEY_CHAIN_ID, LS_KEY_DERIVATION_PATH };
|
package/dist/hid/helpers.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
import { type Address } from 'viem';
|
|
2
|
+
export type PersistedLedgerAccount = {
|
|
3
|
+
address: Address;
|
|
4
|
+
path: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const isLockedDeviceError: (error: unknown) => boolean;
|
|
1
7
|
export declare const checkError: (error: any) => never;
|
|
2
8
|
export declare const clearLedgerDerivationPath: () => void;
|
|
9
|
+
export declare const saveLedgerChainId: (chainId: number) => void;
|
|
10
|
+
export declare const restoreLedgerChainId: () => number | undefined;
|
|
11
|
+
export declare const clearLedgerChainId: () => void;
|
|
12
|
+
export declare const saveLedgerAccount: (account: PersistedLedgerAccount) => void;
|
|
13
|
+
export declare const restoreLedgerAccount: () => PersistedLedgerAccount | undefined;
|
|
14
|
+
export declare const clearLedgerAccount: () => void;
|
|
3
15
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/hid/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/hid/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAO/C,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,OACc,CAAC;AAEpE,eAAO,MAAM,UAAU,GAAI,OAAO,GAAG,KAAG,KAmBvC,CAAC;AAEF,eAAO,MAAM,yBAAyB,YAErC,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,SAAS,MAAM,SAGhD,CAAC;AAEF,eAAO,MAAM,oBAAoB,QAAO,MAAM,GAAG,SAMhD,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAG9B,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,SAAS,sBAAsB,SAGhE,CAAC;AAEF,eAAO,MAAM,oBAAoB,QAAO,sBAAsB,GAAG,SAchE,CAAC;AAEF,eAAO,MAAM,kBAAkB,YAG9B,CAAC"}
|
package/dist/hid/helpers.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { LS_KEY_DERIVATION_PATH } from "./constants.js";
|
|
2
|
-
|
|
1
|
+
import { LS_KEY_ACCOUNT, LS_KEY_CHAIN_ID, LS_KEY_DERIVATION_PATH } from "./constants.js";
|
|
2
|
+
import { isAddress } from "viem";
|
|
3
3
|
//#region src/hid/helpers.ts
|
|
4
|
+
const isLockedDeviceError = (error) => error?.name === "LockedDeviceError";
|
|
4
5
|
const checkError = (error) => {
|
|
5
6
|
if (error.statusText === "INS_NOT_SUPPORTED") error.message = "Device is not supported. Make sure the Ethereum app is open on the device.";
|
|
6
7
|
if (error.statusText === "UNKNOWN_ERROR") error.message = "Unknown error. Make sure the device is connected and the Ethereum app is open on the device.";
|
|
@@ -10,6 +11,40 @@ const checkError = (error) => {
|
|
|
10
11
|
const clearLedgerDerivationPath = () => {
|
|
11
12
|
window?.localStorage.removeItem(LS_KEY_DERIVATION_PATH);
|
|
12
13
|
};
|
|
13
|
-
|
|
14
|
+
const saveLedgerChainId = (chainId) => {
|
|
15
|
+
if (typeof window === "undefined") return;
|
|
16
|
+
window.localStorage.setItem(LS_KEY_CHAIN_ID, String(chainId));
|
|
17
|
+
};
|
|
18
|
+
const restoreLedgerChainId = () => {
|
|
19
|
+
if (typeof window === "undefined") return void 0;
|
|
20
|
+
const stored = window.localStorage.getItem(LS_KEY_CHAIN_ID);
|
|
21
|
+
if (!stored) return void 0;
|
|
22
|
+
const chainId = Number(stored);
|
|
23
|
+
return Number.isInteger(chainId) && chainId > 0 ? chainId : void 0;
|
|
24
|
+
};
|
|
25
|
+
const clearLedgerChainId = () => {
|
|
26
|
+
if (typeof window === "undefined") return;
|
|
27
|
+
window.localStorage.removeItem(LS_KEY_CHAIN_ID);
|
|
28
|
+
};
|
|
29
|
+
const saveLedgerAccount = (account) => {
|
|
30
|
+
if (typeof window === "undefined") return;
|
|
31
|
+
window.localStorage.setItem(LS_KEY_ACCOUNT, JSON.stringify(account));
|
|
32
|
+
};
|
|
33
|
+
const restoreLedgerAccount = () => {
|
|
34
|
+
if (typeof window === "undefined") return void 0;
|
|
35
|
+
const stored = window.localStorage.getItem(LS_KEY_ACCOUNT);
|
|
36
|
+
if (!stored) return void 0;
|
|
37
|
+
try {
|
|
38
|
+
const { address, path } = JSON.parse(stored);
|
|
39
|
+
if (address && isAddress(address) && typeof path === "string") return {
|
|
40
|
+
address,
|
|
41
|
+
path
|
|
42
|
+
};
|
|
43
|
+
} catch {}
|
|
44
|
+
};
|
|
45
|
+
const clearLedgerAccount = () => {
|
|
46
|
+
if (typeof window === "undefined") return;
|
|
47
|
+
window.localStorage.removeItem(LS_KEY_ACCOUNT);
|
|
48
|
+
};
|
|
14
49
|
//#endregion
|
|
15
|
-
export { checkError, clearLedgerDerivationPath };
|
|
50
|
+
export { checkError, clearLedgerAccount, clearLedgerChainId, clearLedgerDerivationPath, isLockedDeviceError, restoreLedgerAccount, restoreLedgerChainId, saveLedgerAccount, saveLedgerChainId };
|
package/dist/hid/index.js
CHANGED
package/dist/hid/provider.d.ts
CHANGED
|
@@ -17,9 +17,11 @@ export declare class LedgerHQProvider {
|
|
|
17
17
|
private publicClient?;
|
|
18
18
|
private walletClient?;
|
|
19
19
|
private listeners;
|
|
20
|
-
|
|
20
|
+
private readonly supportedChainIds;
|
|
21
|
+
constructor({ chain, rpcUrl, supportedChainIds, }: {
|
|
21
22
|
chain: Chain;
|
|
22
23
|
rpcUrl?: string;
|
|
24
|
+
supportedChainIds?: number[];
|
|
23
25
|
});
|
|
24
26
|
on(event: ProviderEvent, listener: Listener): void;
|
|
25
27
|
removeListener(event: ProviderEvent, listener: Listener): void;
|
|
@@ -31,6 +33,7 @@ export declare class LedgerHQProvider {
|
|
|
31
33
|
enable(): Promise<Address>;
|
|
32
34
|
resetAccount(): void;
|
|
33
35
|
getAccount(): Promise<LocalAccount>;
|
|
36
|
+
private readAddress;
|
|
34
37
|
getAddress(): Promise<Address>;
|
|
35
38
|
private getPublicClient;
|
|
36
39
|
private getWalletClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/hid/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAC;AAC5C,OAAO,KAAK,eAAe,MAAM,+BAA+B,CAAC;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/hid/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,sBAAsB,CAAC;AAC5C,OAAO,KAAK,eAAe,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAYL,KAAK,OAAO,EACZ,KAAK,KAAK,EAEV,KAAK,YAAY,EAIlB,MAAM,MAAM,CAAC;AA6Cd,KAAK,gBAAgB,GAAG;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB,CAAC;AAEF,KAAK,aAAa,GAAG,YAAY,CAAC;AAClC,KAAK,QAAQ,GAAG,MAAM,IAAI,CAAC;AAE3B,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAEf,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB,SAAS,CAAC,EAAE,OAAO,eAAe,CAAC;IAE1C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IAEjC,OAAO,CAAC,OAAO,CAAC,CAAe;IAE/B,OAAO,CAAC,WAAW,CAAC,CAAS;IAE7B,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC,OAAO,CAAC,YAAY,CAAC,CAAe;IAEpC,OAAO,CAAC,SAAS,CAAqD;IAItE,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAW;gBAEjC,EACV,KAAK,EACL,MAAM,EACN,iBAAiB,GAClB,EAAE;QACD,KAAK,EAAE,KAAK,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC9B;IAgBD,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ;IAI3C,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ;IAIvD,IAAI,CAAC,KAAK,EAAE,aAAa;IAMzB,IAAI,cAAc,WAQjB;IAEK,aAAa;IAQb,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC;IAc9C,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAoB3D,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAyBhC,YAAY;IAMN,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC;YAqC3B,WAAW;IAoBnB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAOpC,OAAO,CAAC,eAAe;YAQT,eAAe;YAUf,eAAe;IAuEvB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAW,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CA2E3E"}
|
package/dist/hid/provider.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { checkError } from "./helpers.js";
|
|
1
|
+
import "./constants.js";
|
|
2
|
+
import { checkError, clearLedgerAccount, isLockedDeviceError, restoreLedgerAccount, saveLedgerAccount } from "./helpers.js";
|
|
3
3
|
import { createLedgerAccount } from "./account.js";
|
|
4
|
-
import { createPublicClient, createWalletClient, getAddress, hexToBigInt, hexToNumber, http, isAddress, isAddressEqual, isHex, numberToHex } from "viem";
|
|
5
|
-
|
|
4
|
+
import { MethodNotSupportedRpcError, createPublicClient, createWalletClient, getAddress, hexToBigInt, hexToNumber, http, isAddress, isAddressEqual, isHex, numberToHex } from "viem";
|
|
6
5
|
//#region src/hid/provider.ts
|
|
7
6
|
const NOOP = () => {};
|
|
8
7
|
const DEFAULT_DERIVATION_PATH = "m/44'/60'/0'/0/0";
|
|
@@ -11,6 +10,15 @@ const TX_TYPES = {
|
|
|
11
10
|
"0x1": "eip2930",
|
|
12
11
|
"0x2": "eip1559"
|
|
13
12
|
};
|
|
13
|
+
const UNSUPPORTED_WALLET_METHODS = /* @__PURE__ */ new Set([
|
|
14
|
+
"eth_signTransaction",
|
|
15
|
+
"eth_signTypedData",
|
|
16
|
+
"eth_signTypedData_v1",
|
|
17
|
+
"eth_signTypedData_v3",
|
|
18
|
+
"eth_decrypt",
|
|
19
|
+
"eth_getEncryptionPublicKey",
|
|
20
|
+
"personal_ecRecover"
|
|
21
|
+
]);
|
|
14
22
|
let deviceSessionLock = Promise.resolve();
|
|
15
23
|
const withDeviceSession = (fn) => {
|
|
16
24
|
const result = deviceSessionLock.then(fn);
|
|
@@ -18,10 +26,11 @@ const withDeviceSession = (fn) => {
|
|
|
18
26
|
return result;
|
|
19
27
|
};
|
|
20
28
|
var LedgerHQProvider = class {
|
|
21
|
-
constructor({ chain, rpcUrl }) {
|
|
29
|
+
constructor({ chain, rpcUrl, supportedChainIds }) {
|
|
22
30
|
this.listeners = {};
|
|
23
31
|
this.chain = chain;
|
|
24
32
|
this.rpcUrl = rpcUrl;
|
|
33
|
+
this.supportedChainIds = supportedChainIds ?? [chain.id];
|
|
25
34
|
if (!rpcUrl) console.warn(`[reef-knot] No RPC URL configured for chain ${chain.id} (${chain.name}), falling back to its default public RPC endpoint`);
|
|
26
35
|
}
|
|
27
36
|
on(event, listener) {
|
|
@@ -35,7 +44,7 @@ var LedgerHQProvider = class {
|
|
|
35
44
|
this.listeners[event]?.forEach((listener) => listener());
|
|
36
45
|
}
|
|
37
46
|
get derivationPath() {
|
|
38
|
-
if (typeof window !== "undefined") return window.localStorage.getItem(
|
|
47
|
+
if (typeof window !== "undefined") return window.localStorage.getItem("reef-knot_ledger-derivation-path") || DEFAULT_DERIVATION_PATH;
|
|
39
48
|
return DEFAULT_DERIVATION_PATH;
|
|
40
49
|
}
|
|
41
50
|
async loadTransport() {
|
|
@@ -94,13 +103,48 @@ var LedgerHQProvider = class {
|
|
|
94
103
|
async getAccount() {
|
|
95
104
|
const path = this.derivationPath;
|
|
96
105
|
if (!this.account || this.accountPath !== path) {
|
|
97
|
-
const { address } = await this.
|
|
98
|
-
|
|
106
|
+
const { address, verifiedByDevice } = await this.readAddress(path);
|
|
107
|
+
let verified = verifiedByDevice;
|
|
108
|
+
const withVerifyingEthApp = (cb) => this.withEthApp(async (eth) => {
|
|
109
|
+
if (!verified) {
|
|
110
|
+
const actual = await eth.getAddress(path);
|
|
111
|
+
if (!isAddressEqual(getAddress(actual.address), address)) {
|
|
112
|
+
clearLedgerAccount();
|
|
113
|
+
this.resetAccount();
|
|
114
|
+
this.emit("disconnect");
|
|
115
|
+
throw new Error("The connected account does not match the device. Please reconnect.");
|
|
116
|
+
}
|
|
117
|
+
verified = true;
|
|
118
|
+
}
|
|
119
|
+
return cb(eth);
|
|
120
|
+
});
|
|
121
|
+
this.account = createLedgerAccount(address, path, withVerifyingEthApp);
|
|
99
122
|
this.accountPath = path;
|
|
100
123
|
this.walletClient = void 0;
|
|
101
124
|
}
|
|
102
125
|
return this.account;
|
|
103
126
|
}
|
|
127
|
+
async readAddress(path) {
|
|
128
|
+
try {
|
|
129
|
+
const { address } = await this.withEthApp((eth) => eth.getAddress(path));
|
|
130
|
+
const checksummed = getAddress(address);
|
|
131
|
+
saveLedgerAccount({
|
|
132
|
+
address: checksummed,
|
|
133
|
+
path
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
address: checksummed,
|
|
137
|
+
verifiedByDevice: true
|
|
138
|
+
};
|
|
139
|
+
} catch (error) {
|
|
140
|
+
const persisted = restoreLedgerAccount();
|
|
141
|
+
if (isLockedDeviceError(error) && persisted?.path === path) return {
|
|
142
|
+
address: persisted.address,
|
|
143
|
+
verifiedByDevice: false
|
|
144
|
+
};
|
|
145
|
+
return checkError(error);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
104
148
|
async getAddress() {
|
|
105
149
|
const { address } = await this.getAccount();
|
|
106
150
|
return address;
|
|
@@ -180,7 +224,12 @@ var LedgerHQProvider = class {
|
|
|
180
224
|
case "eth_signTypedData_v4":
|
|
181
225
|
if (typeof params[1] !== "string") throw new Error("eth_signTypedData_v4 arg 1 is not a string");
|
|
182
226
|
return (await this.getAccount()).signTypedData(JSON.parse(params[1]));
|
|
227
|
+
case "wallet_getCapabilities": {
|
|
228
|
+
const chainIds = ((Array.isArray(params[1]) ? params[1].filter((value) => isHex(value)).map((value) => hexToNumber(value)) : void 0) ?? this.supportedChainIds).filter((chainId) => this.supportedChainIds.includes(chainId));
|
|
229
|
+
return Object.fromEntries(chainIds.map((chainId) => [numberToHex(chainId), {}]));
|
|
230
|
+
}
|
|
183
231
|
default: {
|
|
232
|
+
if (method.startsWith("wallet_") || UNSUPPORTED_WALLET_METHODS.has(method)) throw new MethodNotSupportedRpcError(/* @__PURE__ */ new Error(`The method ${method} is not supported`), { method });
|
|
184
233
|
const rpcRequest = this.getPublicClient().request;
|
|
185
234
|
return rpcRequest({
|
|
186
235
|
method,
|
|
@@ -190,6 +239,5 @@ var LedgerHQProvider = class {
|
|
|
190
239
|
}
|
|
191
240
|
}
|
|
192
241
|
};
|
|
193
|
-
|
|
194
242
|
//#endregion
|
|
195
|
-
export { LedgerHQProvider };
|
|
243
|
+
export { LedgerHQProvider };
|
package/dist/iframe/connector.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { SwitchChainNotSupportedError, createConnector } from "wagmi";
|
|
2
2
|
import { ResourceUnavailableRpcError, UserRejectedRequestError, getAddress, numberToHex } from "viem";
|
|
3
|
-
|
|
4
3
|
//#region src/iframe/connector.ts
|
|
5
4
|
const idLedgerLive = "ledgerLive";
|
|
6
5
|
const name = "Ledger Live";
|
|
@@ -101,6 +100,5 @@ function ledgerLiveConnector({ options, defaultChain }) {
|
|
|
101
100
|
}
|
|
102
101
|
}));
|
|
103
102
|
}
|
|
104
|
-
|
|
105
103
|
//#endregion
|
|
106
|
-
export { idLedgerLive, ledgerLiveConnector, name };
|
|
104
|
+
export { idLedgerLive, ledgerLiveConnector, name };
|
package/dist/iframe/helpers.js
CHANGED
package/dist/iframe/index.js
CHANGED
package/dist/iframe/provider.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { IFrameEthereumProvider } from "@ledgerhq/iframe-provider";
|
|
2
|
-
|
|
3
2
|
//#region src/iframe/provider.ts
|
|
4
3
|
var LedgerIFrameProvider = class extends IFrameEthereumProvider {
|
|
5
4
|
request({ method, params }) {
|
|
6
5
|
return this.send(method, params);
|
|
7
6
|
}
|
|
8
7
|
};
|
|
9
|
-
|
|
10
8
|
//#endregion
|
|
11
|
-
export { LedgerIFrameProvider };
|
|
9
|
+
export { LedgerIFrameProvider };
|
package/dist/index.js
CHANGED
|
@@ -4,5 +4,4 @@ import "./iframe/index.js";
|
|
|
4
4
|
import { LS_KEY_DERIVATION_PATH } from "./hid/constants.js";
|
|
5
5
|
import { idLedgerHid, ledgerHIDConnector } from "./hid/connector.js";
|
|
6
6
|
import "./hid/index.js";
|
|
7
|
-
|
|
8
|
-
export { LS_KEY_DERIVATION_PATH, idLedgerHid, idLedgerLive, isIframe, isLedgerLive, ledgerHIDConnector, ledgerLiveConnector, name };
|
|
7
|
+
export { LS_KEY_DERIVATION_PATH, idLedgerHid, idLedgerLive, isIframe, isLedgerLive, ledgerHIDConnector, ledgerLiveConnector, name };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reef-knot/ledger-connector",
|
|
3
|
-
"version": "5.2.0-alpha.
|
|
3
|
+
"version": "5.2.0-alpha.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typecheck": "tsc --noEmit"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@types/w3c-web-hid": "^1.0.
|
|
41
|
+
"@types/w3c-web-hid": "^1.0.7",
|
|
42
42
|
"build-config": "*",
|
|
43
43
|
"eslint-config-custom": "*",
|
|
44
44
|
"viem": ">=2.50",
|