@swapkit/wallet-hardware 4.8.3 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/chunk-9jd3dhjv.js +4 -0
  2. package/dist/chunk-9jd3dhjv.js.map +10 -0
  3. package/dist/chunk-m08x6an5.js +4 -0
  4. package/dist/chunk-m08x6an5.js.map +10 -0
  5. package/dist/ledger/index.cjs +3 -3
  6. package/dist/ledger/index.cjs.map +13 -13
  7. package/dist/ledger/index.js +3 -3
  8. package/dist/ledger/index.js.map +13 -13
  9. package/dist/types/ledger/clients/cosmos.d.ts +2 -1
  10. package/dist/types/ledger/clients/cosmos.d.ts.map +1 -1
  11. package/dist/types/ledger/clients/evm.d.ts +5 -1
  12. package/dist/types/ledger/clients/evm.d.ts.map +1 -1
  13. package/dist/types/ledger/clients/near.d.ts +2 -1
  14. package/dist/types/ledger/clients/near.d.ts.map +1 -1
  15. package/dist/types/ledger/clients/sui.d.ts +4 -2
  16. package/dist/types/ledger/clients/sui.d.ts.map +1 -1
  17. package/dist/types/ledger/clients/thorchain/index.d.ts +2 -1
  18. package/dist/types/ledger/clients/thorchain/index.d.ts.map +1 -1
  19. package/dist/types/ledger/clients/tron.d.ts +4 -2
  20. package/dist/types/ledger/clients/tron.d.ts.map +1 -1
  21. package/dist/types/ledger/clients/utxo-psbt.d.ts +3 -2
  22. package/dist/types/ledger/clients/utxo-psbt.d.ts.map +1 -1
  23. package/dist/types/ledger/clients/utxo.d.ts +7 -6
  24. package/dist/types/ledger/clients/utxo.d.ts.map +1 -1
  25. package/dist/types/ledger/clients/xrp.d.ts +2 -1
  26. package/dist/types/ledger/clients/xrp.d.ts.map +1 -1
  27. package/dist/types/ledger/helpers/getLedgerClient.d.ts +3 -1
  28. package/dist/types/ledger/helpers/getLedgerClient.d.ts.map +1 -1
  29. package/dist/types/ledger/index.d.ts +13 -1
  30. package/dist/types/ledger/index.d.ts.map +1 -1
  31. package/dist/types/ledger/interfaces/CosmosLedgerInterface.d.ts +3 -0
  32. package/dist/types/ledger/interfaces/CosmosLedgerInterface.d.ts.map +1 -1
  33. package/package.json +5 -5
  34. package/src/ledger/clients/cosmos.ts +3 -2
  35. package/src/ledger/clients/evm.ts +13 -4
  36. package/src/ledger/clients/near.ts +3 -2
  37. package/src/ledger/clients/sui.ts +7 -3
  38. package/src/ledger/clients/thorchain/index.ts +3 -2
  39. package/src/ledger/clients/tron.ts +7 -3
  40. package/src/ledger/clients/utxo-psbt.ts +21 -17
  41. package/src/ledger/clients/utxo.ts +21 -17
  42. package/src/ledger/clients/xrp.ts +2 -2
  43. package/src/ledger/helpers/getLedgerClient.ts +20 -13
  44. package/src/ledger/index.ts +34 -13
  45. package/src/ledger/interfaces/CosmosLedgerInterface.ts +14 -1
  46. package/dist/chunk-3zf2pqfd.js +0 -4
  47. package/dist/chunk-3zf2pqfd.js.map +0 -10
  48. package/dist/chunk-x85da57j.js +0 -4
  49. package/dist/chunk-x85da57j.js.map +0 -10
@@ -1,5 +1,6 @@
1
1
  import type BitcoinApp from "@ledgerhq/hw-app-btc";
2
2
  import type { CreateTransactionArg } from "@ledgerhq/hw-app-btc/lib-es/createTransaction";
3
+ import type Transport from "@ledgerhq/hw-transport";
3
4
  import { hex } from "@scure/base";
4
5
  import { type DerivationPathArray, derivationPathToString, getWalletFormatFor, SwapKitError } from "@swapkit/helpers";
5
6
  import type { UTXOType } from "@swapkit/toolboxes/utxo";
