@reef-knot/ledger-connector 5.2.0 → 5.3.0-alpha.1

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.
Files changed (55) hide show
  1. package/dist/hid/account.d.ts +6 -9
  2. package/dist/hid/account.d.ts.map +1 -1
  3. package/dist/hid/account.js +5 -2
  4. package/dist/hid/account.js.map +1 -0
  5. package/dist/hid/connector.d.ts +9 -8
  6. package/dist/hid/connector.d.ts.map +1 -1
  7. package/dist/hid/connector.js +2 -0
  8. package/dist/hid/connector.js.map +1 -0
  9. package/dist/hid/constants.d.ts +2 -2
  10. package/dist/hid/constants.d.ts.map +1 -1
  11. package/dist/hid/constants.js +2 -0
  12. package/dist/hid/constants.js.map +1 -0
  13. package/dist/hid/helpers.js +6 -3
  14. package/dist/hid/helpers.js.map +1 -0
  15. package/dist/hid/index.d.ts +4 -4
  16. package/dist/hid/provider.d.ts +39 -37
  17. package/dist/hid/provider.d.ts.map +1 -1
  18. package/dist/hid/provider.js +15 -2
  19. package/dist/hid/provider.js.map +1 -0
  20. package/dist/iframe/connector.d.ts +9 -7
  21. package/dist/iframe/connector.d.ts.map +1 -1
  22. package/dist/iframe/connector.js +2 -0
  23. package/dist/iframe/connector.js.map +1 -0
  24. package/dist/iframe/helpers.d.ts +2 -0
  25. package/dist/iframe/helpers.d.ts.map +1 -1
  26. package/dist/iframe/helpers.js +3 -1
  27. package/dist/iframe/helpers.js.map +1 -0
  28. package/dist/iframe/index.d.ts +3 -3
  29. package/dist/iframe/provider.d.ts +6 -4
  30. package/dist/iframe/provider.d.ts.map +1 -1
  31. package/dist/iframe/provider.js +2 -0
  32. package/dist/iframe/provider.js.map +1 -0
  33. package/dist/index.d.ts +8 -3
  34. package/package.json +3 -4
  35. package/dist/__tests__/ssr.test.d.ts +0 -2
  36. package/dist/__tests__/ssr.test.d.ts.map +0 -1
  37. package/dist/hid/__tests__/connector.test.d.ts +0 -2
  38. package/dist/hid/__tests__/connector.test.d.ts.map +0 -1
  39. package/dist/hid/__tests__/fixtures.d.ts +0 -86
  40. package/dist/hid/__tests__/fixtures.d.ts.map +0 -1
  41. package/dist/hid/__tests__/helpers.test.d.ts +0 -2
  42. package/dist/hid/__tests__/helpers.test.d.ts.map +0 -1
  43. package/dist/hid/__tests__/provider.test.d.ts +0 -2
  44. package/dist/hid/__tests__/provider.test.d.ts.map +0 -1
  45. package/dist/hid/helpers.d.ts +0 -15
  46. package/dist/hid/helpers.d.ts.map +0 -1
  47. package/dist/hid/index.d.ts.map +0 -1
  48. package/dist/iframe/__tests__/connector.test.d.ts +0 -2
  49. package/dist/iframe/__tests__/connector.test.d.ts.map +0 -1
  50. package/dist/iframe/__tests__/fake-ledger-live.d.ts +0 -27
  51. package/dist/iframe/__tests__/fake-ledger-live.d.ts.map +0 -1
  52. package/dist/iframe/__tests__/helpers.test.d.ts +0 -2
  53. package/dist/iframe/__tests__/helpers.test.d.ts.map +0 -1
  54. package/dist/iframe/index.d.ts.map +0 -1
  55. package/dist/index.d.ts.map +0 -1
@@ -1,12 +1,9 @@
1
- import type Eth from '@ledgerhq/hw-app-eth';
2
- import { type Address, type LocalAccount } from 'viem';
3
- export type WithEthApp = <T>(callback: (eth: Eth) => T | Promise<T>) => Promise<T>;
4
- export type LedgerAccountOptions = {
5
- forceClearSign?: boolean;
6
- };
1
+ import { Address, LocalAccount } from "viem";
2
+ import Eth from "@ledgerhq/hw-app-eth";
3
+ //#region src/hid/account.d.ts
7
4
  export declare class ClearSignUnavailableError extends Error {
8
- name: string;
9
- constructor();
5
+ name: string;
6
+ constructor();
10
7
  }
11
- export declare const createLedgerAccount: (address: Address, path: string, withEthApp: WithEthApp, { forceClearSign }?: LedgerAccountOptions) => LocalAccount;
8
+ //#endregion
12
9
  //# sourceMappingURL=account.d.ts.map
@@ -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,EAEZ,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;AAEhB,MAAM,MAAM,oBAAoB,GAAG;IAEjC,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAMF,qBAAa,yBAA0B,SAAQ,KAAK;IACzC,IAAI,SAA+B;;CAK7C;AA4BD,eAAO,MAAM,mBAAmB,GAC9B,SAAS,OAAO,EAChB,MAAM,MAAM,EACZ,YAAY,UAAU,EACtB,qBAA4B,oBAAyB,KACpD,YA4FC,CAAC"}
1
+ {"version":3,"file":"account.d.ts","names":[],"sources":["../../src/hid/account.ts"],"mappings":";;;qBAgCa,kCAAkC;EACpC;EAET"}
@@ -1,4 +1,4 @@
1
- import { bytesToHex, getTypesForEIP712Domain, hashStruct, serializeSignature, serializeTransaction, stringToHex } from "viem";
1
+ import { BaseError, bytesToHex, getTypesForEIP712Domain, hashStruct, serializeSignature, serializeTransaction, stringToHex } from "viem";
2
2
  import { toAccount } from "viem/accounts";
3
3
  //#region src/hid/account.ts