@@ -101,27 +102,30 @@ const BaseLedgerUTXO = ({
101
102
  chain: "bitcoin-cash" | "bitcoin" | "litecoin" | "dogecoin" | "dash" | "zcash";
102
103
  additionalSignParams?: Partial<CreateTransactionArg>;
103
104
  }) => {
104
- let btcApp: InstanceType<typeof BitcoinApp>;
105
- let transport: any = null;
106
-
107
- async function checkBtcAppAndCreateTransportWebUSB(checkBtcApp = true) {
108
- if (checkBtcApp && !btcApp) {
109
- new SwapKitError("wallet_ledger_connection_error", {
110
- message: `Ledger connection failed:\n${JSON.stringify({ btcApp, checkBtcApp })}`,
111
- });
112
- }
105
+ return (derivationPathArray?: DerivationPathArray | string, injectedTransport?: Transport) => {
106
+ // Per-call state each BitcoinLedger/LitecoinLedger/... invocation has its own
107
+ // transport + btcApp so different consumers (e.g. concurrent MCP sessions) cannot
108
+ // cross-contaminate each other's Ledger device handle.
109
+ let btcApp: InstanceType<typeof BitcoinApp>;
110
+ let transport: any = null;
111
+
112
+ async function checkBtcAppAndCreateTransportWebUSB(checkBtcApp = true) {
113
+ if (checkBtcApp && !btcApp) {
114
+ new SwapKitError("wallet_ledger_connection_error", {
115
+ message: `Ledger connection failed:\n${JSON.stringify({ btcApp, checkBtcApp })}`,
116
+ });
117
+ }
113
118
 
114
- transport ||= await getLedgerTransport();
115
- }
119
+ transport ||= injectedTransport ?? (await getLedgerTransport());
120
+ }
116
121
 
117
- async function createTransportWebUSB() {
118
- transport = await getLedgerTransport();
119
- const BitcoinApp = (await import("@ledgerhq/hw-app-btc")).default;
122
+ async function createTransportWebUSB() {
123
+ transport = injectedTransport ?? (await getLedgerTransport());
124
+ const BitcoinApp = (await import("@ledgerhq/hw-app-btc")).default;
120
125
 
121
- btcApp = new BitcoinApp({ currency: chain, transport });
122
- }
126
+ btcApp = new BitcoinApp({ currency: chain, transport });
127
+ }
123
128
 
124
- return (derivationPathArray?: DerivationPathArray | string) => {
125
129
  const derivationPath =
126
130
  typeof derivationPathArray === "string"
127
131
  ? derivationPathArray
@@ -22,9 +22,9 @@ function establishConnection(transport: Transport) {
22
22
  return new Xrp(transport);
23
23
  }
24
24
 
25
- export const XRPLedger = async (derivationPath?: DerivationPathArray) => {
25
+ export const XRPLedger = async (derivationPath?: DerivationPathArray, injectedTransport?: Transport) => {
26
26
  const path = derivationPathToString(derivationPath || NetworkDerivationPath[Chain.Ripple]);
27
- const transport = await getLedgerTransport();
27
+ const transport = injectedTransport ?? (await getLedgerTransport());
28
28
  const xrpInstance = establishConnection(transport);
29
29
 
30
30
  const { address, publicKey } = await xrpInstance.getAddress(path);
@@ -1,3 +1,4 @@
1
+ import type Transport from "@ledgerhq/hw-transport";
1
2
  import { Chain, type DerivationPathArray, type EVMChain, SwapKitError, WalletOption } from "@swapkit/helpers";
2
3
 
3
4
  import { CosmosLedger } from "../clients/cosmos";
@@ -61,29 +62,35 @@ type LedgerSupportedChain = keyof LedgerSignerMap;
61
62
  export const getLedgerClient = async <T extends LedgerSupportedChain>({
62
63
  chain,
63
64
  derivationPath,
65
+ transport,
64
66
  }: {
65
67
  chain: T;
66
68
  derivationPath?: DerivationPathArray;
69
+ transport?: Transport;
67
70
  }): Promise<LedgerSignerMap[T]> => {
68
71
  const { match } = await import("ts-pattern");
69
72
 
70
73
  return (
71
74
  match(chain as LedgerSupportedChain)
72
75
  .returnType<Promise<LedgerSignerMap[T]>>()
73
- .with(Chain.THORChain, () => Promise.resolve(new THORChainLedger(derivationPath) as LedgerSignerMap[T]))
74
- .with(Chain.Cosmos, () => Promise.resolve(new CosmosLedger(derivationPath) as LedgerSignerMap[T]))
75
- .with(Chain.Bitcoin, () => Promise.resolve(BitcoinLedger(derivationPath) as LedgerSignerMap[T]))
76
- .with(Chain.BitcoinCash, () => Promise.resolve(BitcoinCashLedger(derivationPath) as LedgerSignerMap[T]))
77
- .with(Chain.Dash, () => Promise.resolve(DashLedger(derivationPath) as LedgerSignerMap[T]))
78
- .with(Chain.Dogecoin, () => Promise.resolve(DogecoinLedger(derivationPath) as LedgerSignerMap[T]))
79
- .with(Chain.Litecoin, () => Promise.resolve(LitecoinLedger(derivationPath) as LedgerSignerMap[T]))
80
- .with(Chain.Zcash, () => Promise.resolve(ZcashLedger(derivationPath) as LedgerSignerMap[T]))
81
- .with(Chain.Ripple, () => Promise.resolve(XRPLedger(derivationPath) as LedgerSignerMap[T]))
82
- .with(Chain.Tron, () => Promise.resolve(TronLedger(derivationPath) as LedgerSignerMap[T]))
83
- .with(Chain.Sui, () => Promise.resolve(SuiLedger(derivationPath) as LedgerSignerMap[T]))
76
+ .with(Chain.THORChain, () =>
77
+ Promise.resolve(new THORChainLedger(derivationPath, transport) as LedgerSignerMap[T]),
78
+ )
79
+ .with(Chain.Cosmos, () => Promise.resolve(new CosmosLedger(derivationPath, transport) as LedgerSignerMap[T]))
80
+ .with(Chain.Bitcoin, () => Promise.resolve(BitcoinLedger(derivationPath, transport) as LedgerSignerMap[T]))
81
+ .with(Chain.BitcoinCash, () =>
82
+ Promise.resolve(BitcoinCashLedger(derivationPath, transport) as LedgerSignerMap[T]),
83
+ )
84
+ .with(Chain.Dash, () => Promise.resolve(DashLedger(derivationPath, transport) as LedgerSignerMap[T]))
85
+ .with(Chain.Dogecoin, () => Promise.resolve(DogecoinLedger(derivationPath, transport) as LedgerSignerMap[T]))
86
+ .with(Chain.Litecoin, () => Promise.resolve(LitecoinLedger(derivationPath, transport) as LedgerSignerMap[T]))
87
+ .with(Chain.Zcash, () => Promise.resolve(ZcashLedger(derivationPath, transport) as LedgerSignerMap[T]))
88
+ .with(Chain.Ripple, () => Promise.resolve(XRPLedger(derivationPath, transport) as LedgerSignerMap[T]))
89
+ .with(Chain.Tron, () => Promise.resolve(TronLedger(derivationPath, transport) as LedgerSignerMap[T]))
90
+ .with(Chain.Sui, () => Promise.resolve(SuiLedger(derivationPath, transport) as LedgerSignerMap[T]))
84
91
  // @ts-expect-error
85
92
  .with(Chain.Near, () => {
86
- return Promise.resolve(getNearLedgerClient(derivationPath));
93
+ return Promise.resolve(getNearLedgerClient(derivationPath, transport));
87
94
  })
88
95
  .with(
89
96
  Chain.Arbitrum,
@@ -100,7 +107,7 @@ export const getLedgerClient = async <T extends LedgerSupportedChain>({
100
107
  Chain.XLayer,
101
108
  async () => {
102
109
  const { getProvider } = await import("@swapkit/toolboxes/evm");
103
- const params = { derivationPath, provider: await getProvider(chain as EVMChain) };
110
+ const params = { derivationPath, provider: await getProvider(chain as EVMChain), transport };
104
111
 
105
112
  return match(chain as Chain)
106
113
  .with(Chain.BinanceSmartChain, () => BinanceSmartChainLedger(params) as LedgerSignerMap[T])
@@ -1,3 +1,4 @@
1
+ import type Transport from "@ledgerhq/hw-transport";
1
2
  import {
2
3
  type AssetValue,
3
4
  Chain,
@@ -30,15 +31,29 @@ import type { Transaction } from "@swapkit/utxo-signer";
30
31
  import { createWallet, getWalletSupportedChains } from "@swapkit/wallet-core";
31
32
  import { getLedgerAddress, getLedgerClient } from "./helpers";
32
33
 
34
+ /**
35
+ * Options passed to `connectLedger` at call time.
36
+ *
37
+ * When `transport` is supplied, the consumer opens and owns its lifecycle —
38
+ * wallet-hardware will use that exact instance for every per-chain Ledger
39
+ * client and will NOT recreate it on `forceReconnect`. When omitted, the
40
+ * default browser flow (WebHID / WebUSB via `navigator.usb`) is used.
41
+ */
42
+ export type ConnectLedgerOptions = { transport?: Transport };
43
+
33
44
  export const ledgerWallet = createWallet({
34
45
  connect: ({ addChain, supportedChains, walletType }) =>
35
- async function connectLedger(chains: Chain[], derivationPath?: DerivationPathArray) {
46
+ async function connectLedger(
47
+ chains: Chain[],
48
+ derivationPath?: DerivationPathArray,
49
+ { transport }: ConnectLedgerOptions = {},
50
+ ) {
36
51
  const [chain] = filterSupportedChains({ chains, supportedChains, walletType });
37
52
 
38
53
  if (!chain) return false;
39
54
 
40
55
  const resolvedPath = derivationPath ?? (NetworkDerivationPath[chain] as DerivationPathArray | undefined);
41
- const walletMethods = await getWalletMethods({ chain, derivationPath: resolvedPath });
56
+ const walletMethods = await getWalletMethods({ chain, derivationPath: resolvedPath, transport });
42
57
 
43
58
  addChain({ ...walletMethods, chain, walletType: WalletOption.LEDGER });
44
59
 
@@ -137,7 +152,11 @@ function stringifyKeysInOrder(data: any) {
137
152
  return JSON.stringify(recursivelyOrderKeys(data));
138
153
  }
139
154
 
140
- async function getWalletMethods({ chain, derivationPath }: { chain: Chain; derivationPath?: DerivationPathArray }) {
155
+ async function getWalletMethods({
156
+ chain,
157
+ derivationPath,
158
+ transport,
159
+ }: ConnectLedgerOptions & { chain: Chain; derivationPath?: DerivationPathArray }) {
141
160
  switch (chain) {
142
161
  case Chain.BitcoinCash:
143
162
  case Chain.Bitcoin:
@@ -148,7 +167,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
148
167
  const { getUtxoToolbox } = await import("@swapkit/toolboxes/utxo");
149
168
  const utxoChain = chain as UTXOChain;
150
169
 
151
- const signer = await getLedgerClient({ chain, derivationPath });
170
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
152
171
 
153
172
  const address = await getLedgerAddress({ chain, ledgerClient: signer });
154
173
 
@@ -163,7 +182,9 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
163
182
  if (chain === Chain.Bitcoin || chain === Chain.Litecoin) {
164
183
  const { BitcoinPsbtLedger, LitecoinPsbtLedger } = await import("./clients/utxo-psbt");
165
184
  const psbtClient =
166
- chain === Chain.Bitcoin ? BitcoinPsbtLedger(derivationPath) : LitecoinPsbtLedger(derivationPath);
185
+ chain === Chain.Bitcoin
186
+ ? BitcoinPsbtLedger(derivationPath, transport)
187
+ : LitecoinPsbtLedger(derivationPath, transport);
167
188
  toolboxSigner = { getAddress: psbtClient.getAddress, signTransaction: psbtClient.signTransaction };
168
189
  } else if (chain === Chain.BitcoinCash || chain === Chain.Dogecoin || chain === Chain.Dash) {
169
190
  const { createLegacyPsbtSigner } = await import("./clients/utxo-legacy-adapter");
@@ -221,7 +242,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
221
242
  try {
222
243
  const fullPath = getUTXOAddressPath({ accountIndex, chain: utxoChain, change, derivationPath, index });
223
244
 
224
- const indexedSigner = await getLedgerClient({ chain: utxoChain, derivationPath: fullPath });
245
+ const indexedSigner = await getLedgerClient({ chain: utxoChain, derivationPath: fullPath, transport });
225
246
  const derivedAddress = await getLedgerAddress({ chain: utxoChain, ledgerClient: indexedSigner });
226
247
 
227
248
  return {
@@ -377,7 +398,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
377
398
  case Chain.Monad:
378
399
  case Chain.XLayer: {
379
400
  const { getEvmToolboxAsync } = await import("@swapkit/toolboxes/evm");
380
- const signer = await getLedgerClient({ chain, derivationPath });
401
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
381
402
  const address = await getLedgerAddress({ chain, ledgerClient: signer });
382
403
  const toolbox = await getEvmToolboxAsync(chain, { signer });
383
404
 
@@ -388,7 +409,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
388
409
  const { createSigningStargateClient, getMsgSendDenom, getCosmosToolbox } = await import(
389
410
  "@swapkit/toolboxes/cosmos"
390
411
  );
391
- const signer = await getLedgerClient({ chain, derivationPath });
412
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
392
413
  const address = await getLedgerAddress({ chain, ledgerClient: signer });
393
414
  const toolbox = await getCosmosToolbox(Chain.Cosmos, { signer });
394
415
 
@@ -438,7 +459,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
438
459
  parseAminoMessageForDirectSigning,
439
460
  } = await import("@swapkit/toolboxes/cosmos");
440
461
  const toolbox = getCosmosToolbox(chain);
441
- const signer = await getLedgerClient({ chain, derivationPath });
462
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
442
463
  const address = await getLedgerAddress({ chain, ledgerClient: signer });
443
464
 
444
465
  const fee = getDefaultChainFee(chain);
@@ -506,7 +527,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
506
527
 
507
528
  case Chain.Near: {
508
529
  const { getNearToolbox } = await import("@swapkit/toolboxes/near");
509
- const signer = await getLedgerClient({ chain, derivationPath });
530
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
510
531
  const accountId = await signer.getAddress();
511
532
  const toolbox = getNearToolbox({ signer });
512
533
 
@@ -515,7 +536,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
515
536
 
516
537
  case Chain.Ripple: {
517
538
  const { getRippleToolbox } = await import("@swapkit/toolboxes/ripple");
518
- const signer = await getLedgerClient({ chain, derivationPath });
539
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
519
540
  const address = signer.getAddress();
520
541
  const toolbox = getRippleToolbox({ signer });
521
542
 
@@ -524,7 +545,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
524
545
 
525
546
  case Chain.Tron: {
526
547
  const { getTronToolbox } = await import("@swapkit/toolboxes/tron");
527
- const signer = await getLedgerClient({ chain, derivationPath });
548
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
528
549
  const address = await getLedgerAddress({ chain, ledgerClient: signer });
529
550
  const toolbox = getTronToolbox({ signer });
530
551
 
@@ -533,7 +554,7 @@ async function getWalletMethods({ chain, derivationPath }: { chain: Chain; deriv
533
554
 
534
555
  case Chain.Sui: {
535
556
  const { getSuiToolbox } = await import("@swapkit/toolboxes/sui");
536
- const signer = await getLedgerClient({ chain, derivationPath });
557
+ const signer = await getLedgerClient({ chain, derivationPath, transport });
537
558
  const address = await getLedgerAddress({ chain, ledgerClient: signer });
538
559
  const toolbox = getSuiToolbox({ signer });
539
560
 
@@ -1,3 +1,4 @@
1
+ import type Transport from "@ledgerhq/hw-transport";
1
2
  import { type DerivationPathArray, LedgerErrorCode, NetworkDerivationPath, SwapKitError } from "@swapkit/helpers";
2
3
 
3
4
  import { THORChainApp } from "../clients/thorchain/lib";
@@ -10,11 +11,23 @@ export abstract class CosmosLedgerInterface {
10
11
  ledgerApp: any;
11
12
  chain: "thor" | "cosmos" = "thor";
12
13
 
14
+ private readonly injectedTransport?: Transport;
15
+
16
+ constructor(transport?: Transport) {
17
+ this.injectedTransport = transport;
18
+ if (transport) this.transport = transport;
19
+ }
20
+
13
21
  checkOrCreateTransportAndLedger = async (forceReconnect = false) => {
14
22
  if (!forceReconnect && this.transport && this.ledgerApp) return;
15
23
 
16
24
  try {
17
- this.transport = forceReconnect || !this.transport ? await getLedgerTransport() : this.transport;
25
+ // Consumer owns the lifecycle of an injected transport, so forceReconnect
26
+ // only refreshes ledgerApp — the transport itself stays as passed in.
27
+ const needsNewTransport = !this.transport || (forceReconnect && !this.injectedTransport);
28
+ if (needsNewTransport) {
29
+ this.transport = this.injectedTransport ?? (await getLedgerTransport());
30
+ }
18
31
 
19
32
  switch (this.chain) {
20
33
  case "thor": {
@@ -1,4 +0,0 @@
1
- import{c as K}from"./chunk-3yr76n9s.js";import{d as W}from"./chunk-n05bv2n5.js";import{base64 as A}from"@scure/base";import{HDKey as x}from"@scure/bip32";import{derivationPathToString as f,getWalletFormatFor as m,SwapKitError as E}from"@swapkit/helpers";function y(q){switch(q){case"bech32":return"wpkh(@0/**)";case"p2sh":return"sh(wpkh(@0/**))";case"legacy":return"pkh(@0/**)";default:return"wpkh(@0/**)"}}function b(q){return typeof q==="string"?q:f(q)}function P(q){return q.replace(/^m\//,"").split("/").filter(Boolean).map((J)=>{let R=J.endsWith("'"),M=Number.parseInt(R?J.slice(0,-1):J,10);return R?(M|2147483648)>>>0:M})}var w=({chain:q})=>{let J,R;async function M(){if(!J){let V=await K(),{AppClient:Q}=await import("ledger-bitcoin");J=new Q(V)}return J}async function B(){if(!R)R=await(await M()).getMasterFingerprint();return R}return(V)=>{let Q=V?b(V):"84'/0'/0'/0/0",_=Q.split("/").slice(0,3).join("/"),I=Q.split("/").slice(3),N=Number(I[0]??0),O=Number(I[1]??0),X=m(Q),k=y(X),Z,$;async function H(){let j=await M(),G=await B();if(!Z)Z=await j.getExtendedPubkey(`m/${_}`);let{DefaultWalletPolicy:z}=await import("ledger-bitcoin"),D=new z(k,`[${G}/${_}]${Z}`);return{app:j,fpr:G,policy:D,xpub:Z}}async function S(){if(!$){let{xpub:j}=await H(),z=x.fromExtendedKey(j).derive(`m/${N}/${O}`);if(!z.publicKey)throw new E("wallet_ledger_get_address_error",{message:`Cannot derive leaf pubkey for ${q}`});$=z.publicKey}return $}return{connect:async()=>{await M()},getAddress:async()=>{let{app:j,policy:G}=await H(),z=await j.getWalletAddress(G,null,N,O,!1);if(!z)throw new E("wallet_ledger_get_address_error",{message:`Cannot get ${q} address from ledger derivation path: ${Q}`});return z},getExtendedPublicKey:async(j=`m/${_}`)=>{return(await M()).getExtendedPubkey(j)},signTransaction:async(j)=>{let{app:G,policy:z,fpr:D}=await H(),T=Number.parseInt(D,16)>>>0,C=P(Q),F=await S();for(let Y=0;Y<j.inputsLength;Y++)j.updateInput(Y,{bip32Derivation:[[F,{fingerprint:T,path:C}]]});let L=A.encode(j.toPSBT(0)),v=await G.signPsbt(L,z,null);for(let[Y,U]of v)j.updateInput(Y,{partialSig:[[new Uint8Array(U.pubkey),new Uint8Array(U.signature)]]});return j.finalize(),j}}}},o=w({chain:"bitcoin"}),d=w({chain:"litecoin"});export{d as LitecoinPsbtLedger,o as BitcoinPsbtLedger};
2
-
3
- //# debugId=27457FA5B66F8C7364756E2164756E21
4
- //# sourceMappingURL=chunk-3zf2pqfd.js.map
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/ledger/clients/utxo-psbt.ts"],
4
- "sourcesContent": [
5
- "import { base64 } from \"@scure/base\";\nimport { HDKey } from \"@scure/bip32\";\nimport { type DerivationPathArray, derivationPathToString, getWalletFormatFor, SwapKitError } from \"@swapkit/helpers\";\nimport type { Transaction } from \"@swapkit/utxo-signer\";\n\nimport { getLedgerTransport } from \"../helpers/getLedgerTransport\";\n\ntype SupportedCoin = \"bitcoin\" | \"litecoin\";\n\ntype DefaultDescriptorTemplate = \"wpkh(@0/**)\" | \"tr(@0/**)\" | \"sh(wpkh(@0/**))\" | \"pkh(@0/**)\";\n\nfunction templateForFormat(format: ReturnType<typeof getWalletFormatFor>): DefaultDescriptorTemplate {\n switch (format) {\n case \"bech32\":\n return \"wpkh(@0/**)\";\n case \"p2sh\":\n return \"sh(wpkh(@0/**))\";\n case \"legacy\":\n return \"pkh(@0/**)\";\n default:\n return \"wpkh(@0/**)\";\n }\n}\n\nfunction pathToString(path: DerivationPathArray | string): string {\n return typeof path === \"string\" ? path : derivationPathToString(path);\n}\n\nfunction pathToNumberArray(path: string): number[] {\n return path\n .replace(/^m\\//, \"\")\n .split(\"/\")\n .filter(Boolean)\n .map((p) => {\n const hardened = p.endsWith(\"'\");\n const num = Number.parseInt(hardened ? p.slice(0, -1) : p, 10);\n return hardened ? (num | 0x80000000) >>> 0 : num;\n });\n}\n\nconst BaseLedgerPsbtUTXO = ({ chain }: { chain: SupportedCoin }) => {\n let appClient: import(\"ledger-bitcoin\").AppClient | undefined;\n let masterFingerprint: string | undefined;\n\n async function getAppClient() {\n if (!appClient) {\n const transport = await getLedgerTransport();\n const { AppClient } = await import(\"ledger-bitcoin\");\n appClient = new AppClient(transport);\n }\n return appClient;\n }\n\n async function getFingerprint() {\n if (!masterFingerprint) {\n const app = await getAppClient();\n masterFingerprint = await app.getMasterFingerprint();\n }\n return masterFingerprint;\n }\n\n return (derivationPathArray?: DerivationPathArray | string) => {\n // Single-address account: change == index == 0 by default.\n const derivationPath = derivationPathArray ? pathToString(derivationPathArray) : \"84'/0'/0'/0/0\";\n const accountPath = derivationPath.split(\"/\").slice(0, 3).join(\"/\");\n const leafSegments = derivationPath.split(\"/\").slice(3);\n const change = Number(leafSegments[0] ?? 0);\n const addressIndex = Number(leafSegments[1] ?? 0);\n const format = getWalletFormatFor(derivationPath);\n const template = templateForFormat(format);\n\n let cachedAccountXpub: string | undefined;\n let cachedLeafPubkey: Uint8Array | undefined;\n\n async function buildPolicy() {\n const app = await getAppClient();\n const fpr = await getFingerprint();\n if (!cachedAccountXpub) {\n cachedAccountXpub = await app.getExtendedPubkey(`m/${accountPath}`);\n }\n const { DefaultWalletPolicy } = await import(\"ledger-bitcoin\");\n const policy = new DefaultWalletPolicy(template, `[${fpr}/${accountPath}]${cachedAccountXpub}`);\n return { app, fpr, policy, xpub: cachedAccountXpub };\n }\n\n async function getLeafPubkey() {\n if (!cachedLeafPubkey) {\n const { xpub } = await buildPolicy();\n const accountKey = HDKey.fromExtendedKey(xpub);\n const leaf = accountKey.derive(`m/${change}/${addressIndex}`);\n if (!leaf.publicKey) {\n throw new SwapKitError(\"wallet_ledger_get_address_error\", {\n message: `Cannot derive leaf pubkey for ${chain}`,\n });\n }\n cachedLeafPubkey = leaf.publicKey;\n }\n return cachedLeafPubkey;\n }\n\n return {\n connect: async () => {\n await getAppClient();\n },\n getAddress: async () => {\n const { app, policy } = await buildPolicy();\n const address = await app.getWalletAddress(policy, null, change, addressIndex, false);\n if (!address) {\n throw new SwapKitError(\"wallet_ledger_get_address_error\", {\n message: `Cannot get ${chain} address from ledger derivation path: ${derivationPath}`,\n });\n }\n return address;\n },\n getExtendedPublicKey: async (path = `m/${accountPath}`) => {\n const app = await getAppClient();\n return app.getExtendedPubkey(path);\n },\n signTransaction: async (tx: Transaction): Promise<Transaction> => {\n const { app, policy, fpr } = await buildPolicy();\n const fingerprintBE = Number.parseInt(fpr, 16) >>> 0;\n const pathNumbers = pathToNumberArray(derivationPath);\n const leafPubkey = await getLeafPubkey();\n\n // Single-address account: every input is owned by the same key + path.\n for (let i = 0; i < tx.inputsLength; i++) {\n tx.updateInput(i, { bip32Derivation: [[leafPubkey, { fingerprint: fingerprintBE, path: pathNumbers }]] });\n }\n\n const psbtB64 = base64.encode(tx.toPSBT(0));\n const sigs = await app.signPsbt(psbtB64, policy, null);\n\n for (const [idx, partial] of sigs) {\n tx.updateInput(idx, { partialSig: [[new Uint8Array(partial.pubkey), new Uint8Array(partial.signature)]] });\n }\n\n tx.finalize();\n return tx;\n },\n };\n };\n};\n\nexport const BitcoinPsbtLedger = BaseLedgerPsbtUTXO({ chain: \"bitcoin\" });\nexport const LitecoinPsbtLedger = BaseLedgerPsbtUTXO({ chain: \"litecoin\" });\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "27457FA5B66F8C7364756E2164756E21",
9
- "names": []
10
- }
@@ -1,4 +0,0 @@
1
- var K=require("@scure/base"),w=require("@scure/bip32"),R=require("@swapkit/helpers");function x(q){switch(q){case"bech32":return"wpkh(@0/**)";case"p2sh":return"sh(wpkh(@0/**))";case"legacy":return"pkh(@0/**)";default:return"wpkh(@0/**)"}}function f(q){return typeof q==="string"?q:R.derivationPathToString(q)}function m(q){return q.replace(/^m\//,"").split("/").filter(Boolean).map((J)=>{let V=J.endsWith("'"),M=Number.parseInt(V?J.slice(0,-1):J,10);return V?(M|2147483648)>>>0:M})}var B=({chain:q})=>{let J,V;async function M(){if(!J){let Y=await E(),{AppClient:Q}=await import("ledger-bitcoin");J=new Q(Y)}return J}async function X(){if(!V)V=await(await M()).getMasterFingerprint();return V}return(Y)=>{let Q=Y?f(Y):"84'/0'/0'/0/0",$=Q.split("/").slice(0,3).join("/"),N=Q.split("/").slice(3),O=Number(N[0]??0),U=Number(N[1]??0),k=R.getWalletFormatFor(Q),S=x(k),_,H;async function D(){let j=await M(),G=await X();if(!_)_=await j.getExtendedPubkey(`m/${$}`);let{DefaultWalletPolicy:z}=await import("ledger-bitcoin"),I=new z(S,`[${G}/${$}]${_}`);return{app:j,fpr:G,policy:I,xpub:_}}async function T(){if(!H){let{xpub:j}=await D(),z=w.HDKey.fromExtendedKey(j).derive(`m/${O}/${U}`);if(!z.publicKey)throw new R.SwapKitError("wallet_ledger_get_address_error",{message:`Cannot derive leaf pubkey for ${q}`});H=z.publicKey}return H}return{connect:async()=>{await M()},getAddress:async()=>{let{app:j,policy:G}=await D(),z=await j.getWalletAddress(G,null,O,U,!1);if(!z)throw new R.SwapKitError("wallet_ledger_get_address_error",{message:`Cannot get ${q} address from ledger derivation path: ${Q}`});return z},getExtendedPublicKey:async(j=`m/${$}`)=>{return(await M()).getExtendedPubkey(j)},signTransaction:async(j)=>{let{app:G,policy:z,fpr:I}=await D(),C=Number.parseInt(I,16)>>>0,F=m(Q),L=await T();for(let Z=0;Z<j.inputsLength;Z++)j.updateInput(Z,{bip32Derivation:[[L,{fingerprint:C,path:F}]]});let v=K.base64.encode(j.toPSBT(0)),A=await G.signPsbt(v,z,null);for(let[Z,W]of A)j.updateInput(Z,{partialSig:[[new Uint8Array(W.pubkey),new Uint8Array(W.signature)]]});return j.finalize(),j}}}},b=B({chain:"bitcoin"}),P=B({chain:"litecoin"});
2
-
3
- //# debugId=0B3F2685533B86ED64756E2164756E21
4
- //# sourceMappingURL=chunk-x85da57j.js.map
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/ledger/clients/utxo-psbt.ts"],
4
- "sourcesContent": [
5
- "import { base64 } from \"@scure/base\";\nimport { HDKey } from \"@scure/bip32\";\nimport { type DerivationPathArray, derivationPathToString, getWalletFormatFor, SwapKitError } from \"@swapkit/helpers\";\nimport type { Transaction } from \"@swapkit/utxo-signer\";\n\nimport { getLedgerTransport } from \"../helpers/getLedgerTransport\";\n\ntype SupportedCoin = \"bitcoin\" | \"litecoin\";\n\ntype DefaultDescriptorTemplate = \"wpkh(@0/**)\" | \"tr(@0/**)\" | \"sh(wpkh(@0/**))\" | \"pkh(@0/**)\";\n\nfunction templateForFormat(format: ReturnType<typeof getWalletFormatFor>): DefaultDescriptorTemplate {\n switch (format) {\n case \"bech32\":\n return \"wpkh(@0/**)\";\n case \"p2sh\":\n return \"sh(wpkh(@0/**))\";\n case \"legacy\":\n return \"pkh(@0/**)\";\n default:\n return \"wpkh(@0/**)\";\n }\n}\n\nfunction pathToString(path: DerivationPathArray | string): string {\n return typeof path === \"string\" ? path : derivationPathToString(path);\n}\n\nfunction pathToNumberArray(path: string): number[] {\n return path\n .replace(/^m\\//, \"\")\n .split(\"/\")\n .filter(Boolean)\n .map((p) => {\n const hardened = p.endsWith(\"'\");\n const num = Number.parseInt(hardened ? p.slice(0, -1) : p, 10);\n return hardened ? (num | 0x80000000) >>> 0 : num;\n });\n}\n\nconst BaseLedgerPsbtUTXO = ({ chain }: { chain: SupportedCoin }) => {\n let appClient: import(\"ledger-bitcoin\").AppClient | undefined;\n let masterFingerprint: string | undefined;\n\n async function getAppClient() {\n if (!appClient) {\n const transport = await getLedgerTransport();\n const { AppClient } = await import(\"ledger-bitcoin\");\n appClient = new AppClient(transport);\n }\n return appClient;\n }\n\n async function getFingerprint() {\n if (!masterFingerprint) {\n const app = await getAppClient();\n masterFingerprint = await app.getMasterFingerprint();\n }\n return masterFingerprint;\n }\n\n return (derivationPathArray?: DerivationPathArray | string) => {\n // Single-address account: change == index == 0 by default.\n const derivationPath = derivationPathArray ? pathToString(derivationPathArray) : \"84'/0'/0'/0/0\";\n const accountPath = derivationPath.split(\"/\").slice(0, 3).join(\"/\");\n const leafSegments = derivationPath.split(\"/\").slice(3);\n const change = Number(leafSegments[0] ?? 0);\n const addressIndex = Number(leafSegments[1] ?? 0);\n const format = getWalletFormatFor(derivationPath);\n const template = templateForFormat(format);\n\n let cachedAccountXpub: string | undefined;\n let cachedLeafPubkey: Uint8Array | undefined;\n\n async function buildPolicy() {\n const app = await getAppClient();\n const fpr = await getFingerprint();\n if (!cachedAccountXpub) {\n cachedAccountXpub = await app.getExtendedPubkey(`m/${accountPath}`);\n }\n const { DefaultWalletPolicy } = await import(\"ledger-bitcoin\");\n const policy = new DefaultWalletPolicy(template, `[${fpr}/${accountPath}]${cachedAccountXpub}`);\n return { app, fpr, policy, xpub: cachedAccountXpub };\n }\n\n async function getLeafPubkey() {\n if (!cachedLeafPubkey) {\n const { xpub } = await buildPolicy();\n const accountKey = HDKey.fromExtendedKey(xpub);\n const leaf = accountKey.derive(`m/${change}/${addressIndex}`);\n if (!leaf.publicKey) {\n throw new SwapKitError(\"wallet_ledger_get_address_error\", {\n message: `Cannot derive leaf pubkey for ${chain}`,\n });\n }\n cachedLeafPubkey = leaf.publicKey;\n }\n return cachedLeafPubkey;\n }\n\n return {\n connect: async () => {\n await getAppClient();\n },\n getAddress: async () => {\n const { app, policy } = await buildPolicy();\n const address = await app.getWalletAddress(policy, null, change, addressIndex, false);\n if (!address) {\n throw new SwapKitError(\"wallet_ledger_get_address_error\", {\n message: `Cannot get ${chain} address from ledger derivation path: ${derivationPath}`,\n });\n }\n return address;\n },\n getExtendedPublicKey: async (path = `m/${accountPath}`) => {\n const app = await getAppClient();\n return app.getExtendedPubkey(path);\n },\n signTransaction: async (tx: Transaction): Promise<Transaction> => {\n const { app, policy, fpr } = await buildPolicy();\n const fingerprintBE = Number.parseInt(fpr, 16) >>> 0;\n const pathNumbers = pathToNumberArray(derivationPath);\n const leafPubkey = await getLeafPubkey();\n\n // Single-address account: every input is owned by the same key + path.\n for (let i = 0; i < tx.inputsLength; i++) {\n tx.updateInput(i, { bip32Derivation: [[leafPubkey, { fingerprint: fingerprintBE, path: pathNumbers }]] });\n }\n\n const psbtB64 = base64.encode(tx.toPSBT(0));\n const sigs = await app.signPsbt(psbtB64, policy, null);\n\n for (const [idx, partial] of sigs) {\n tx.updateInput(idx, { partialSig: [[new Uint8Array(partial.pubkey), new Uint8Array(partial.signature)]] });\n }\n\n tx.finalize();\n return tx;\n },\n };\n };\n};\n\nexport const BitcoinPsbtLedger = BaseLedgerPsbtUTXO({ chain: \"bitcoin\" });\nexport const LitecoinPsbtLedger = BaseLedgerPsbtUTXO({ chain: \"litecoin\" });\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "0B3F2685533B86ED64756E2164756E21",
9
- "names": []
10
- }