4
4
  var ClearSignUnavailableError = class extends Error {
@@ -25,9 +25,10 @@ const toSignatureHex = ({ r, s, v }) => serializeSignature({
25
25
  s: `0x${s}`,
26
26
  v: BigInt(v)
27
27
  });
28
- const createLedgerAccount = (address, path, withEthApp, { forceClearSign = false } = {}) => toAccount({
28
+ const createLedgerAccount = (address, path, withEthApp, { chainId, forceClearSign = false }) => toAccount({
29
29
  address,
30
30
  async signTransaction(transaction, { serializer = serializeTransaction } = {}) {
31
+ if (transaction.chainId !== chainId) throw new BaseError("Transaction chain ID does not match the configured Ledger chain.");
31
32
  const unsignedRawTx = (await serializer(transaction)).slice(2);
32
33
  const { r, s, v } = await withEthApp(async (eth) => {
33
34
  const resolution = await eth.ledgerService.resolveTransaction(unsignedRawTx, eth.loadConfig, RESOLUTION_CONFIG).catch((error) => {
@@ -74,3 +75,5 @@ const createLedgerAccount = (address, path, withEthApp, { forceClearSign = false
74
75
  });
75
76
  //#endregion
76
77
  export { ClearSignUnavailableError, createLedgerAccount };
78
+
79
+ //# sourceMappingURL=account.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account.js","names":[],"sources":["../../src/hid/account.ts"],"sourcesContent":["import type Eth from '@ledgerhq/hw-app-eth';\nimport { toAccount } from 'viem/accounts';\nimport {\n BaseError,\n bytesToHex,\n getTypesForEIP712Domain,\n hashStruct,\n serializeSignature,\n serializeTransaction,\n stringToHex,\n type Address,\n type Hex,\n type LocalAccount,\n type TypedDataDefinition,\n} from 'viem';\n\ntype EIP712Message = Parameters<Eth['signEIP712Message']>[1];\n\nexport type WithEthApp = <T>(\n callback: (eth: Eth) => T | Promise<T>,\n) => Promise<T>;\n\nexport type LedgerAccountOptions = {\n chainId: number;\n // Refuse to sign a contract call the device cannot clear sign.\n forceClearSign?: boolean;\n};\n\ntype TransactionResolution = Awaited<\n ReturnType<Eth['ledgerService']['resolveTransaction']>\n>;\n\nexport class ClearSignUnavailableError extends Error {\n override name = 'ClearSignUnavailableError';\n\n constructor() {\n super('The transaction cannot be clear signed on the device.');\n }\n}\n\nconst hasCalldata = (data?: Hex) => !!data && data !== '0x';\n\nconst isEmptyResolution = (resolution: TransactionResolution | null) =>\n !resolution ||\n [\n resolution.erc20Tokens,\n resolution.nfts,\n resolution.externalPlugin,\n resolution.plugin,\n ].every((descriptors) => descriptors.length === 0);\n\n// What the Ledger service should try to resolve for clear signing.\nconst RESOLUTION_CONFIG = {\n erc20: true,\n externalPlugins: true,\n nft: true,\n};\n\n// Devices without full EIP-712 support (e.g. Nano S) reject the structured\n// message and can only sign its domain and message hashes.\nconst shouldFallbackToHashedSigning = (error: unknown) =>\n (error as { statusText?: string } | null)?.statusText === 'INS_NOT_SUPPORTED';\n\nconst toSignatureHex = ({ r, s, v }: { r: string; s: string; v: number }) =>\n serializeSignature({ r: `0x${r}`, s: `0x${s}`, v: BigInt(v) });\n\nexport const createLedgerAccount = (\n address: Address,\n path: string,\n withEthApp: WithEthApp,\n { chainId, forceClearSign = false }: LedgerAccountOptions,\n): LocalAccount =>\n toAccount({\n address,\n\n async signTransaction(\n transaction,\n { serializer = serializeTransaction } = {},\n ) {\n // RPC filling can replace chainId even when the request pinned it.\n // Fail before serialization, metadata resolution or any device action.\n if (transaction.chainId !== chainId)\n throw new BaseError(\n 'Transaction chain ID does not match the configured Ledger chain.',\n );\n const unsignedRawTx = (await serializer(transaction)).slice(2);\n const { r, s, v } = await withEthApp(async (eth) => {\n // Metadata fetch failures are swallowed by the Ledger service and\n // surface as an empty resolution, which the device blind signs.\n const resolution = await eth.ledgerService\n .resolveTransaction(unsignedRawTx, eth.loadConfig, RESOLUTION_CONFIG)\n .catch((error: unknown) => {\n if (forceClearSign) throw error;\n return null;\n });\n if (\n forceClearSign &&\n hasCalldata(transaction.data) &&\n isEmptyResolution(resolution)\n )\n throw new ClearSignUnavailableError();\n return eth.signTransaction(path, unsignedRawTx, resolution);\n });\n\n // For typed transactions the device returns the yParity (0/1),\n // for legacy ones — the full EIP-155 `v`; viem accepts both.\n return serializer(transaction, {\n r: `0x${r}`,\n s: `0x${s}`,\n v: BigInt(`0x${v}`),\n });\n },\n\n async signMessage({ message }) {\n const messageHex =\n typeof message === 'string'\n ? stringToHex(message)\n : typeof message.raw === 'string'\n ? message.raw\n : bytesToHex(message.raw);\n\n const signature = await withEthApp((eth) =>\n eth.signPersonalMessage(path, messageHex.slice(2)),\n );\n return toSignatureHex(signature);\n },\n\n async signTypedData(parameters) {\n const {\n domain = {},\n types,\n primaryType,\n message,\n } = parameters as TypedDataDefinition;\n\n const signature = await withEthApp(async (eth) => {\n try {\n return await eth.signEIP712Message(\n path,\n parameters as unknown as EIP712Message,\n );\n } catch (error) {\n if (!shouldFallbackToHashedSigning(error)) throw error;\n\n const typedDataDomain = domain;\n const domainSeparator = hashStruct({\n data: typedDataDomain,\n primaryType: 'EIP712Domain',\n types: {\n EIP712Domain: getTypesForEIP712Domain({\n domain: typedDataDomain,\n }),\n },\n });\n const messageHash = hashStruct({\n data: message,\n primaryType,\n types,\n });\n\n return eth.signEIP712HashedMessage(\n path,\n domainSeparator.slice(2),\n messageHash.slice(2),\n );\n }\n });\n return toSignatureHex(signature);\n },\n });\n"],"mappings":";;;AAgCA,IAAa,4BAAb,cAA+C,MAAM;CAGnD,cAAc;EACZ,MAAM,uDAAuD;EAH/D,KAAS,OAAO;CAIhB;AACF;AAEA,MAAM,eAAe,SAAe,CAAC,CAAC,QAAQ,SAAS;AAEvD,MAAM,qBAAqB,eACzB,CAAC,cACD;CACE,WAAW;CACX,WAAW;CACX,WAAW;CACX,WAAW;AACb,CAAC,CAAC,OAAO,gBAAgB,YAAY,WAAW,CAAC;AAGnD,MAAM,oBAAoB;CACxB,OAAO;CACP,iBAAiB;CACjB,KAAK;AACP;AAIA,MAAM,iCAAiC,UACpC,OAA0C,eAAe;AAE5D,MAAM,kBAAkB,EAAE,GAAG,GAAG,QAC9B,mBAAmB;CAAE,GAAG,KAAK;CAAK,GAAG,KAAK;CAAK,GAAG,OAAO,CAAC;AAAE,CAAC;AAE/D,MAAa,uBACX,SACA,MACA,YACA,EAAE,SAAS,iBAAiB,YAE5B,UAAU;CACR;CAEA,MAAM,gBACJ,aACA,EAAE,aAAa,yBAAyB,CAAC,GACzC;EAGA,IAAI,YAAY,YAAY,SAC1B,MAAM,IAAI,UACR,kEACF;EACF,MAAM,iBAAiB,MAAM,WAAW,WAAW,EAAA,CAAG,MAAM,CAAC;EAC7D,MAAM,EAAE,GAAG,GAAG,MAAM,MAAM,WAAW,OAAO,QAAQ;GAGlD,MAAM,aAAa,MAAM,IAAI,cAC1B,mBAAmB,eAAe,IAAI,YAAY,iBAAiB,CAAC,CACpE,OAAO,UAAmB;IACzB,IAAI,gBAAgB,MAAM;IAC1B,OAAO;GACT,CAAC;GACH,IACE,kBACA,YAAY,YAAY,IAAI,KAC5B,kBAAkB,UAAU,GAE5B,MAAM,IAAI,0BAA0B;GACtC,OAAO,IAAI,gBAAgB,MAAM,eAAe,UAAU;EAC5D,CAAC;EAID,OAAO,WAAW,aAAa;GAC7B,GAAG,KAAK;GACR,GAAG,KAAK;GACR,GAAG,OAAO,KAAK,GAAG;EACpB,CAAC;CACH;CAEA,MAAM,YAAY,EAAE,WAAW;EAC7B,MAAM,aACJ,OAAO,YAAY,WACf,YAAY,OAAO,IACnB,OAAO,QAAQ,QAAQ,WACrB,QAAQ,MACR,WAAW,QAAQ,GAAG;EAE9B,MAAM,YAAY,MAAM,YAAY,QAClC,IAAI,oBAAoB,MAAM,WAAW,MAAM,CAAC,CAAC,CACnD;EACA,OAAO,eAAe,SAAS;CACjC;CAEA,MAAM,cAAc,YAAY;EAC9B,MAAM,EACJ,SAAS,CAAC,GACV,OACA,aACA,YACE;EAEJ,MAAM,YAAY,MAAM,WAAW,OAAO,QAAQ;GAChD,IAAI;IACF,OAAO,MAAM,IAAI,kBACf,MACA,UACF;GACF,SAAS,OAAO;IACd,IAAI,CAAC,8BAA8B,KAAK,GAAG,MAAM;IAEjD,MAAM,kBAAkB;IACxB,MAAM,kBAAkB,WAAW;KACjC,MAAM;KACN,aAAa;KACb,OAAO,EACL,cAAc,wBAAwB,EACpC,QAAQ,gBACV,CAAC,EACH;IACF,CAAC;IACD,MAAM,cAAc,WAAW;KAC7B,MAAM;KACN;KACA;IACF,CAAC;IAED,OAAO,IAAI,wBACT,MACA,gBAAgB,MAAM,CAAC,GACvB,YAAY,MAAM,CAAC,CACrB;GACF;EACF,CAAC;EACD,OAAO,eAAe,SAAS;CACjC;AACF,CAAC"}
@@ -1,15 +1,16 @@
1
- import { Chain } from 'wagmi/chains';
2
- import type { LedgerHQProvider } from './provider';
1
+ import { LedgerHQProvider } from "./provider.js";
2
+ import { Chain } from "wagmi/chains";
3
+ //#region src/hid/connector.d.ts
3
4
  export declare const idLedgerHid = "ledgerHID";
4
- export declare const name = "Ledger";
5
5
  type LedgerHIDConnectorOptions = {
6
- rpc: Record<number, string>;
7
- defaultChain: Chain;
8
- forceClearSign?: boolean;
6
+ rpc: Record<number, string>;
7
+ defaultChain: Chain;
8
+ forceClearSign?: boolean;
9
9
  };
10
- export declare function ledgerHIDConnector({ rpc, defaultChain, forceClearSign, }: LedgerHIDConnectorOptions): import("wagmi").CreateConnectorFn<LedgerHQProvider, Record<string, unknown>, Record<string, unknown>>;
10
+ export declare function ledgerHIDConnector({ rpc, defaultChain, forceClearSign }: LedgerHIDConnectorOptions): import("wagmi").CreateConnectorFn<LedgerHQProvider, Record<string, unknown>, Record<string, unknown>>;
11
11
  export declare namespace ledgerHIDConnector {
12
- var type: "ledgerHID";
12
+ var type: "ledgerHID";
13
13
  }
14
+ //#endregion
14
15
  export {};
15
16
  //# sourceMappingURL=connector.d.ts.map
@@ -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;AAUrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,eAAO,MAAM,WAAW,cAAc,CAAC;AACvC,eAAO,MAAM,IAAI,WAAW,CAAC;AAE7B,KAAK,yBAAyB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,YAAY,EAAE,KAAK,CAAC;IAGpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAGF,wBAAgB,kBAAkB,CAAC,EACjC,GAAG,EACH,YAAY,EACZ,cAAc,GACf,EAAE,yBAAyB,yGAqI3B;yBAzIe,kBAAkB"}
1
+ {"version":3,"file":"connector.d.ts","names":[],"sources":["../../src/hid/connector.ts"],"mappings":";;;qBAgBa;KAGR;EACH,KAAK;EACL,cAAc;EAGd;;wBAIc,qBACd,KACA,cACA,kBACC,4CAAyB,kBAAA,kBAAA,yBAAA;yBAJZ;MAAA"}
@@ -96,3 +96,5 @@ function ledgerHIDConnector({ rpc, defaultChain, forceClearSign }) {
96
96
  }
97
97
  //#endregion
98
98
  export { idLedgerHid, ledgerHIDConnector, name };
99
+
100
+ //# sourceMappingURL=connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connector.js","names":[],"sources":["../../src/hid/connector.ts"],"sourcesContent":["import {\n ChainNotConfiguredError,\n ConnectorNotFoundError,\n createConnector,\n} from 'wagmi';\nimport { Chain } from 'wagmi/chains';\nimport { SwitchChainError } from 'viem';\nimport {\n checkError,\n clearLedgerAccount,\n clearLedgerChainId,\n clearLedgerDerivationPath,\n restoreLedgerChainId,\n saveLedgerChainId,\n} from '../hid/helpers';\nimport type { LedgerHQProvider } from './provider';\nexport const idLedgerHid = 'ledgerHID';\nexport const name = 'Ledger';\n\ntype LedgerHIDConnectorOptions = {\n rpc: Record<number, string>;\n defaultChain: Chain;\n // Reject contract calls the device cannot clear sign (e.g. when Ledger's\n // metadata service is unreachable) instead of letting it blind sign.\n forceClearSign?: boolean;\n};\n\nledgerHIDConnector.type = 'ledgerHID' as const;\nexport function ledgerHIDConnector({\n rpc,\n defaultChain,\n forceClearSign,\n}: LedgerHIDConnectorOptions) {\n const providers: Record<Chain['id'], LedgerHQProvider> = {};\n // The chain chosen by the user is persisted in localStorage so that a\n // reconnect after a page reload lands on the same chain.\n let currentChainId: number | undefined = restoreLedgerChainId();\n\n return createConnector<LedgerHQProvider>(({ chains, emitter }) => {\n // Shared by programmatic and physical disconnects. The listener may sit\n // on a provider other than the current one after a chain switch.\n const forgetSession = () => {\n Object.values(providers).forEach((provider) => {\n provider.removeListener('disconnect', onDisconnect);\n provider.resetAccount();\n });\n currentChainId = undefined;\n clearLedgerDerivationPath();\n clearLedgerChainId();\n clearLedgerAccount();\n };\n\n // Fired by the provider on HID disconnect (e.g. unplug); called unbound.\n const onDisconnect = () => {\n forgetSession();\n emitter.emit('disconnect');\n };\n\n return {\n id: idLedgerHid,\n name,\n type: ledgerHIDConnector.type,\n\n async getProvider({ chainId } = {}) {\n const chain =\n chains.find((x) => x.id === (chainId ?? currentChainId)) ??\n defaultChain;\n if (!providers[chain.id]) {\n const { LedgerHQProvider } = await import('./provider');\n providers[chain.id] = new LedgerHQProvider({\n chain,\n rpcUrl: rpc?.[chain.id],\n supportedChainIds: chains.map((x) => x.id),\n forceClearSign,\n });\n }\n return providers[chain.id];\n },\n\n async connect({\n chainId,\n withCapabilities = false,\n }: {\n chainId?: number;\n isReconnecting?: boolean;\n withCapabilities?: boolean;\n } = {}) {\n try {\n // On reconnect wagmi calls connect() without a chainId — keep the\n // restored one instead of falling back to the default chain.\n currentChainId = chainId ?? currentChainId;\n const provider = await this.getProvider({ chainId: currentChainId });\n provider.on('disconnect', onDisconnect);\n const account = await provider.enable();\n const connectedChainId = await this.getChainId();\n currentChainId = connectedChainId;\n saveLedgerChainId(connectedChainId);\n\n return {\n accounts: (withCapabilities\n ? [{ address: account, capabilities: {} }]\n : [account]) as never,\n chainId: connectedChainId,\n };\n } catch (error) {\n // Revert the optimistic assignment above to the last persisted chain.\n currentChainId = restoreLedgerChainId();\n return checkError(error);\n }\n },\n\n async disconnect() {\n forgetSession();\n },\n\n async getAccounts() {\n const provider = await this.getProvider();\n const address = await provider.getAddress();\n return [address];\n },\n\n async getChainId() {\n const provider = await this.getProvider();\n return provider.chain.id;\n },\n\n async isAuthorized() {\n try {\n const provider = await this.getProvider();\n if (!provider) throw new ConnectorNotFoundError();\n const [account] = await this.getAccounts();\n return !!account;\n } catch (e) {\n // The errors caught here are generally expected in most use cases.\n // However, unexpected errors may still occur, so they should at least be logged to the console.\n console.error(e);\n return false;\n }\n },\n\n async switchChain({ chainId }) {\n const chain = chains.find((x) => x.id === chainId);\n if (!chain) throw new SwitchChainError(new ChainNotConfiguredError());\n\n currentChainId = chainId;\n saveLedgerChainId(chainId);\n emitter.emit('change', { chainId });\n return chain;\n },\n\n onDisconnect,\n\n onAccountsChanged() {\n // NOOP\n // HID Ledger cannot change account by itself\n },\n\n onChainChanged() {\n // NOOP\n // HID Ledger cannot change chain by itself\n },\n };\n });\n}\n"],"mappings":";;;;AAgBA,MAAa,cAAc;AAC3B,MAAa,OAAO;AAUpB,mBAAmB,OAAO;AAC1B,SAAgB,mBAAmB,EACjC,KACA,cACA,kBAC4B;CAC5B,MAAM,YAAmD,CAAC;CAG1D,IAAI,iBAAqC,qBAAqB;CAE9D,OAAO,iBAAmC,EAAE,QAAQ,cAAc;EAGhE,MAAM,sBAAsB;GAC1B,OAAO,OAAO,SAAS,CAAC,CAAC,SAAS,aAAa;IAC7C,SAAS,eAAe,cAAc,YAAY;IAClD,SAAS,aAAa;GACxB,CAAC;GACD,iBAAiB,KAAA;GACjB,0BAA0B;GAC1B,mBAAmB;GACnB,mBAAmB;EACrB;EAGA,MAAM,qBAAqB;GACzB,cAAc;GACd,QAAQ,KAAK,YAAY;EAC3B;EAEA,OAAO;GACL,IAAI;GACJ;GACA,MAAM,mBAAmB;GAEzB,MAAM,YAAY,EAAE,YAAY,CAAC,GAAG;IAClC,MAAM,QACJ,OAAO,MAAM,MAAM,EAAE,QAAQ,WAAW,eAAe,KACvD;IACF,IAAI,CAAC,UAAU,MAAM,KAAK;KACxB,MAAM,EAAE,qBAAqB,MAAM,OAAO;KAC1C,UAAU,MAAM,MAAM,IAAI,iBAAiB;MACzC;MACA,QAAQ,MAAM,MAAM;MACpB,mBAAmB,OAAO,KAAK,MAAM,EAAE,EAAE;MACzC;KACF,CAAC;IACH;IACA,OAAO,UAAU,MAAM;GACzB;GAEA,MAAM,QAAQ,EACZ,SACA,mBAAmB,UAKjB,CAAC,GAAG;IACN,IAAI;KAGF,iBAAiB,WAAW;KAC5B,MAAM,WAAW,MAAM,KAAK,YAAY,EAAE,SAAS,eAAe,CAAC;KACnE,SAAS,GAAG,cAAc,YAAY;KACtC,MAAM,UAAU,MAAM,SAAS,OAAO;KACtC,MAAM,mBAAmB,MAAM,KAAK,WAAW;KAC/C,iBAAiB;KACjB,kBAAkB,gBAAgB;KAElC,OAAO;MACL,UAAW,mBACP,CAAC;OAAE,SAAS;OAAS,cAAc,CAAC;MAAE,CAAC,IACvC,CAAC,OAAO;MACZ,SAAS;KACX;IACF,SAAS,OAAO;KAEd,iBAAiB,qBAAqB;KACtC,OAAO,WAAW,KAAK;IACzB;GACF;GAEA,MAAM,aAAa;IACjB,cAAc;GAChB;GAEA,MAAM,cAAc;IAGlB,OAAO,CAAC,OADc,MADC,KAAK,YAAY,EAAA,CACT,WAAW,CAC3B;GACjB;GAEA,MAAM,aAAa;IAEjB,QAAO,MADgB,KAAK,YAAY,EAAA,CACxB,MAAM;GACxB;GAEA,MAAM,eAAe;IACnB,IAAI;KAEF,IAAI,CAAC,MADkB,KAAK,YAAY,GACzB,MAAM,IAAI,uBAAuB;KAChD,MAAM,CAAC,WAAW,MAAM,KAAK,YAAY;KACzC,OAAO,CAAC,CAAC;IACX,SAAS,GAAG;KAGV,QAAQ,MAAM,CAAC;KACf,OAAO;IACT;GACF;GAEA,MAAM,YAAY,EAAE,WAAW;IAC7B,MAAM,QAAQ,OAAO,MAAM,MAAM,EAAE,OAAO,OAAO;IACjD,IAAI,CAAC,OAAO,MAAM,IAAI,iBAAiB,IAAI,wBAAwB,CAAC;IAEpE,iBAAiB;IACjB,kBAAkB,OAAO;IACzB,QAAQ,KAAK,UAAU,EAAE,QAAQ,CAAC;IAClC,OAAO;GACT;GAEA;GAEA,oBAAoB,CAGpB;GAEA,iBAAiB,CAGjB;EACF;CACF,CAAC;AACH"}
@@ -1,4 +1,4 @@
1
+ //#region src/hid/constants.d.ts
1
2
  export declare const LS_KEY_DERIVATION_PATH = "reef-knot_ledger-derivation-path";
2
- export declare const LS_KEY_CHAIN_ID = "reef-knot_ledger-chain-id";
3
- export declare const LS_KEY_ACCOUNT = "reef-knot_ledger-account";
3
+ //#endregion
4
4
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"constants.d.ts","names":[],"sources":["../../src/hid/constants.ts"],"mappings":";qBAAa"}
@@ -4,3 +4,5 @@ const LS_KEY_CHAIN_ID = "reef-knot_ledger-chain-id";
4
4
  const LS_KEY_ACCOUNT = "reef-knot_ledger-account";
5
5
  //#endregion
6
6
  export { LS_KEY_ACCOUNT, LS_KEY_CHAIN_ID, LS_KEY_DERIVATION_PATH };
7
+
8
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../src/hid/constants.ts"],"sourcesContent":["export const LS_KEY_DERIVATION_PATH = 'reef-knot_ledger-derivation-path';\nexport const LS_KEY_CHAIN_ID = 'reef-knot_ledger-chain-id';\nexport const LS_KEY_ACCOUNT = 'reef-knot_ledger-account';\n"],"mappings":";AAAA,MAAa,yBAAyB;AACtC,MAAa,kBAAkB;AAC/B,MAAa,iBAAiB"}
@@ -3,9 +3,10 @@ import { isAddress } from "viem";
3
3
  //#region src/hid/helpers.ts
4
4
  const isLockedDeviceError = (error) => error?.name === "LockedDeviceError";
5
5
  const checkError = (error) => {
6
- if (error.statusText === "INS_NOT_SUPPORTED") error.message = "Device is not supported. Make sure the Ethereum app is open on the device.";
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.";
8
- if (error.statusText === "CONDITIONS_OF_USE_NOT_SATISFIED") error.message = "User rejected the request";
6
+ const ledgerError = error;
7
+ if (ledgerError.statusText === "INS_NOT_SUPPORTED") ledgerError.message = "Device is not supported. Make sure the Ethereum app is open on the device.";
8
+ if (ledgerError.statusText === "UNKNOWN_ERROR") ledgerError.message = "Unknown error. Make sure the device is connected and the Ethereum app is open on the device.";
9
+ if (ledgerError.statusText === "CONDITIONS_OF_USE_NOT_SATISFIED") ledgerError.message = "User rejected the request";
9
10
  throw error;
10
11
  };
11
12
  const clearLedgerDerivationPath = () => {
@@ -49,3 +50,5 @@ const clearLedgerAccount = () => {
49
50
  };
50
51
  //#endregion
51
52
  export { checkError, clearLedgerAccount, clearLedgerChainId, clearLedgerDerivationPath, isLockedDeviceError, restoreLedgerAccount, restoreLedgerChainId, saveLedgerAccount, saveLedgerChainId };
53
+
54
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","names":[],"sources":["../../src/hid/helpers.ts"],"sourcesContent":["import { isAddress, type Address } from 'viem';\nimport {\n LS_KEY_ACCOUNT,\n LS_KEY_CHAIN_ID,\n LS_KEY_DERIVATION_PATH,\n} from './constants';\n\nexport type PersistedLedgerAccount = {\n address: Address;\n path: string;\n};\n\nexport const isLockedDeviceError = (error: unknown): boolean =>\n (error as { name?: string } | null)?.name === 'LockedDeviceError';\n\nexport const checkError = (error: unknown): never => {\n // Ledger transport errors expose statusText in addition to the standard Error fields.\n const ledgerError = error as { statusText?: string; message?: string };\n if (ledgerError.statusText === 'INS_NOT_SUPPORTED') {\n ledgerError.message =\n 'Device is not supported. Make sure the Ethereum app is open on the device.';\n }\n\n if (ledgerError.statusText === 'UNKNOWN_ERROR') {\n ledgerError.message =\n 'Unknown error. Make sure the device is connected and the Ethereum app is open on the device.';\n }\n\n if (ledgerError.statusText === 'CONDITIONS_OF_USE_NOT_SATISFIED') {\n ledgerError.message = 'User rejected the request';\n }\n\n throw error;\n};\n\nexport const clearLedgerDerivationPath = () => {\n // `window?.` is not enough: an undeclared identifier still throws in SSR.\n if (typeof window === 'undefined') return;\n window.localStorage.removeItem(LS_KEY_DERIVATION_PATH);\n};\n\nexport const saveLedgerChainId = (chainId: number) => {\n if (typeof window === 'undefined') return;\n window.localStorage.setItem(LS_KEY_CHAIN_ID, String(chainId));\n};\n\nexport const restoreLedgerChainId = (): number | undefined => {\n if (typeof window === 'undefined') return undefined;\n const stored = window.localStorage.getItem(LS_KEY_CHAIN_ID);\n if (!stored) return undefined;\n const chainId = Number(stored);\n return Number.isInteger(chainId) && chainId > 0 ? chainId : undefined;\n};\n\nexport const clearLedgerChainId = () => {\n if (typeof window === 'undefined') return;\n window.localStorage.removeItem(LS_KEY_CHAIN_ID);\n};\n\nexport const saveLedgerAccount = (account: PersistedLedgerAccount) => {\n if (typeof window === 'undefined') return;\n window.localStorage.setItem(LS_KEY_ACCOUNT, JSON.stringify(account));\n};\n\nexport const restoreLedgerAccount = (): PersistedLedgerAccount | undefined => {\n if (typeof window === 'undefined') return undefined;\n const stored = window.localStorage.getItem(LS_KEY_ACCOUNT);\n if (!stored) return undefined;\n try {\n const { address, path } = JSON.parse(\n stored,\n ) as Partial<PersistedLedgerAccount>;\n if (address && isAddress(address) && typeof path === 'string')\n return { address, path };\n } catch {\n // A malformed record is the same as no record.\n }\n return undefined;\n};\n\nexport const clearLedgerAccount = () => {\n if (typeof window === 'undefined') return;\n window.localStorage.removeItem(LS_KEY_ACCOUNT);\n};\n"],"mappings":";;;AAYA,MAAa,uBAAuB,UACjC,OAAoC,SAAS;AAEhD,MAAa,cAAc,UAA0B;CAEnD,MAAM,cAAc;CACpB,IAAI,YAAY,eAAe,qBAC7B,YAAY,UACV;CAGJ,IAAI,YAAY,eAAe,iBAC7B,YAAY,UACV;CAGJ,IAAI,YAAY,eAAe,mCAC7B,YAAY,UAAU;CAGxB,MAAM;AACR;AAEA,MAAa,kCAAkC;CAE7C,IAAI,OAAO,WAAW,aAAa;CACnC,OAAO,aAAa,WAAW,sBAAsB;AACvD;AAEA,MAAa,qBAAqB,YAAoB;CACpD,IAAI,OAAO,WAAW,aAAa;CACnC,OAAO,aAAa,QAAQ,iBAAiB,OAAO,OAAO,CAAC;AAC9D;AAEA,MAAa,6BAAiD;CAC5D,IAAI,OAAO,WAAW,aAAa,OAAO,KAAA;CAC1C,MAAM,SAAS,OAAO,aAAa,QAAQ,eAAe;CAC1D,IAAI,CAAC,QAAQ,OAAO,KAAA;CACpB,MAAM,UAAU,OAAO,MAAM;CAC7B,OAAO,OAAO,UAAU,OAAO,KAAK,UAAU,IAAI,UAAU,KAAA;AAC9D;AAEA,MAAa,2BAA2B;CACtC,IAAI,OAAO,WAAW,aAAa;CACnC,OAAO,aAAa,WAAW,eAAe;AAChD;AAEA,MAAa,qBAAqB,YAAoC;CACpE,IAAI,OAAO,WAAW,aAAa;CACnC,OAAO,aAAa,QAAQ,gBAAgB,KAAK,UAAU,OAAO,CAAC;AACrE;AAEA,MAAa,6BAAiE;CAC5E,IAAI,OAAO,WAAW,aAAa,OAAO,KAAA;CAC1C,MAAM,SAAS,OAAO,aAAa,QAAQ,cAAc;CACzD,IAAI,CAAC,QAAQ,OAAO,KAAA;CACpB,IAAI;EACF,MAAM,EAAE,SAAS,SAAS,KAAK,MAC7B,MACF;EACA,IAAI,WAAW,UAAU,OAAO,KAAK,OAAO,SAAS,UACnD,OAAO;GAAE;GAAS;EAAK;CAC3B,QAAQ,CAER;AAEF;AAEA,MAAa,2BAA2B;CACtC,IAAI,OAAO,WAAW,aAAa;CACnC,OAAO,aAAa,WAAW,cAAc;AAC/C"}
@@ -1,4 +1,4 @@
1
- export { idLedgerHid, ledgerHIDConnector } from './connector';
2
- export { LS_KEY_DERIVATION_PATH } from './constants';
3
- export { ClearSignUnavailableError } from './account';
4
- //# sourceMappingURL=index.d.ts.map
1
+ import { idLedgerHid, ledgerHIDConnector } from "./connector.js";
2
+ import { LS_KEY_DERIVATION_PATH } from "./constants.js";
3
+ import { ClearSignUnavailableError } from "./account.js";
4
+ export { ClearSignUnavailableError, LS_KEY_DERIVATION_PATH, idLedgerHid, ledgerHIDConnector };
@@ -1,47 +1,49 @@
1
- import type Eth from '@ledgerhq/hw-app-eth';
2
- import type TransportWebHID from '@ledgerhq/hw-transport-webhid';
3
- import { type Address, type Chain, type LocalAccount } from 'viem';
1
+ import { Address, Chain, LocalAccount } from "viem";
2
+ import Eth from "@ledgerhq/hw-app-eth";
3
+ import TransportWebHID from "@ledgerhq/hw-transport-webhid";
4
+ //#region src/hid/provider.d.ts
4
5
  type RequestArguments = {
5
- method: string;
6
- params?: unknown[];
6
+ method: string;
7
+ params?: unknown[];
7
8
  };
8
9
  type ProviderEvent = 'disconnect';
9
10
  type Listener = () => void;
10
11
  type LedgerHQProviderOptions = {
11
- chain: Chain;
12
- rpcUrl?: string;
13
- supportedChainIds?: number[];
14
- forceClearSign?: boolean;
12
+ chain: Chain;
13
+ rpcUrl?: string;
14
+ supportedChainIds?: number[];
15
+ forceClearSign?: boolean;
15
16
  };
16
17
  export declare class LedgerHQProvider {
17
- readonly chain: Chain;
18
- device?: HIDDevice;
19
- transport?: typeof TransportWebHID;
20
- private readonly rpcUrl?;
21
- private account?;
22
- private accountPath?;
23
- private publicClient?;
24
- private walletClient?;
25
- private listeners;
26
- private readonly supportedChainIds;
27
- private readonly forceClearSign;
28
- constructor({ chain, rpcUrl, supportedChainIds, forceClearSign, }: LedgerHQProviderOptions);
29
- on(event: ProviderEvent, listener: Listener): void;
30
- removeListener(event: ProviderEvent, listener: Listener): void;
31
- emit(event: ProviderEvent): void;
32
- get derivationPath(): string;
33
- loadTransport(): Promise<void>;
34
- getTransport(): Promise<TransportWebHID>;
35
- withEthApp<T>(callback: (eth: Eth) => T | Promise<T>): Promise<T>;
36
- enable(): Promise<Address>;
37
- resetAccount(): void;
38
- getAccount(): Promise<LocalAccount>;
39
- private readAddress;
40
- getAddress(): Promise<Address>;
41
- private getPublicClient;
42
- private getWalletClient;
43
- private sendTransaction;
44
- request({ method, params }: RequestArguments): Promise<unknown>;
18
+ readonly chain: Chain;
19
+ device?: HIDDevice;
20
+ transport?: typeof TransportWebHID;
21
+ private readonly rpcUrl?;
22
+ private account?;
23
+ private accountPath?;
24
+ private publicClient?;
25
+ private walletClient?;
26
+ private listeners;
27
+ private readonly supportedChainIds;
28
+ private readonly forceClearSign;
29
+ constructor({ chain, rpcUrl, supportedChainIds, forceClearSign }: LedgerHQProviderOptions);
30
+ on(event: ProviderEvent, listener: Listener): void;
31
+ removeListener(event: ProviderEvent, listener: Listener): void;
32
+ emit(event: ProviderEvent): void;
33
+ get derivationPath(): string;
34
+ loadTransport(): Promise<void>;
35
+ getTransport(): Promise<TransportWebHID>;
36
+ withEthApp<T>(callback: (eth: Eth) => T | Promise<T>): Promise<T>;
37
+ enable(): Promise<Address>;
38
+ resetAccount(): void;
39
+ getAccount(): Promise<LocalAccount>;
40
+ private readAddress;
41
+ getAddress(): Promise<Address>;
42
+ private getPublicClient;
43
+ private getWalletClient;
44
+ private sendTransaction;
45
+ request({ method, params }: RequestArguments): Promise<unknown>;
45
46
  }
47
+ //#endregion
46
48
  export {};
47
49
  //# sourceMappingURL=provider.d.ts.map
@@ -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,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,KAAK,uBAAuB,GAAG;IAC7B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,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;IAE7C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;gBAE7B,EACV,KAAK,EACL,MAAM,EACN,iBAAiB,EACjB,cAAsB,GACvB,EAAE,uBAAuB;IAiB1B,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;YAuC3B,WAAW;IAoBnB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IAOpC,OAAO,CAAC,eAAe;YAQT,eAAe;YAUf,eAAe;IA4EvB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAW,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;CA2E3E"}
1
+ {"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/hid/provider.ts"],"mappings":";;;;KAmEK;EACH;EACA;;KAOG;KACA;KAEA;EACH,OAAO;EACP;EACA;EACA;;qBAGW;WACF,OAAO;EAET,SAAS;EAET,mBAAmB;mBAET;UAET;UAEA;UAEA;UAEA;UAEA;mBAIS;mBAEA;EAEjB,cACE,OACA,QACA,mBACA,kBACC;EAgBH,GAAG,OAAO,eAAe,UAAU;EAInC,eAAe,OAAO,eAAe,UAAU;EAI/C,KAAK,OAAO;MAMR;EAUE,iBAAa;EAQb,gBAAgB,QAAQ;EAc9B,WAAW,GAAG,WAAW,KAAK,QAAQ,IAAI,QAAQ,KAAK,QAAQ;EAoBzD,UAAU,QAAQ;EAyBxB;EAMM,cAAc,QAAQ;UAwCd;EAoBR,cAAc,QAAQ;UAOpB;UAQM;UAUA;EAqFR,UAAU,QAAQ,UAAe,mBAAmB"}
@@ -1,7 +1,7 @@
1
1
  import "./constants.js";
2
2
  import { checkError, clearLedgerAccount, isLockedDeviceError, restoreLedgerAccount, saveLedgerAccount } from "./helpers.js";
3
3
  import { createLedgerAccount } from "./account.js";
4
- import { MethodNotSupportedRpcError, createPublicClient, createWalletClient, getAddress, hexToBigInt, hexToNumber, http, isAddress, isAddressEqual, isHex, numberToHex } from "viem";
4
+ import { ChainMismatchError, MethodNotSupportedRpcError, createPublicClient, createWalletClient, getAddress, hexToBigInt, hexToNumber, http, isAddress, isAddressEqual, isHex, numberToHex } from "viem";
5
5
  //#region src/hid/provider.ts
6
6
  const NOOP = () => {};
7
7
  const DEFAULT_DERIVATION_PATH = "m/44'/60'/0'/0/0";
@@ -119,7 +119,10 @@ var LedgerHQProvider = class {
119
119
  }
120
120
  return cb(eth);
121
121
  });
122
- this.account = createLedgerAccount(address, path, withVerifyingEthApp, { forceClearSign: this.forceClearSign });
122
+ this.account = createLedgerAccount(address, path, withVerifyingEthApp, {
123
+ chainId: this.chain.id,
124
+ forceClearSign: this.forceClearSign
125
+ });
123
126
  this.accountPath = path;
124
127
  this.walletClient = void 0;
125
128
  }
@@ -167,6 +170,13 @@ var LedgerHQProvider = class {
167
170
  return this.walletClient;
168
171
  }
169
172
  async sendTransaction(transaction) {
173
+ if (transaction.chainId != null) {
174
+ const chainId = hexToNumber(transaction.chainId);
175
+ if (chainId !== this.chain.id) throw new ChainMismatchError({
176
+ chain: this.chain,
177
+ currentChainId: chainId
178
+ });
179
+ }
170
180
  const walletClient = await this.getWalletClient();
171
181
  const account = walletClient.account;
172
182
  if (transaction.from && (!isAddress(transaction.from) || !isAddressEqual(transaction.from, account.address))) throw new Error("from address mismatch");
@@ -175,6 +185,7 @@ var LedgerHQProvider = class {
175
185
  const request = {
176
186
  account,
177
187
  chain: this.chain,
188
+ chainId: this.chain.id,
178
189
  to: transaction.to ?? void 0,
179
190
  data: transaction.data,
180
191
  value: transaction.value ? hexToBigInt(transaction.value) : void 0,
@@ -243,3 +254,5 @@ var LedgerHQProvider = class {
243
254
  };
244
255
  //#endregion
245
256
  export { LedgerHQProvider };
257
+
258
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","names":[],"sources":["../../src/hid/provider.ts"],"sourcesContent":["import type Eth from '@ledgerhq/hw-app-eth';\nimport type TransportWebHID from '@ledgerhq/hw-transport-webhid';\nimport {\n ChainMismatchError,\n createPublicClient,\n createWalletClient,\n getAddress,\n hexToBigInt,\n hexToNumber,\n http,\n isAddress,\n isAddressEqual,\n isHex,\n MethodNotSupportedRpcError,\n numberToHex,\n type Address,\n type Chain,\n type Hex,\n type LocalAccount,\n type PublicClient,\n type RpcTransactionRequest,\n type WalletClient,\n} from 'viem';\nimport {\n checkError,\n clearLedgerAccount,\n isLockedDeviceError,\n restoreLedgerAccount,\n saveLedgerAccount,\n} from './helpers';\nimport { createLedgerAccount } from './account';\nimport { LS_KEY_DERIVATION_PATH } from './constants';\n\nconst NOOP = () => {};\n\nconst DEFAULT_DERIVATION_PATH = \"m/44'/60'/0'/0/0\";\n\nconst TX_TYPES = {\n '0x0': 'legacy',\n '0x1': 'eip2930',\n '0x2': 'eip1559',\n} as const;\n\n// Wallet-addressed methods outside the wallet_* namespace that this provider\n// does not implement. They must fail closed like wallet_* methods do — the\n// RPC node cannot serve them and would produce a confusing error.\nconst UNSUPPORTED_WALLET_METHODS = new Set([\n 'eth_signTransaction',\n 'eth_signTypedData',\n 'eth_signTypedData_v1',\n 'eth_signTypedData_v3',\n 'eth_decrypt',\n 'eth_getEncryptionPublicKey',\n 'personal_ecRecover',\n]);\n\n// The Ledger is one physical device, while providers exist per chain — the\n// session lock lives at module scope so sessions never overlap across\n// provider instances. WebHID rejects open() while the device is already open.\nlet deviceSessionLock: Promise<void> = Promise.resolve();\n\nconst withDeviceSession = <T>(fn: () => Promise<T>): Promise<T> => {\n const result = deviceSessionLock.then(fn);\n deviceSessionLock = result.then(NOOP, NOOP);\n return result;\n};\n\ntype RequestArguments = {\n method: string;\n params?: unknown[];\n};\n\n// Some callers include chainId in eth_sendTransaction, although viem's RPC\n// request union does not include it for every transaction type.\ntype LedgerTransactionRequest = RpcTransactionRequest & { chainId?: Hex };\n\ntype ProviderEvent = 'disconnect';\ntype Listener = () => void;\n\ntype LedgerHQProviderOptions = {\n chain: Chain;\n rpcUrl?: string;\n supportedChainIds?: number[];\n forceClearSign?: boolean;\n};\n\nexport class LedgerHQProvider {\n readonly chain: Chain;\n\n public device?: HIDDevice;\n\n public transport?: typeof TransportWebHID;\n\n private readonly rpcUrl?: string;\n\n private account?: LocalAccount;\n\n private accountPath?: string;\n\n private publicClient?: PublicClient;\n\n private walletClient?: WalletClient;\n\n private listeners: Partial<Record<ProviderEvent, Set<Listener>>> = {};\n\n // All chains the wallet (connector) is configured with, not just this\n // provider's chain — wallet_getCapabilities answers for the whole wallet.\n private readonly supportedChainIds: number[];\n\n private readonly forceClearSign: boolean;\n\n constructor({\n chain,\n rpcUrl,\n supportedChainIds,\n forceClearSign = false,\n }: LedgerHQProviderOptions) {\n this.chain = chain;\n this.rpcUrl = rpcUrl;\n this.supportedChainIds = supportedChainIds ?? [chain.id];\n this.forceClearSign = forceClearSign;\n\n if (!rpcUrl) {\n console.warn(\n `[reef-knot] No RPC URL configured for chain ${chain.id} (${chain.name}), ` +\n `falling back to its default public RPC endpoint`,\n );\n }\n }\n\n // --- events (the EIP-1193 subset the connector relies on) ---\n\n on(event: ProviderEvent, listener: Listener) {\n (this.listeners[event] ??= new Set()).add(listener);\n }\n\n removeListener(event: ProviderEvent, listener: Listener) {\n this.listeners[event]?.delete(listener);\n }\n\n emit(event: ProviderEvent) {\n this.listeners[event]?.forEach((listener) => listener());\n }\n\n // --- device transport ---\n\n get derivationPath() {\n if (typeof window !== 'undefined') {\n return (\n window.localStorage.getItem(LS_KEY_DERIVATION_PATH) ||\n DEFAULT_DERIVATION_PATH\n );\n }\n return DEFAULT_DERIVATION_PATH;\n }\n\n async loadTransport() {\n if (!this.transport) {\n const { default: TransportWebHID } =\n await import('@ledgerhq/hw-transport-webhid');\n this.transport = TransportWebHID;\n }\n }\n\n async getTransport(): Promise<TransportWebHID> {\n await this.loadTransport();\n\n try {\n const transportInstance =\n (await this.transport?.create()) as TransportWebHID;\n this.device = transportInstance.device;\n\n return transportInstance;\n } catch (error) {\n return checkError(error);\n }\n }\n\n withEthApp<T>(callback: (eth: Eth) => T | Promise<T>): Promise<T> {\n return withDeviceSession(async () => {\n const transport = await this.getTransport();\n\n try {\n const { default: Eth } = await import('@ledgerhq/hw-app-eth');\n const eth = new Eth(transport);\n await eth.getAppConfiguration();\n\n return await callback(eth);\n } catch (error) {\n return checkError(error);\n } finally {\n await transport.close();\n }\n });\n }\n\n // --- account ---\n\n async enable(): Promise<Address> {\n try {\n await this.loadTransport();\n\n const { hid } = window.navigator;\n\n const onDisconnect = (event: HIDConnectionEvent) => {\n if (this.device === event.device) {\n hid.removeEventListener('disconnect', onDisconnect);\n this.emit('disconnect');\n }\n };\n\n hid.addEventListener('disconnect', onDisconnect);\n\n // The device or the derivation path may have changed since the\n // previous connect, so the account is always re-read here.\n this.resetAccount();\n\n return await this.getAddress();\n } catch (error) {\n return checkError(error);\n }\n }\n\n resetAccount() {\n this.account = undefined;\n this.accountPath = undefined;\n this.walletClient = undefined;\n }\n\n async getAccount(): Promise<LocalAccount> {\n const path = this.derivationPath;\n\n // The cache is keyed by derivation path: when the user picks another\n // account, providers of other chains see the path change and re-read.\n if (!this.account || this.accountPath !== path) {\n const { address, verifiedByDevice } = await this.readAddress(path);\n let verified = verifiedByDevice;\n\n // An address restored from localStorage while the device was locked is\n // not yet proved by the device that will sign — the attached device may\n // not be the one the address was persisted from. Verify it inside the\n // first signing session and fail closed on mismatch.\n const withVerifyingEthApp = <T>(cb: (eth: Eth) => T | Promise<T>) =>\n this.withEthApp(async (eth) => {\n if (!verified) {\n const actual = await eth.getAddress(path);\n if (!isAddressEqual(getAddress(actual.address), address)) {\n clearLedgerAccount();\n this.resetAccount();\n this.emit('disconnect');\n throw new Error(\n 'The connected account does not match the device. Please reconnect.',\n );\n }\n verified = true;\n }\n return cb(eth);\n });\n\n this.account = createLedgerAccount(address, path, withVerifyingEthApp, {\n chainId: this.chain.id,\n forceClearSign: this.forceClearSign,\n });\n this.accountPath = path;\n this.walletClient = undefined;\n }\n return this.account;\n }\n\n private async readAddress(\n path: string,\n ): Promise<{ address: Address; verifiedByDevice: boolean }> {\n try {\n const { address } = await this.withEthApp((eth) => eth.getAddress(path));\n const checksummed = getAddress(address);\n saveLedgerAccount({ address: checksummed, path });\n return { address: checksummed, verifiedByDevice: true };\n } catch (error) {\n // A locked device is not a disconnect — the user is expected to keep\n // using the UI while the device locks itself. Fall back to the account\n // persisted on the last successful read; the lock error still surfaces\n // on any device action (signing) where the UI handles it specially.\n const persisted = restoreLedgerAccount();\n if (isLockedDeviceError(error) && persisted?.path === path)\n return { address: persisted.address, verifiedByDevice: false };\n return checkError(error);\n }\n }\n\n async getAddress(): Promise<Address> {\n const { address } = await this.getAccount();\n return address;\n }\n\n // --- RPC ---\n\n private getPublicClient(): PublicClient {\n this.publicClient ??= createPublicClient({\n chain: this.chain,\n transport: http(this.rpcUrl, { batch: true }),\n });\n return this.publicClient;\n }\n\n private async getWalletClient(): Promise<WalletClient> {\n const account = await this.getAccount();\n this.walletClient ??= createWalletClient({\n account,\n chain: this.chain,\n transport: http(this.rpcUrl, { batch: true }),\n });\n return this.walletClient;\n }\n\n private async sendTransaction(\n transaction: LedgerTransactionRequest,\n ): Promise<Hex> {\n if (transaction.chainId != null) {\n const chainId = hexToNumber(transaction.chainId);\n if (chainId !== this.chain.id)\n throw new ChainMismatchError({\n chain: this.chain,\n currentChainId: chainId,\n });\n }\n const walletClient = await this.getWalletClient();\n const account = walletClient.account as LocalAccount;\n\n if (\n transaction.from &&\n (!isAddress(transaction.from) ||\n !isAddressEqual(transaction.from, account.address))\n )\n throw new Error('from address mismatch');\n\n // Only the types the device can sign; anything else must not be\n // reinterpreted as one of them.\n const type =\n transaction.type != null\n ? TX_TYPES[transaction.type as keyof typeof TX_TYPES]\n : undefined;\n if (transaction.type != null && !type)\n throw new Error(`Unsupported transaction type ${transaction.type}`);\n\n // Missing fields (nonce, fees, gas) are populated by viem sequentially,\n // so transaction preparation never races on the device.\n const request = {\n account,\n chain: this.chain,\n chainId: this.chain.id,\n to: transaction.to ?? undefined,\n data: transaction.data,\n value: transaction.value ? hexToBigInt(transaction.value) : undefined,\n gas: transaction.gas ? hexToBigInt(transaction.gas) : undefined,\n nonce:\n transaction.nonce != null ? hexToNumber(transaction.nonce) : undefined,\n };\n // Not part of `request`: the legacy transaction type forbids accessList.\n const accessList = transaction.accessList;\n\n // An explicitly requested pre-1559 type must survive even without\n // gasPrice — viem then populates legacy fees instead of EIP-1559 ones.\n // The branches are spelled out because viem's transaction-request union\n // needs a literal `type` in each call.\n const gasPrice = transaction.gasPrice\n ? hexToBigInt(transaction.gasPrice)\n : undefined;\n\n if (type === 'legacy')\n return walletClient.sendTransaction({\n ...request,\n type: 'legacy',\n gasPrice,\n });\n\n if (type === 'eip2930')\n return walletClient.sendTransaction({\n ...request,\n type: 'eip2930',\n gasPrice,\n accessList,\n });\n\n if (!type && gasPrice)\n return walletClient.sendTransaction({ ...request, gasPrice, accessList });\n\n return walletClient.sendTransaction({\n ...request,\n type,\n accessList,\n maxFeePerGas: transaction.maxFeePerGas\n ? hexToBigInt(transaction.maxFeePerGas)\n : undefined,\n maxPriorityFeePerGas: transaction.maxPriorityFeePerGas\n ? hexToBigInt(transaction.maxPriorityFeePerGas)\n : undefined,\n });\n }\n\n async request({ method, params = [] }: RequestArguments): Promise<unknown> {\n switch (method) {\n case 'eth_chainId':\n return numberToHex(this.chain.id);\n\n case 'eth_accounts':\n case 'eth_requestAccounts':\n return [await this.getAddress()];\n\n case 'eth_sendTransaction':\n return this.sendTransaction(params[0] as LedgerTransactionRequest);\n\n case 'personal_sign': {\n const messageHex = params[0];\n if (!isHex(messageHex))\n throw new Error('personal_sign message must be a hex string');\n const account = await this.getAccount();\n return account.signMessage({ message: { raw: messageHex } });\n }\n\n case 'eth_sign': {\n const messageHex = params[1];\n if (!isHex(messageHex))\n throw new Error('eth_sign message must be a hex string');\n const account = await this.getAccount();\n return account.signMessage({ message: { raw: messageHex } });\n }\n\n case 'eth_signTypedData_v4': {\n if (typeof params[1] !== 'string')\n throw new Error('eth_signTypedData_v4 arg 1 is not a string');\n const account = await this.getAccount();\n return account.signTypedData(\n JSON.parse(params[1]) as Parameters<typeof account.signTypedData>[0],\n );\n }\n\n case 'wallet_getCapabilities': {\n // EIP-5792: an empty capability set is a valid success response, and\n // unsupported chains MUST be omitted from the response rather than\n // answered with an error.\n const requested = Array.isArray(params[1])\n ? (params[1] as unknown[])\n .filter((value): value is Hex => isHex(value))\n .map((value) => hexToNumber(value))\n : undefined;\n const chainIds = (requested ?? this.supportedChainIds).filter(\n (chainId) => this.supportedChainIds.includes(chainId),\n );\n return Object.fromEntries(\n chainIds.map((chainId) => [numberToHex(chainId), {}]),\n );\n }\n\n default: {\n // wallet_* methods (e.g. EIP-5792 wallet_sendCalls) are addressed\n // to the wallet, not the node — an HTTP RPC endpoint cannot answer\n // them, so they must not fall through.\n // MethodNotSupportedRpcError (-32004) rather than the EIP-1193 4200\n // error: viem's sendCalls experimental_fallback recognizes it by name\n // and degrades to eth_sendTransaction instead of failing.\n if (\n method.startsWith('wallet_') ||\n UNSUPPORTED_WALLET_METHODS.has(method)\n )\n throw new MethodNotSupportedRpcError(\n new Error(`The method ${method} is not supported`),\n { method },\n );\n\n const rpcRequest = this.getPublicClient().request as (\n args: RequestArguments,\n ) => Promise<unknown>;\n return rpcRequest({ method, params });\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -1,15 +1,17 @@
1
- import { Chain } from 'wagmi/chains';
2
- import type { IFrameEthereumProviderOptions } from '@ledgerhq/iframe-provider';
3
- import type { LedgerIFrameProvider } from './provider';
1
+ import { LedgerIFrameProvider } from "./provider.js";
2
+ import { IFrameEthereumProviderOptions } from "@ledgerhq/iframe-provider";
3
+ import { Chain } from "wagmi/chains";
4
+ //#region src/iframe/connector.d.ts
4
5
  export declare const idLedgerLive = "ledgerLive";
5
6
  export declare const name = "Ledger Live";
6
7
  type LedgerLiveConnectorArgs = {
7
- options?: IFrameEthereumProviderOptions;
8
- defaultChain: Chain;
8
+ options?: IFrameEthereumProviderOptions;
9
+ defaultChain: Chain;
9
10
  };
10
- export declare function ledgerLiveConnector({ options, defaultChain, }: LedgerLiveConnectorArgs): import("wagmi").CreateConnectorFn<LedgerIFrameProvider, Record<string, unknown>, Record<string, unknown>>;
11
+ export declare function ledgerLiveConnector({ options, defaultChain }: LedgerLiveConnectorArgs): import("wagmi").CreateConnectorFn<LedgerIFrameProvider, Record<string, unknown>, Record<string, unknown>>;
11
12
  export declare namespace ledgerLiveConnector {
12
- var type: string;
13
+ var type: string;
13
14
  }
15
+ //#endregion
14
16
  export {};
15
17
  //# sourceMappingURL=connector.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../../src/iframe/connector.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AACrC,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,YAAY,eAAe,CAAC;AACzC,eAAO,MAAM,IAAI,gBAAgB,CAAC;AAElC,KAAK,uBAAuB,GAAG;IAC7B,OAAO,CAAC,EAAE,6BAA6B,CAAC;IACxC,YAAY,EAAE,KAAK,CAAC;CACrB,CAAC;AAGF,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,YAAY,GACb,EAAE,uBAAuB,6GAmKzB;yBAtKe,mBAAmB"}
1
+ {"version":3,"file":"connector.d.ts","names":[],"sources":["../../src/iframe/connector.ts"],"mappings":";;;;qBAiBa;qBACA;KAER;EACH,UAAU;EACV,cAAc;;wBAIA,sBACd,SACA,gBACC,0CAAuB,kBAAA,sBAAA,yBAAA;yBAHV;MAAA"}
@@ -117,3 +117,5 @@ function ledgerLiveConnector({ options, defaultChain }) {
117
117
  }
118
118
  //#endregion
119
119
  export { idLedgerLive, ledgerLiveConnector, name };
120
+
121
+ //# sourceMappingURL=connector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connector.js","names":[],"sources":["../../src/iframe/connector.ts"],"sourcesContent":["import {\n SwitchChainNotSupportedError,\n createConnector,\n Connector,\n} from 'wagmi';\nimport {\n type Address,\n ProviderRpcError,\n UserRejectedRequestError,\n ResourceUnavailableRpcError,\n getAddress,\n numberToHex,\n} from 'viem';\nimport { Chain } from 'wagmi/chains';\nimport type { IFrameEthereumProviderOptions } from '@ledgerhq/iframe-provider';\nimport type { LedgerIFrameProvider } from './provider';\n\nexport const idLedgerLive = 'ledgerLive';\nexport const name = 'Ledger Live';\n\ntype LedgerLiveConnectorArgs = {\n options?: IFrameEthereumProviderOptions;\n defaultChain: Chain;\n};\n\nledgerLiveConnector.type = 'ledgerLive';\nexport function ledgerLiveConnector({\n options,\n defaultChain,\n}: LedgerLiveConnectorArgs) {\n const providers: Record<Chain['id'], LedgerIFrameProvider> = {};\n\n return createConnector<LedgerIFrameProvider>(({ chains, emitter }) => {\n // eventemitter3 invokes listeners with the provider as `this`, so these\n // are standalone closures rather than connector methods — `this` inside\n // a connector method used as a listener would resolve to the provider.\n const handlers = {\n onAccountsChanged: (accounts: Address[]) => {\n if (accounts.length === 0 || !accounts[0]) {\n emitter.emit('disconnect');\n handlers.detach();\n } else {\n emitter.emit('change', { accounts });\n }\n },\n onChainChanged: (chainId: number | string) => {\n emitter.emit('change', { chainId: Number(chainId) });\n },\n detach: () => {\n Object.values(providers).forEach((provider) => {\n provider.removeListener(\n 'accountsChanged',\n handlers.onAccountsChanged,\n );\n provider.removeListener('chainChanged', handlers.onChainChanged);\n });\n },\n };\n\n return {\n id: idLedgerLive,\n name,\n type: ledgerLiveConnector.type,\n\n async getProvider({ chainId } = {}) {\n const chain = chains.find((x) => x.id === chainId) ?? defaultChain;\n if (!providers[chain.id]) {\n const { LedgerIFrameProvider } = await import('./provider');\n providers[chain.id] = new LedgerIFrameProvider(options);\n }\n return providers[chain.id];\n },\n\n async connect({\n chainId,\n withCapabilities,\n }: {\n chainId?: number;\n isReconnecting?: boolean;\n withCapabilities?: boolean;\n } = {}) {\n try {\n const provider = await this.getProvider();\n\n // eventemitter3 stacks duplicate listeners, and wagmi may call\n // connect() repeatedly on a live connector — detach first so every\n // host event is forwarded exactly once.\n handlers.detach();\n provider.on('accountsChanged', handlers.onAccountsChanged);\n provider.on('chainChanged', handlers.onChainChanged);\n\n emitter.emit('message', { type: 'connecting' });\n\n const accounts = await this.getAccounts();\n let currentChainId = await this.getChainId();\n\n if (chainId && currentChainId !== chainId && this.switchChain) {\n const chain = await this.switchChain({ chainId });\n currentChainId = chain.id;\n }\n\n return {\n accounts: (withCapabilities\n ? accounts.map((address) => ({ address, capabilities: {} }))\n : accounts) as never,\n chainId: currentChainId,\n };\n } catch (error) {\n if (error instanceof Error) {\n if ((error as ProviderRpcError)?.code === 4001) {\n throw new UserRejectedRequestError(error);\n }\n throw new ResourceUnavailableRpcError(error);\n }\n\n throw error;\n }\n },\n\n async switchChain({ chainId }) {\n const provider = await this.getProvider();\n const id = numberToHex(chainId);\n\n try {\n await provider.send('wallet_switchEthereumChain', [{ chainId: id }]);\n\n return (\n chains.find((x) => x.id === chainId) ?? {\n id: chainId,\n name: `Chain ${id}`,\n network: `${id}`,\n nativeCurrency: { decimals: 18, name: 'Ether', symbol: 'ETH' },\n rpcUrls: { default: { http: [''] }, public: { http: [''] } },\n }\n );\n } catch (error) {\n const message =\n typeof error === 'string'\n ? error\n : (error as ProviderRpcError)?.message;\n if (/user rejected request/i.test(message)) {\n throw new UserRejectedRequestError(error as Error);\n }\n throw new SwitchChainNotSupportedError({\n connector: { name } as Connector, // only name is needed to generate an error message\n });\n }\n },\n\n async getAccounts() {\n const provider = await this.getProvider();\n const accounts = await provider.send<unknown[], string[]>(\n 'eth_requestAccounts',\n );\n // Checksum each address; the explicit lambda keeps Array.map's index\n // out of getAddress's second (chainId, EIP-1191) parameter.\n return accounts.map((account: string) => getAddress(account));\n },\n\n async getChainId() {\n const provider = await this.getProvider();\n const chainId: unknown = await provider.send('eth_chainId');\n return Number(chainId);\n },\n\n async isAuthorized() {\n try {\n const provider = await this.getProvider();\n const accounts = await provider.send<unknown[], string[]>(\n 'eth_accounts',\n );\n const account = accounts[0];\n return !!account;\n } catch {\n return false;\n }\n },\n\n onAccountsChanged(accounts: string[]) {\n handlers.onAccountsChanged(accounts as Address[]);\n },\n\n onChainChanged(chainId: number | string) {\n handlers.onChainChanged(chainId);\n },\n\n async disconnect() {\n handlers.detach();\n },\n\n onDisconnect() {\n emitter.emit('disconnect');\n },\n };\n });\n}\n"],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ //#region src/iframe/helpers.d.ts
1
2
  export declare const isIframe: () => boolean;
2
3
  export declare const isLedgerLive: () => boolean;
4
+ //#endregion
3
5
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/iframe/helpers.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,eACgD,CAAC;AAEtE,eAAO,MAAM,YAAY,eAWxB,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","names":[],"sources":["../../src/iframe/helpers.ts"],"mappings":";qBAAa;qBAGA"}
@@ -5,9 +5,11 @@ const isLedgerLive = () => {
5
5
  try {
6
6
  const isEmbed = !!new URLSearchParams(window.self.location.search).get("embed");
7
7
  return isIframe() && isEmbed;
8
- } catch (error) {
8
+ } catch {
9
9
  return false;
10
10
  }
11
11
  };
12
12
  //#endregion
13
13
  export { isIframe, isLedgerLive };
14
+
15
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","names":[],"sources":["../../src/iframe/helpers.ts"],"sourcesContent":["export const isIframe = () =>\n globalThis.window && globalThis.window.parent !== globalThis.window;\n\nexport const isLedgerLive = () => {\n if (typeof window === 'undefined') return false;\n\n try {\n const params = new URLSearchParams(window.self.location.search);\n const isEmbed = !!params.get('embed');\n\n return isIframe() && isEmbed;\n } catch {\n return false;\n }\n};\n"],"mappings":";AAAA,MAAa,iBACX,WAAW,UAAU,WAAW,OAAO,WAAW,WAAW;AAE/D,MAAa,qBAAqB;CAChC,IAAI,OAAO,WAAW,aAAa,OAAO;CAE1C,IAAI;EAEF,MAAM,UAAU,CAAC,CAAC,IADC,gBAAgB,OAAO,KAAK,SAAS,MACjC,CAAC,CAAC,IAAI,OAAO;EAEpC,OAAO,SAAS,KAAK;CACvB,QAAQ;EACN,OAAO;CACT;AACF"}
@@ -1,3 +1,3 @@
1
- export * from './connector';
2
- export * from './helpers';
3
- //# sourceMappingURL=index.d.ts.map
1
+ import { idLedgerLive, ledgerLiveConnector, name } from "./connector.js";
2
+ import { isIframe, isLedgerLive } from "./helpers.js";
3
+ export { idLedgerLive, isIframe, isLedgerLive, ledgerLiveConnector, name };
@@ -1,10 +1,12 @@
1
- import { IFrameEthereumProvider } from '@ledgerhq/iframe-provider';
1
+ import { IFrameEthereumProvider } from "@ledgerhq/iframe-provider";
2
+ //#region src/iframe/provider.d.ts
2
3
  interface RequestArguments {
3
- readonly method: string;
4
- readonly params?: any[];
4
+ readonly method: string;
5
+ readonly params?: unknown[];
5
6
  }
6
7
  export declare class LedgerIFrameProvider extends IFrameEthereumProvider {
7
- request({ method, params }: RequestArguments): Promise<any>;
8
+ request({ method, params }: RequestArguments): Promise<any>;
8
9
  }
10
+ //#endregion
9
11
  export {};
10
12
  //# sourceMappingURL=provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/iframe/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,UAAU,gBAAgB;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC;CACzB;AAED,qBAAa,oBAAqB,SAAQ,sBAAsB;IAC9D,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,gBAAgB;CAG7C"}
1
+ {"version":3,"file":"provider.d.ts","names":[],"sources":["../../src/iframe/provider.ts"],"mappings":";;UAEU;WACC;WACA;;qBAGE,6BAA6B;EACxC,UAAU,QAAQ,UAAU,mBAAgB"}
@@ -7,3 +7,5 @@ var LedgerIFrameProvider = class extends IFrameEthereumProvider {
7
7
  };
8
8
  //#endregion
9
9
  export { LedgerIFrameProvider };
10
+
11
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","names":[],"sources":["../../src/iframe/provider.ts"],"sourcesContent":["import { IFrameEthereumProvider } from '@ledgerhq/iframe-provider';\n\ninterface RequestArguments {\n readonly method: string;\n readonly params?: unknown[];\n}\n\nexport class LedgerIFrameProvider extends IFrameEthereumProvider {\n request({ method, params }: RequestArguments) {\n return this.send(method, params);\n }\n}\n"],"mappings":";;AAOA,IAAa,uBAAb,cAA0C,uBAAuB;CAC/D,QAAQ,EAAE,QAAQ,UAA4B;EAC5C,OAAO,KAAK,KAAK,QAAQ,MAAM;CACjC;AACF"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,8 @@
1
- export * from './iframe';
2
- export * from './hid';
3
- //# sourceMappingURL=index.d.ts.map
1
+ import { idLedgerLive, ledgerLiveConnector, name } from "./iframe/connector.js";
2
+ import { isIframe, isLedgerLive } from "./iframe/helpers.js";
3
+ import "./iframe/index.js";
4
+ import { idLedgerHid, ledgerHIDConnector } from "./hid/connector.js";
5
+ import { LS_KEY_DERIVATION_PATH } from "./hid/constants.js";
6
+ import { ClearSignUnavailableError } from "./hid/account.js";
7
+ import "./hid/index.js";
8
+ export { ClearSignUnavailableError, 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",
3
+ "version": "5.3.0-alpha.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
@@ -34,15 +34,14 @@
34
34
  "scripts": {
35
35
  "build": "yarn run -T tsdown",
36
36
  "dev": "yarn run -T tsdown --watch",
37
- "lint": "eslint --ext ts,tsx,js,mjs .",
37
+ "lint": "yarn run -T eslint .",
38
38
  "test": "vitest run",
39
- "typecheck": "tsc --noEmit"
39
+ "typecheck": "yarn run -T tsc --noEmit"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@ledgerhq/hw-transport-mocker": "6.34.7",
43
43
  "@types/w3c-web-hid": "^1.0.7",
44
44
  "build-config": "*",
45
- "eslint-config-custom": "*",
46
45
  "happy-dom": "^20.0.0",
47
46
  "viem": ">=2.50",
48
47
  "vitest": "^4.1.11",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ssr.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ssr.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/ssr.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=connector.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connector.test.d.ts","sourceRoot":"","sources":["../../../src/hid/__tests__/connector.test.ts"],"names":[],"mappings":""}
@@ -1,86 +0,0 @@
1
- import { RecordStore } from '@ledgerhq/hw-transport-mocker';
2
- import type { Address } from 'viem';
3
- import type { LedgerHQProvider } from '../provider';
4
- export declare const DERIVATION_PATH = "m/44'/60'/0'/0/0";
5
- export declare const DERIVATION_PATH_B = "m/44'/60'/1'/0/0";
6
- export declare const ADDRESS_A: Address;
7
- export declare const ADDRESS_B: Address;
8
- export declare const SIGNATURE_R: `0x${string}`;
9
- export declare const SIGNATURE_S: `0x${string}`;
10
- export declare const MESSAGE_SIGNATURE: string;
11
- export declare const APP_CONFIG = "=> e006000000\n<= 010109009000";
12
- export declare const DEVICE_LOCKED = "=> e006000000\n<= 5515";
13
- export declare const getAddressExchange: (address: Address) => string;
14
- export declare const getAddressExchangeForPathB: (address: Address) => string;
15
- export declare const PERSONAL_SIGN_MESSAGE = "reef-knot";
16
- export declare const PERSONAL_SIGN: string;
17
- export declare const LEGACY_TX: {
18
- readonly type: "legacy";
19
- readonly chainId: 1;
20
- readonly nonce: 0;
21
- readonly gasPrice: 1000000000n;
22
- readonly gas: 21000n;
23
- readonly to: `0x${string}`;
24
- readonly value: 1n;
25
- };
26
- export declare const SIGN_TX: string;
27
- export declare const FILLED_LEGACY_TX: {
28
- readonly gasPrice: 1200000000n;
29
- readonly type: "legacy";
30
- readonly chainId: 1;
31
- readonly nonce: 0;
32
- readonly gas: 21000n;
33
- readonly to: `0x${string}`;
34
- readonly value: 1n;
35
- };
36
- export declare const SIGN_TX_FILLED: string;
37
- export declare const TX_1559: {
38
- readonly chainId: 1;
39
- readonly nonce: 0;
40
- readonly maxPriorityFeePerGas: 1000000000n;
41
- readonly maxFeePerGas: 2000000000n;
42
- readonly gas: 21000n;
43
- readonly to: `0x${string}`;
44
- readonly value: 1n;
45
- };
46
- export declare const SIGN_TX_1559: string;
47
- export declare const TX_2930: {
48
- readonly chainId: 1;
49
- readonly type: "eip2930";
50
- readonly nonce: 0;
51
- readonly gasPrice: 1000000000n;
52
- readonly gas: 21000n;
53
- readonly to: `0x${string}`;
54
- readonly value: 1n;
55
- readonly accessList: readonly [];
56
- };
57
- export declare const SIGN_TX_2930: string;
58
- export declare const TYPED_DATA: {
59
- domain: {
60
- name: string;
61
- version: string;
62
- chainId: number;
63
- };
64
- types: {
65
- EIP712Domain: {
66
- name: string;
67
- type: string;
68
- }[];
69
- Mail: {
70
- name: string;
71
- type: string;
72
- }[];
73
- };
74
- primaryType: string;
75
- message: {
76
- contents: string;
77
- };
78
- };
79
- export declare const EIP712_REJECT = "=> b001000000\n<= 6d00";
80
- export declare const EIP712_HASHED: string;
81
- export declare const injectReplayer: (provider: LedgerHQProvider, ...exchanges: string[]) => RecordStore;
82
- export declare const injectReplayerWithDevice: (provider: LedgerHQProvider, device: HIDDevice, ...exchanges: string[]) => RecordStore;
83
- export declare const stubHid: () => {
84
- unplug: (device: HIDDevice) => void;
85
- };
86
- //# sourceMappingURL=fixtures.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../src/hid/__tests__/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACZ,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAOpD,eAAO,MAAM,eAAe,qBAAqB,CAAC;AAClD,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD,eAAO,MAAM,SAAS,EAAE,OAAsD,CAAC;AAC/E,eAAO,MAAM,SAAS,EAAE,OAAsD,CAAC;AAE/E,eAAO,MAAM,WAAW,eAAkC,CAAC;AAC3D,eAAO,MAAM,WAAW,eAAkC,CAAC;AAE3D,eAAO,MAAM,iBAAiB,QAA6C,CAAC;AAW5E,eAAO,MAAM,UAAU,mCAAmC,CAAC;AAG3D,eAAO,MAAM,aAAa,2BAA2B,CAAC;AAGtD,eAAO,MAAM,kBAAkB,GAAI,SAAS,OAAO,WAEa,CAAC;AAEjE,eAAO,MAAM,0BAA0B,GAAI,SAAS,OAAO,WAEK,CAAC;AAEjE,eAAO,MAAM,qBAAqB,cAAc,CAAC;AACjD,eAAO,MAAM,aAAa,QAEO,CAAC;AAIlC,eAAO,MAAM,SAAS;;;;;;;;CAQZ,CAAC;AACX,eAAO,MAAM,OAAO,QAEa,CAAC;AAIlC,eAAO,MAAM,gBAAgB;;;;;;;;CAGnB,CAAC;AACX,eAAO,MAAM,cAAc,QAEM,CAAC;AAGlC,eAAO,MAAM,OAAO;;;;;;;;CAQV,CAAC;AACX,eAAO,MAAM,YAAY,QAEQ,CAAC;AAGlC,eAAO,MAAM,OAAO;;;;;;;;;CASV,CAAC;AACX,eAAO,MAAM,YAAY,QAEQ,CAAC;AAElC,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;CAYtB,CAAC;AAIF,eAAO,MAAM,aAAa,2BAA2B,CAAC;AAEtD,eAAO,MAAM,aAAa,QAEO,CAAC;AAKlC,eAAO,MAAM,cAAc,GACzB,UAAU,gBAAgB,EAC1B,GAAG,WAAW,MAAM,EAAE,gBAOvB,CAAC;AAIF,eAAO,MAAM,wBAAwB,GACnC,UAAU,gBAAgB,EAC1B,QAAQ,SAAS,EACjB,GAAG,WAAW,MAAM,EAAE,gBAQvB,CAAC;AAIF,eAAO,MAAM,OAAO;qBAaC,SAAS;CAK7B,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=helpers.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.test.d.ts","sourceRoot":"","sources":["../../../src/hid/__tests__/helpers.test.ts"],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=provider.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"provider.test.d.ts","sourceRoot":"","sources":["../../../src/hid/__tests__/provider.test.ts"],"names":[],"mappings":""}
@@ -1,15 +0,0 @@
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;
7
- export declare const checkError: (error: any) => never;
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;
15
- //# sourceMappingURL=helpers.d.ts.map
@@ -1 +0,0 @@
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,YAIrC,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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hid/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=connector.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connector.test.d.ts","sourceRoot":"","sources":["../../../src/iframe/__tests__/connector.test.ts"],"names":[],"mappings":""}
@@ -1,27 +0,0 @@
1
- import type { MinimalEventSourceInterface, MinimalEventTargetInterface } from '@ledgerhq/iframe-provider';
2
- type JsonRpcRequest = {
3
- jsonrpc: '2.0';
4
- id: number;
5
- method: string;
6
- params?: unknown[];
7
- };
8
- export type HostHandlers = Record<string, (params: unknown[]) => unknown>;
9
- export declare class HostRpcError extends Error {
10
- readonly code: number;
11
- constructor(code: number, message: string);
12
- }
13
- export declare class FakeLedgerLive implements MinimalEventSourceInterface, MinimalEventTargetInterface {
14
- private readonly handlers;
15
- readonly calls: {
16
- method: string;
17
- params: unknown[];
18
- }[];
19
- private listeners;
20
- constructor(handlers: HostHandlers);
21
- addEventListener(_type: 'message', listener: (event: MessageEvent) => void): void;
22
- postMessage(message: JsonRpcRequest): void;
23
- emitEvent(method: string, params: unknown[]): void;
24
- private dispatch;
25
- }
26
- export {};
27
- //# sourceMappingURL=fake-ledger-live.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fake-ledger-live.d.ts","sourceRoot":"","sources":["../../../src/iframe/__tests__/fake-ledger-live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,2BAA2B,EAC5B,MAAM,2BAA2B,CAAC;AAEnC,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,CAAC;AAG1E,qBAAa,YAAa,SAAQ,KAAK;aAEnB,IAAI,EAAE,MAAM;gBAAZ,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAIlB;AAKD,qBAAa,cACX,YAAW,2BAA2B,EAAE,2BAA2B;IAMvD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAJrC,QAAQ,CAAC,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,EAAE,CAAA;KAAE,EAAE,CAAM;IAE7D,OAAO,CAAC,SAAS,CAA4C;gBAEhC,QAAQ,EAAE,YAAY;IAEnD,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI;IAI1E,WAAW,CAAC,OAAO,EAAE,cAAc;IA0BnC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IAI3C,OAAO,CAAC,QAAQ;CAKjB"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=helpers.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.test.d.ts","sourceRoot":"","sources":["../../../src/iframe/__tests__/helpers.test.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/iframe/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,OAAO,CAAC"}