@swapkit/wallet-hardware 6.1.0 → 6.2.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 (101) hide show
  1. package/dist/chunk-035dayv6.js +4 -0
  2. package/dist/chunk-035dayv6.js.map +10 -0
  3. package/dist/{chunk-yrxe491r.js → chunk-2jddegc1.js} +3 -3
  4. package/dist/{chunk-yrxe491r.js.map → chunk-2jddegc1.js.map} +1 -1
  5. package/dist/{chunk-gr3eswf1.js → chunk-42xrtarj.js} +3 -3
  6. package/dist/{chunk-gr3eswf1.js.map → chunk-42xrtarj.js.map} +1 -1
  7. package/dist/{chunk-3t17wpjg.js → chunk-545s1tsc.js} +3 -3
  8. package/dist/{chunk-3t17wpjg.js.map → chunk-545s1tsc.js.map} +1 -1
  9. package/dist/{chunk-1amf58aq.js → chunk-5xg0xc0g.js} +3 -3
  10. package/dist/{chunk-1amf58aq.js.map → chunk-5xg0xc0g.js.map} +1 -1
  11. package/dist/{chunk-xn0fnag5.js → chunk-71kfnwdp.js} +3 -3
  12. package/dist/{chunk-xn0fnag5.js.map → chunk-71kfnwdp.js.map} +1 -1
  13. package/dist/{chunk-xmvg4cds.js → chunk-7kwtpk70.js} +3 -3
  14. package/dist/{chunk-xmvg4cds.js.map → chunk-7kwtpk70.js.map} +1 -1
  15. package/dist/{chunk-0arpsm5f.js → chunk-7rbvcts9.js} +3 -3
  16. package/dist/{chunk-0arpsm5f.js.map → chunk-7rbvcts9.js.map} +1 -1
  17. package/dist/{chunk-k3thje6a.js → chunk-a47dwwv6.js} +3 -3
  18. package/dist/{chunk-k3thje6a.js.map → chunk-a47dwwv6.js.map} +1 -1
  19. package/dist/{chunk-5c7b7z2d.js → chunk-a6vcbcyd.js} +3 -3
  20. package/dist/{chunk-5c7b7z2d.js.map → chunk-a6vcbcyd.js.map} +1 -1
  21. package/dist/{chunk-wfbg89d3.js → chunk-b093ajcq.js} +3 -3
  22. package/dist/{chunk-wfbg89d3.js.map → chunk-b093ajcq.js.map} +1 -1
  23. package/dist/{chunk-ds2m83jp.js → chunk-b7htg03t.js} +3 -3
  24. package/dist/{chunk-ds2m83jp.js.map → chunk-b7htg03t.js.map} +1 -1
  25. package/dist/chunk-g6rrzxcx.js +5 -0
  26. package/dist/chunk-g6rrzxcx.js.map +10 -0
  27. package/dist/{chunk-jewm2ag3.js → chunk-j3n6fbqh.js} +4 -4
  28. package/dist/{chunk-jewm2ag3.js.map → chunk-j3n6fbqh.js.map} +1 -1
  29. package/dist/{chunk-nhva847d.js → chunk-kaw35ae2.js} +3 -3
  30. package/dist/{chunk-nhva847d.js.map → chunk-kaw35ae2.js.map} +1 -1
  31. package/dist/{chunk-dptbnkzm.js → chunk-mzan0m09.js} +4 -4
  32. package/dist/{chunk-dptbnkzm.js.map → chunk-mzan0m09.js.map} +1 -1
  33. package/dist/{chunk-jzrytcrf.js → chunk-rydhx4se.js} +3 -3
  34. package/dist/{chunk-jzrytcrf.js.map → chunk-rydhx4se.js.map} +1 -1
  35. package/dist/{chunk-09e51wma.js → chunk-s2akss77.js} +3 -3
  36. package/dist/{chunk-09e51wma.js.map → chunk-s2akss77.js.map} +1 -1
  37. package/dist/{chunk-tm47brht.js → chunk-s5a5v0m1.js} +3 -3
  38. package/dist/{chunk-tm47brht.js.map → chunk-s5a5v0m1.js.map} +1 -1
  39. package/dist/{chunk-8m2sn76p.js → chunk-sbebfr50.js} +3 -3
  40. package/dist/{chunk-8m2sn76p.js.map → chunk-sbebfr50.js.map} +1 -1
  41. package/dist/{chunk-xx7cwpzq.js → chunk-sp3dq5hr.js} +2 -2
  42. package/dist/{chunk-hg71hp4m.js → chunk-tecse0bj.js} +3 -3
  43. package/dist/{chunk-hg71hp4m.js.map → chunk-tecse0bj.js.map} +1 -1
  44. package/dist/chunk-tm5gk51g.js +4 -0
  45. package/dist/{chunk-eenx3cv6.js → chunk-x28a37pz.js} +3 -3
  46. package/dist/{chunk-eenx3cv6.js.map → chunk-x28a37pz.js.map} +1 -1
  47. package/dist/{chunk-3h1f3hyp.js → chunk-ys51wj1c.js} +3 -3
  48. package/dist/{chunk-3h1f3hyp.js.map → chunk-ys51wj1c.js.map} +1 -1
  49. package/dist/keepkey/index.cjs +2 -2
  50. package/dist/keepkey/index.cjs.map +3 -3
  51. package/dist/keepkey/index.js +2 -2
  52. package/dist/keepkey/index.js.map +3 -3
  53. package/dist/ledger/index.cjs +30 -30
  54. package/dist/ledger/index.cjs.map +11 -7
  55. package/dist/ledger/index.js +2 -2
  56. package/dist/ledger/index.js.map +10 -7
  57. package/dist/trezor/index.cjs +2 -2
  58. package/dist/trezor/index.cjs.map +6 -5
  59. package/dist/trezor/index.js +2 -2
  60. package/dist/trezor/index.js.map +3 -3
  61. package/dist/types/helpers/cardano.d.ts +35 -0
  62. package/dist/types/helpers/cardano.d.ts.map +1 -0
  63. package/dist/types/keepkey/index.d.ts +1 -0
  64. package/dist/types/keepkey/index.d.ts.map +1 -1
  65. package/dist/types/ledger/clients/cardano.d.ts +24 -0
  66. package/dist/types/ledger/clients/cardano.d.ts.map +1 -0
  67. package/dist/types/ledger/clients/evm.d.ts +1 -0
  68. package/dist/types/ledger/clients/evm.d.ts.map +1 -1
  69. package/dist/types/ledger/clients/stellar.d.ts +13 -0
  70. package/dist/types/ledger/clients/stellar.d.ts.map +1 -0
  71. package/dist/types/ledger/clients/ton.d.ts +13 -0
  72. package/dist/types/ledger/clients/ton.d.ts.map +1 -0
  73. package/dist/types/ledger/helpers/getLedgerAddress.d.ts.map +1 -1
  74. package/dist/types/ledger/helpers/getLedgerClient.d.ts +8 -1
  75. package/dist/types/ledger/helpers/getLedgerClient.d.ts.map +1 -1
  76. package/dist/types/ledger/index.d.ts +3 -2
  77. package/dist/types/ledger/index.d.ts.map +1 -1
  78. package/dist/types/ledger/types.d.ts +2 -2
  79. package/dist/types/ledger/types.d.ts.map +1 -1
  80. package/dist/types/trezor/cardanoSigner.d.ts.map +1 -1
  81. package/dist/types/trezor/index.d.ts +1 -0
  82. package/dist/types/trezor/index.d.ts.map +1 -1
  83. package/dist/types/trezor/stellarSigner.d.ts +1 -1
  84. package/package.json +17 -5
  85. package/src/helpers/cardano.ts +112 -0
  86. package/src/keepkey/index.ts +14 -14
  87. package/src/ledger/clients/cardano.ts +204 -0
  88. package/src/ledger/clients/evm.ts +4 -0
  89. package/src/ledger/clients/stellar.ts +83 -0
  90. package/src/ledger/clients/ton.ts +282 -0
  91. package/src/ledger/helpers/getLedgerAddress.ts +16 -0
  92. package/src/ledger/helpers/getLedgerClient.ts +13 -0
  93. package/src/ledger/index.ts +100 -28
  94. package/src/ledger/types.ts +2 -0
  95. package/src/trezor/cardanoSigner.ts +24 -80
  96. package/src/trezor/index.ts +86 -64
  97. package/dist/chunk-5p3ttw6y.js +0 -4
  98. package/dist/chunk-qjq7gvyx.js +0 -4
  99. package/dist/chunk-qjq7gvyx.js.map +0 -10
  100. /package/dist/{chunk-xx7cwpzq.js.map → chunk-sp3dq5hr.js.map} +0 -0
  101. /package/dist/{chunk-5p3ttw6y.js.map → chunk-tm5gk51g.js.map} +0 -0
@@ -1,12 +1,13 @@
1
1
  import type Transport from "@ledgerhq/hw-transport";
2
2
  import { hex } from "@scure/base";
3
3
  import {
4
- type AssetValue,
4
+ AssetValue,
5
5
  Chain,
6
6
  type DerivationPathArray,
7
7
  derivationPathToString,
8
8
  FeeOption,
9
9
  filterSupportedChains,
10
+ type GenericTransferParams,
10
11
  getUTXOScriptTypeForPath,
11
12
  NetworkDerivationPath,
12
13
  SwapKitError,
@@ -14,6 +15,7 @@ import {
14
15
  UTXOScriptType,
15
16
  WalletOption,
16
17
  } from "@swapkit/helpers";
18
+ import type { TONTransactionInput } from "@swapkit/toolboxes/ton";
17
19
  import {
18
20
  addInputsAndOutputs,
19
21
  assertDerivationIndex,
@@ -92,6 +94,7 @@ const LEDGER_SUPPORTED_CHAINS_CONFIG = [
92
94
  Chain.BinanceSmartChain,
93
95
  Chain.Bitcoin,
94
96
  Chain.BitcoinCash,
97
+ Chain.Cardano,
95
98
  Chain.Cosmos,
96
99
  Chain.Dash,
97
100
  Chain.Dogecoin,
@@ -103,8 +106,11 @@ const LEDGER_SUPPORTED_CHAINS_CONFIG = [
103
106
  Chain.Optimism,
104
107
  Chain.Polygon,
105
108
  Chain.Ripple,
109
+ Chain.Robinhood,
110
+ Chain.Stellar,
106
111
  Chain.Sui,
107
112
  Chain.THORChain,
113
+ Chain.Ton,
108
114
  Chain.XLayer,
109
115
  Chain.Tron,
110
116
  Chain.Zcash,
@@ -134,6 +140,7 @@ const LEDGER_EVM_CHAINS = [
134
140
  Chain.Aurora,
135
141
  Chain.Gnosis,
136
142
  Chain.Monad,
143
+ Chain.Robinhood,
137
144
  Chain.XLayer,
138
145
  ] as const satisfies readonly LedgerSupportedChain[];
139
146
 
@@ -169,35 +176,26 @@ export const ledgerWallet = createWallet({
169
176
 
170
177
  return true;
171
178
  },
172
- directSigningSupport: {
173
- [Chain.Arbitrum]: true,
174
- [Chain.Arc]: true,
175
- [Chain.Aurora]: true,
176
- [Chain.Avalanche]: true,
177
- [Chain.Base]: true,
178
- [Chain.Berachain]: true,
179
- [Chain.BinanceSmartChain]: true,
180
- [Chain.Ethereum]: true,
181
- [Chain.Gnosis]: true,
182
- [Chain.Monad]: true,
183
- [Chain.Bitcoin]: true,
184
- [Chain.BitcoinCash]: true,
185
- [Chain.Cosmos]: true,
186
- [Chain.Dash]: true,
187
- [Chain.Dogecoin]: true,
188
- [Chain.Litecoin]: true,
189
- [Chain.Near]: true,
190
- [Chain.Optimism]: true,
191
- [Chain.Polygon]: true,
192
- [Chain.Ripple]: true,
193
- [Chain.Sui]: true,
194
- [Chain.THORChain]: true,
195
- [Chain.Tron]: true,
196
- [Chain.XLayer]: true,
197
- // ZEC transparent transfers use DSK, but route-level PCZT signing remains unsupported.
198
- },
199
179
  getExtendedPublicKey: getLedgerExtendedPublicKey,
200
180
  name: "connectLedger",
181
+ signingSupport: {
182
+ ...Object.fromEntries(LEDGER_EVM_CHAINS.map((chain) => [chain, { direct: true, typedData: true }])),
183
+ [Chain.Bitcoin]: { direct: true },
184
+ [Chain.BitcoinCash]: { direct: true },
185
+ [Chain.Cardano]: { direct: true },
186
+ [Chain.Cosmos]: { direct: true },
187
+ [Chain.Dash]: { direct: true },
188
+ [Chain.Dogecoin]: { direct: true },
189
+ [Chain.Litecoin]: { direct: true },
190
+ [Chain.Near]: { direct: true },
191
+ [Chain.Ripple]: { direct: true },
192
+ [Chain.Stellar]: { direct: true },
193
+ [Chain.Sui]: { direct: true },
194
+ [Chain.THORChain]: { direct: true },
195
+ [Chain.Ton]: { direct: true },
196
+ [Chain.Tron]: { direct: true },
197
+ // ZEC transparent transfers use DSK, but route-level PCZT signing remains unsupported.
198
+ },
201
199
  supportedChains: [...LEDGER_SUPPORTED_CHAINS_CONFIG],
202
200
  walletType: WalletOption.LEDGER,
203
201
  });
@@ -649,6 +647,21 @@ async function getNearWalletMethods({
649
647
  return { ...toolbox, address: accountId };
650
648
  }
651
649
 
650
+ async function getCardanoWalletMethods({
651
+ chain,
652
+ derivationPath,
653
+ dmkSession,
654
+ onDeviceActionState,
655
+ transport,
656
+ }: WalletMethodsParams<Chain.Cardano>) {
657
+ const { getCardanoToolbox } = await import("@swapkit/toolboxes/cardano");
658
+ const signer = await getLedgerClient({ chain, derivationPath, dmkSession, onDeviceActionState, transport });
659
+ const address = signer.getAddress();
660
+ const toolbox = getCardanoToolbox({ signer });
661
+
662
+ return { ...toolbox, address };
663
+ }
664
+
652
665
  async function getRippleWalletMethods({
653
666
  chain,
654
667
  derivationPath,
@@ -664,6 +677,21 @@ async function getRippleWalletMethods({
664
677
  return { ...toolbox, address };
665
678
  }
666
679
 
680
+ async function getStellarWalletMethods({
681
+ chain,
682
+ derivationPath,
683
+ dmkSession,
684
+ onDeviceActionState,
685
+ transport,
686
+ }: WalletMethodsParams<Chain.Stellar>) {
687
+ const { getStellarToolbox } = await import("@swapkit/toolboxes/stellar");
688
+ const signer = await getLedgerClient({ chain, derivationPath, dmkSession, onDeviceActionState, transport });
689
+ const address = await getLedgerAddress({ chain, ledgerClient: signer });
690
+ const toolbox = getStellarToolbox({ signer });
691
+
692
+ return { ...toolbox, address };
693
+ }
694
+
667
695
  async function getTronWalletMethods({
668
696
  chain,
669
697
  derivationPath,
@@ -694,6 +722,47 @@ async function getSuiWalletMethods({
694
722
  return { ...toolbox, address };
695
723
  }
696
724
 
725
+ async function getTONWalletMethods({
726
+ chain,
727
+ derivationPath,
728
+ dmkSession,
729
+ onDeviceActionState,
730
+ transport,
731
+ }: WalletMethodsParams<Chain.Ton>) {
732
+ const { getTONToolbox } = await import("@swapkit/toolboxes/ton");
733
+ const signer = await getLedgerClient({ chain, derivationPath, dmkSession, onDeviceActionState, transport });
734
+ const address = await getLedgerAddress({ chain, ledgerClient: signer });
735
+ // Signerless toolbox: it builds messages and reads balances, the device signs the external message.
736
+ const toolbox = getTONToolbox();
737
+
738
+ const signAndBroadcastTransaction = async (transaction: TONTransactionInput) =>
739
+ toolbox.broadcastTransaction(await signer.signTransaction(transaction));
740
+
741
+ const transfer = async ({ assetValue, memo, recipient, sweep }: GenericTransferParams) =>
742
+ signAndBroadcastTransaction(
743
+ await toolbox.createTransaction({ assetValue, memo, recipient, sender: address, sweep }),
744
+ );
745
+
746
+ // Same budget as TON Connect: the signerless toolbox underestimates jetton fees
747
+ const estimateTransactionFee = ({ assetValue }: GenericTransferParams) =>
748
+ Promise.resolve(AssetValue.from({ chain: Chain.Ton, value: assetValue.isGasAsset ? "0.01" : "0.06" }));
749
+
750
+ const sign = () => {
751
+ throw new SwapKitError("wallet_ledger_method_not_supported", { method: "sign", wallet: WalletOption.LEDGER });
752
+ };
753
+
754
+ return {
755
+ ...toolbox,
756
+ address,
757
+ estimateTransactionFee,
758
+ getAddress: () => address,
759
+ getBalance: () => toolbox.getBalance(address),
760
+ sign,
761
+ signAndBroadcastTransaction,
762
+ transfer,
763
+ };
764
+ }
765
+
697
766
  function getWalletMethods(params: WalletMethodsParams) {
698
767
  if (!isLedgerSupportedChain(params.chain)) {
699
768
  throw new SwapKitError("wallet_ledger_chain_not_supported", { chain: params.chain });
@@ -706,8 +775,11 @@ function getWalletMethods(params: WalletMethodsParams) {
706
775
  .with(Chain.THORChain, (chain) => getTHORChainWalletMethods({ ...params, chain }))
707
776
  .with(Chain.Near, (chain) => getNearWalletMethods({ ...params, chain }))
708
777
  .with(Chain.Ripple, (chain) => getRippleWalletMethods({ ...params, chain }))
778
+ .with(Chain.Stellar, (chain) => getStellarWalletMethods({ ...params, chain }))
779
+ .with(Chain.Cardano, (chain) => getCardanoWalletMethods({ ...params, chain }))
709
780
  .with(Chain.Tron, (chain) => getTronWalletMethods({ ...params, chain }))
710
781
  .with(Chain.Sui, (chain) => getSuiWalletMethods({ ...params, chain }))
782
+ .with(Chain.Ton, (chain) => getTONWalletMethods({ ...params, chain }))
711
783
  .exhaustive();
712
784
  }
713
785
 
@@ -13,6 +13,7 @@ import type {
13
13
  MonadLedger,
14
14
  OptimismLedger,
15
15
  PolygonLedger,
16
+ RobinhoodLedger,
16
17
  XLayerLedger,
17
18
  } from "./clients/evm";
18
19
  import type { SuiLedger } from "./clients/sui";
@@ -42,6 +43,7 @@ export type EVMLedgerClients =
42
43
  | ReturnType<typeof MonadLedger>
43
44
  | ReturnType<typeof OptimismLedger>
44
45
  | ReturnType<typeof PolygonLedger>
46
+ | ReturnType<typeof RobinhoodLedger>
45
47
  | ReturnType<typeof XLayerLedger>;
46
48
  export type TronLedgerClient = ReturnType<typeof TronLedger>;
47
49
  export type SuiLedgerClient = ReturnType<typeof SuiLedger>;
@@ -8,13 +8,13 @@ import {
8
8
  } from "@swapkit/toolboxes/cardano";
9
9
  import type {
10
10
  CardanoAssetGroup,
11
- CardanoInput,
12
11
  CardanoOutput,
13
12
  CardanoSignedTxData,
14
13
  CardanoSignTransaction,
15
- PROTO,
16
14
  } from "@trezor/connect-web";
17
15
 
16
+ import { type CardanoOutputFields, readCardanoBody } from "../helpers/cardano";
17
+
18
18
  type CardanoAddressParams = { address: string; path: string; stakingPath: string };
19
19
  export type TrezorConnectModule = typeof import("@trezor/connect-web");
20
20
 
@@ -26,9 +26,6 @@ function getConnectParams({ CARDANO, PROTO }: TrezorConnectModule) {
26
26
  };
27
27
  }
28
28
 
29
- const BODY = { AUXILIARY_DATA_HASH: 7, FEE: 2, INPUTS: 0, OUTPUTS: 1, TTL: 3, VALIDITY_INTERVAL_START: 8 } as const;
30
- const SET_TAG = 258;
31
-
32
29
  function notSupported(reason: string) {
33
30
  return new SwapKitError({ errorKey: "wallet_trezor_method_not_supported", info: { chain: Chain.Cardano, reason } });
34
31
  }
@@ -40,50 +37,12 @@ function signFailed(error: string) {
40
37
  });
41
38
  }
42
39
 
43
- function toUint(value: unknown, field: string) {
44
- const isBigNumber = typeof value === "object" && value !== null && "toFixed" in value;
45
- const text = isBigNumber || Number.isSafeInteger(value) ? String((value as number).toFixed()) : "";
46
- if (!/^\d+$/.test(text)) throw notSupported(`Invalid ${field} in Cardano transaction`);
47
- return text;
48
- }
49
-
50
- function toTokenBundle(multiAsset: Map<Uint8Array, Map<Uint8Array, unknown>>): CardanoAssetGroup[] {
51
- return [...multiAsset].map(([policyId, assets]) => ({
52
- policyId: hex.encode(policyId),
53
- tokenAmounts: [...assets].map(([assetName, amount]) => ({
54
- amount: toUint(amount, "token amount"),
55
- assetNameBytes: hex.encode(assetName),
56
- })),
57
- }));
58
- }
59
-
60
40
  async function toTrezorOutput(
61
- output: unknown,
41
+ { address, amount, format, tokenGroups }: CardanoOutputFields,
62
42
  own: CardanoAddressParams,
63
43
  proto: TrezorConnectModule["PROTO"],
64
44
  ): Promise<CardanoOutput> {
65
- let address: unknown;
66
- let value: unknown;
67
- let format: PROTO.CardanoTxOutputSerializationFormat;
68
-
69
- if (Array.isArray(output)) {
70
- if (output.length !== 2) throw notSupported("Trezor cannot sign Cardano outputs with a datum");
71
- [address, value] = output;
72
- format = proto.CardanoTxOutputSerializationFormat.ARRAY_LEGACY;
73
- } else if (output instanceof Map) {
74
- if (output.has(2)) throw notSupported("Trezor cannot sign Cardano outputs with a datum");
75
- if (output.has(3)) throw notSupported("Trezor cannot sign Cardano outputs with a reference script");
76
- if (output.size !== 2) throw notSupported("Unsupported field in Cardano output");
77
- address = output.get(0);
78
- value = output.get(1);
79
- format = proto.CardanoTxOutputSerializationFormat.MAP_BABBAGE;
80
- } else {
81
- throw notSupported("Invalid Cardano output");
82
- }
83
-
84
- if (Array.isArray(value) && value.length !== 2) throw notSupported("Invalid Cardano output value");
85
- const [coin, multiAsset] = Array.isArray(value) ? value : [value];
86
- const outputAddress = await getCardanoAddressFromBytes(address as Uint8Array);
45
+ const outputAddress = await getCardanoAddressFromBytes(address);
87
46
  const destination =
88
47
  outputAddress === own.address
89
48
  ? {
@@ -94,29 +53,22 @@ async function toTrezorOutput(
94
53
  },
95
54
  }
96
55
  : { address: outputAddress };
56
+ const tokenBundle: CardanoAssetGroup[] | undefined = tokenGroups?.map(({ policyId, tokens }) => ({
57
+ policyId: hex.encode(policyId),
58
+ tokenAmounts: tokens.map(({ amount, assetName }) => ({ amount, assetNameBytes: hex.encode(assetName) })),
59
+ }));
97
60
 
98
61
  return {
99
62
  ...destination,
100
- amount: toUint(coin, "output amount"),
101
- format,
102
- ...(multiAsset === undefined ? {} : { tokenBundle: toTokenBundle(multiAsset) }),
63
+ amount,
64
+ format:
65
+ format === "legacy"
66
+ ? proto.CardanoTxOutputSerializationFormat.ARRAY_LEGACY
67
+ : proto.CardanoTxOutputSerializationFormat.MAP_BABBAGE,
68
+ ...(tokenBundle === undefined ? {} : { tokenBundle }),
103
69
  };
104
70
  }
105
71
 
106
- function toTrezorInputs(inputs: unknown, path: string) {
107
- const isTagged =
108
- typeof inputs === "object" && inputs !== null && "tag" in inputs && inputs.tag === SET_TAG && "value" in inputs;
109
- const list = (isTagged ? inputs.value : inputs) as unknown[][];
110
-
111
- const trezorInputs: CardanoInput[] = list.map((input) => {
112
- if (input.length !== 2) throw notSupported("Invalid Cardano input");
113
- const [txHash, index] = input as [Uint8Array, unknown];
114
- return { path, prev_hash: hex.encode(txHash), prev_index: Number(toUint(index, "input index")) };
115
- });
116
-
117
- return { inputs: trezorInputs, tagCborSets: isTagged };
118
- }
119
-
120
72
  export async function toTrezorCardanoTransaction(
121
73
  txHex: string,
122
74
  own: CardanoAddressParams,
@@ -125,31 +77,23 @@ export async function toTrezorCardanoTransaction(
125
77
  const { body } = await decodeCardanoTransaction(txHex);
126
78
  const { derivationType, mainnet } = getConnectParams(connect);
127
79
  const { PROTO: proto } = connect;
128
-
129
- const supportedFields: unknown[] = Object.values(BODY);
130
- const unsupported = [...body.keys()].filter((field) => !supportedFields.includes(field));
131
- if (unsupported.length > 0) {
132
- throw notSupported(`Trezor cannot sign Cardano transactions with body fields ${unsupported.join(", ")}`);
133
- }
134
-
135
- const outputs = body.get(BODY.OUTPUTS) as unknown[];
136
- const auxiliaryDataHash = body.get(BODY.AUXILIARY_DATA_HASH) as Uint8Array | undefined;
137
-
138
- const ttl = body.get(BODY.TTL);
139
- const validityIntervalStart = body.get(BODY.VALIDITY_INTERVAL_START);
80
+ const { auxiliaryDataHash, fee, inputs, outputs, tagCborSets, ttl, validityIntervalStart } = readCardanoBody(
81
+ body,
82
+ "Trezor",
83
+ notSupported,
84
+ );
140
85
 
141
86
  return {
142
- ...toTrezorInputs(body.get(BODY.INPUTS), own.path),
87
+ inputs: inputs.map(({ index, txHash }) => ({ path: own.path, prev_hash: hex.encode(txHash), prev_index: index })),
88
+ tagCborSets,
143
89
  ...mainnet,
144
90
  derivationType,
145
- fee: toUint(body.get(BODY.FEE), "fee"),
91
+ fee,
146
92
  outputs: await Promise.all(outputs.map((output) => toTrezorOutput(output, own, proto))),
147
93
  signingMode: proto.CardanoTxSigningMode.ORDINARY_TRANSACTION,
148
94
  ...(auxiliaryDataHash ? { auxiliaryData: { hash: hex.encode(auxiliaryDataHash) } } : {}),
149
- ...(ttl === undefined ? {} : { ttl: toUint(ttl, "ttl") }),
150
- ...(validityIntervalStart === undefined
151
- ? {}
152
- : { validityIntervalStart: toUint(validityIntervalStart, "validity interval start") }),
95
+ ...(ttl === undefined ? {} : { ttl }),
96
+ ...(validityIntervalStart === undefined ? {} : { validityIntervalStart }),
153
97
  };
154
98
  }
155
99
 
@@ -486,6 +486,35 @@ async function buildZcashTxOutputsForTrezor({
486
486
  return outputs;
487
487
  }
488
488
 
489
+ type ZcashTrezorSignRequest = {
490
+ branchId: number;
491
+ expiry: number;
492
+ inputs: { amount: string; prev_hash: string; prev_index: number }[];
493
+ locktime: number;
494
+ outputs: { address?: string; amount: string; script_type: string }[];
495
+ version: number;
496
+ versionGroupId: number;
497
+ };
498
+
499
+ function describeZcashSignRequest({ inputs, outputs, ...header }: ZcashTrezorSignRequest) {
500
+ const sum = (amounts: { amount: string }[]) => amounts.reduce((total, { amount }) => total + BigInt(amount), 0n);
501
+ const inputTotal = sum(inputs);
502
+ const outputTotal = sum(outputs);
503
+
504
+ return {
505
+ ...header,
506
+ fee: (inputTotal - outputTotal).toString(),
507
+ inputAmounts: inputs.map(({ amount }) => amount),
508
+ inputs: inputs.map(({ prev_hash, prev_index }) => `${prev_hash}:${prev_index}`),
509
+ inputTotal: inputTotal.toString(),
510
+ outputs: outputs.map(({ address, amount, script_type }) => ({
511
+ amount,
512
+ kind: script_type === "PAYTOOPRETURN" ? "op_return" : address ? "external" : "change",
513
+ })),
514
+ outputTotal: outputTotal.toString(),
515
+ };
516
+ }
517
+
489
518
  async function buildUtxoOutputsForTrezor(
490
519
  tx: Transaction,
491
520
  network: BTCNetwork,
@@ -657,11 +686,12 @@ async function getTrezorWallet<T extends Chain>({
657
686
  case Chain.Zcash: {
658
687
  const { getUtxoToolbox } = await import("@swapkit/toolboxes/utxo");
659
688
 
689
+ const coin = chain.toLowerCase();
660
690
  const derivationPathStr = derivationPathToString(derivationPath);
661
691
 
662
692
  const getAddress = async () => {
663
693
  const TrezorConnect = (await import("@trezor/connect-web")).default;
664
- const { success, payload } = await TrezorConnect.getAddress({ coin: "zcash", path: derivationPathStr });
694
+ const { success, payload } = await TrezorConnect.getAddress({ coin, path: derivationPathStr });
665
695
 
666
696
  if (!success) {
667
697
  throw new SwapKitError({
@@ -675,37 +705,41 @@ async function getTrezorWallet<T extends Chain>({
675
705
 
676
706
  const address = providedAddress ?? (await getAddress());
677
707
 
678
- const signPCZTWithSerializedTx = async (pczt: PCZT) => {
708
+ const signWithTrezor = async (request: ZcashTrezorSignRequest, signingPath: "pczt" | "transaction") => {
679
709
  const TrezorConnect = (await import("@trezor/connect-web")).default;
710
+ const result = await TrezorConnect.signTransaction({ ...request, coin, overwintered: true } as Parameters<
711
+ typeof TrezorConnect.signTransaction
712
+ >[0]);
713
+
714
+ if (!result.success) {
715
+ throw new SwapKitError({
716
+ errorKey: "wallet_trezor_failed_to_sign_transaction",
717
+ info: { ...result.payload, chain, derivationPath, request: describeZcashSignRequest(request), signingPath },
718
+ });
719
+ }
720
+
721
+ return result.payload.serializedTx;
722
+ };
723
+
724
+ const signPCZTWithSerializedTx = async (pczt: PCZT) => {
680
725
  const { hex: hexEncode } = await import("@scure/base");
681
726
  const address_n = hardenDerivationPath(derivationPath);
682
727
  const global = pczt.getGlobal();
683
728
 
684
729
  const inputs = buildPCZTInputsForTrezor(pczt, address_n, hexEncode);
685
730
  const outputs = await buildPCZTOutputsForTrezor(pczt, address_n, address, chain);
686
- const result = await TrezorConnect.signTransaction({
731
+ const request = {
687
732
  branchId: global.consensusBranchId,
688
- coin: "zcash",
689
733
  expiry: global.expiryHeight,
690
734
  inputs,
691
735
  locktime: global.lockTime,
692
- outputs: outputs as any,
693
- overwintered: true,
736
+ outputs,
694
737
  version: global.txVersion,
695
738
  versionGroupId: global.versionGroupId,
696
- });
697
-
698
- if (!result.success) {
699
- throw new SwapKitError({
700
- errorKey: "wallet_trezor_failed_to_sign_transaction",
701
- info: { chain, error: (result.payload as { error: string; code?: string }).error },
702
- });
703
- }
704
-
705
- return {
706
- serializedTx: result.payload.serializedTx,
707
- signedPczt: await extractSignaturesFromSignedTx(result.payload.serializedTx, pczt),
708
739
  };
740
+ const serializedTx = await signWithTrezor(request, "pczt");
741
+
742
+ return { serializedTx, signedPczt: await extractSignaturesFromSignedTx(serializedTx, pczt) };
709
743
  };
710
744
 
711
745
  const parseSignedZcashTransaction = async (signedTxHex: string) => {
@@ -714,7 +748,6 @@ async function getTrezorWallet<T extends Chain>({
714
748
  };
715
749
 
716
750
  const signZcashTransactionWithSerializedTx = async (tx: ZcashTransaction) => {
717
- const TrezorConnect = (await import("@trezor/connect-web")).default;
718
751
  const { hex: hexEncode } = await import("@scure/base");
719
752
  const { NETWORKS, ZcashVersionGroupId } = await import("@swapkit/utxo-signer");
720
753
  const address_n = hardenDerivationPath(derivationPath);
@@ -728,29 +761,18 @@ async function getTrezorWallet<T extends Chain>({
728
761
  tx,
729
762
  });
730
763
 
731
- const result = await TrezorConnect.signTransaction({
764
+ const request = {
732
765
  branchId: tx.consensusBranchId,
733
- coin: "zcash",
734
766
  expiry: 0,
735
767
  inputs,
736
768
  locktime: 0,
737
- outputs: outputs as any,
738
- overwintered: true,
769
+ outputs,
739
770
  version: 4,
740
771
  versionGroupId: ZcashVersionGroupId.SAPLING,
741
- });
742
-
743
- if (result.success) {
744
- return {
745
- serializedTx: result.payload.serializedTx,
746
- signedTx: await parseSignedZcashTransaction(result.payload.serializedTx),
747
- };
748
- }
772
+ };
773
+ const serializedTx = await signWithTrezor(request, "transaction");
749
774
 
750
- throw new SwapKitError({
751
- errorKey: "wallet_trezor_failed_to_sign_transaction",
752
- info: { chain, error: (result.payload as { error: string; code?: string }).error },
753
- });
775
+ return { serializedTx, signedTx: await parseSignedZcashTransaction(serializedTx) };
754
776
  };
755
777
 
756
778
  const signer = {
@@ -1427,7 +1449,7 @@ export async function getTrezorExtendedPublicKey(
1427
1449
  const { TrezorConnect } = await initTrezorConnect();
1428
1450
  const utxoChain = chain as UTXOChain;
1429
1451
  const resolvedDerivationPath = derivationPath ?? (NetworkDerivationPath[chain] as DerivationPathArray);
1430
- const coin = chain === Chain.Zcash ? "zcash" : chain.toLowerCase();
1452
+ const coin = chain.toLowerCase();
1431
1453
 
1432
1454
  const resolvedAccountPath = getUTXOAccountPath({
1433
1455
  accountIndex,
@@ -1531,36 +1553,36 @@ export const trezorWallet = createWallet({
1531
1553
 
1532
1554
  return true;
1533
1555
  },
1534
- directSigningSupport: {
1535
- [Chain.Arbitrum]: true,
1536
- [Chain.Arc]: true,
1537
- [Chain.Aurora]: true,
1538
- [Chain.Avalanche]: true,
1539
- [Chain.Base]: true,
1540
- [Chain.Berachain]: true,
1541
- [Chain.BinanceSmartChain]: true,
1542
- [Chain.Bitcoin]: true,
1543
- [Chain.BitcoinCash]: true,
1544
- [Chain.Cardano]: true,
1545
- [Chain.Dash]: true,
1546
- [Chain.Ethereum]: true,
1547
- [Chain.Gnosis]: true,
1548
- [Chain.Dogecoin]: true,
1549
- [Chain.Hyperevm]: true,
1550
- [Chain.Litecoin]: true,
1551
- [Chain.Monad]: true,
1552
- [Chain.Optimism]: true,
1553
- [Chain.Polygon]: true,
1554
- [Chain.Ripple]: true,
1555
- [Chain.Robinhood]: true,
1556
- [Chain.Solana]: true,
1557
- [Chain.Stellar]: true,
1558
- [Chain.Tron]: true,
1559
- [Chain.XLayer]: true,
1560
- [Chain.Zcash]: true,
1561
- },
1562
1556
  getExtendedPublicKey: getTrezorExtendedPublicKey,
1563
1557
  name: "connectTrezor",
1558
+ signingSupport: {
1559
+ [Chain.Arbitrum]: { direct: true, typedData: true },
1560
+ [Chain.Arc]: { direct: true, typedData: true },
1561
+ [Chain.Aurora]: { direct: true, typedData: true },
1562
+ [Chain.Avalanche]: { direct: true, typedData: true },
1563
+ [Chain.Base]: { direct: true, typedData: true },
1564
+ [Chain.Berachain]: { direct: true, typedData: true },
1565
+ [Chain.BinanceSmartChain]: { direct: true, typedData: true },
1566
+ [Chain.Bitcoin]: { direct: true },
1567
+ [Chain.BitcoinCash]: { direct: true },
1568
+ [Chain.Cardano]: { direct: true },
1569
+ [Chain.Dash]: { direct: true },
1570
+ [Chain.Ethereum]: { direct: true, typedData: true },
1571
+ [Chain.Gnosis]: { direct: true, typedData: true },
1572
+ [Chain.Dogecoin]: { direct: true },
1573
+ [Chain.Hyperevm]: { direct: true, typedData: true },
1574
+ [Chain.Litecoin]: { direct: true },
1575
+ [Chain.Monad]: { direct: true, typedData: true },
1576
+ [Chain.Optimism]: { direct: true, typedData: true },
1577
+ [Chain.Polygon]: { direct: true, typedData: true },
1578
+ [Chain.Ripple]: { direct: true },
1579
+ [Chain.Robinhood]: { direct: true, typedData: true },
1580
+ [Chain.Solana]: { direct: true },
1581
+ [Chain.Stellar]: { direct: true },
1582
+ [Chain.Tron]: { direct: true },
1583
+ [Chain.XLayer]: { direct: true, typedData: true },
1584
+ [Chain.Zcash]: { direct: true },
1585
+ },
1564
1586
  supportedChains: [
1565
1587
  Chain.Arbitrum,
1566
1588
  Chain.Arc,
@@ -1,4 +0,0 @@
1
- import{Fa as a,Ga as b,Ha as c}from"./chunk-ds2m83jp.js";import"./chunk-nhva847d.js";export{b as signLegacyPsbtTransaction,a as extractInputsFromPsbt,c as createLegacyPsbtSigner};
2
-
3
- //# debugId=F3CCCADD39A261C464756E2164756E21
4
- //# sourceMappingURL=chunk-5p3ttw6y.js.map
@@ -1,4 +0,0 @@
1
- import"./chunk-nhva847d.js";import{hex as F}from"@scure/base";import{Chain as Y,derivationPathToString as A,SwapKitError as f}from"@swapkit/helpers";import{addCardanoVkeyWitnesses as g,decodeCardanoTransaction as m,getCardanoAddressFromBytes as H,getCardanoPublicKeyHash as O}from"@swapkit/toolboxes/cardano";function K({CARDANO:j,PROTO:q}){return{derivationType:q.CardanoDerivationType.ICARUS,mainnet:{networkId:j.NETWORK_IDS.mainnet,protocolMagic:j.PROTOCOL_MAGICS.mainnet}}}var _={AUXILIARY_DATA_HASH:7,FEE:2,INPUTS:0,OUTPUTS:1,TTL:3,VALIDITY_INTERVAL_START:8},P=258;function G(j){return new f({errorKey:"wallet_trezor_method_not_supported",info:{chain:Y.Cardano,reason:j}})}function B(j){return new f({errorKey:"wallet_trezor_failed_to_sign_transaction",info:{chain:Y.Cardano,error:j}})}function z(j,q){let J=typeof j==="object"&&j!==null&&"toFixed"in j||Number.isSafeInteger(j)?String(j.toFixed()):"";if(!/^\d+$/.test(J))throw G(`Invalid ${q} in Cardano transaction`);return J}function T(j){return[...j].map(([q,L])=>({policyId:F.encode(q),tokenAmounts:[...L].map(([J,M])=>({amount:z(M,"token amount"),assetNameBytes:F.encode(J)}))}))}async function b(j,q,L){let J,M,Q;if(Array.isArray(j)){if(j.length!==2)throw G("Trezor cannot sign Cardano outputs with a datum");[J,M]=j,Q=L.CardanoTxOutputSerializationFormat.ARRAY_LEGACY}else if(j instanceof Map){if(j.has(2))throw G("Trezor cannot sign Cardano outputs with a datum");if(j.has(3))throw G("Trezor cannot sign Cardano outputs with a reference script");if(j.size!==2)throw G("Unsupported field in Cardano output");J=j.get(0),M=j.get(1),Q=L.CardanoTxOutputSerializationFormat.MAP_BABBAGE}else throw G("Invalid Cardano output");if(Array.isArray(M)&&M.length!==2)throw G("Invalid Cardano output value");let[Z,X]=Array.isArray(M)?M:[M],$=await H(J);return{...$===q.address?{addressParameters:{addressType:L.CardanoAddressType.BASE,path:q.path,stakingPath:q.stakingPath}}:{address:$},amount:z(Z,"output amount"),format:Q,...X===void 0?{}:{tokenBundle:T(X)}}}function x(j,q){let L=typeof j==="object"&&j!==null&&"tag"in j&&j.tag===P&&"value"in j;return{inputs:(L?j.value:j).map((Q)=>{if(Q.length!==2)throw G("Invalid Cardano input");let[Z,X]=Q;return{path:q,prev_hash:F.encode(Z),prev_index:Number(z(X,"input index"))}}),tagCborSets:L}}async function v(j,q,L){let{body:J}=await m(j),{derivationType:M,mainnet:Q}=K(L),{PROTO:Z}=L,X=Object.values(_),$=[...J.keys()].filter((V)=>!X.includes(V));if($.length>0)throw G(`Trezor cannot sign Cardano transactions with body fields ${$.join(", ")}`);let W=J.get(_.OUTPUTS),U=J.get(_.AUXILIARY_DATA_HASH),N=J.get(_.TTL),E=J.get(_.VALIDITY_INTERVAL_START);return{...x(J.get(_.INPUTS),q.path),...Q,derivationType:M,fee:z(J.get(_.FEE),"fee"),outputs:await Promise.all(W.map((V)=>b(V,q,Z))),signingMode:Z.CardanoTxSigningMode.ORDINARY_TRANSACTION,...U?{auxiliaryData:{hash:F.encode(U)}}:{},...N===void 0?{}:{ttl:z(N,"ttl")},...E===void 0?{}:{validityIntervalStart:z(E,"validity interval start")}}}async function y(j,{hash:q,witnesses:L},J,{PROTO:M}){let{bodyHash:Q}=await m(j);if(q.toLowerCase()!==Q)throw B("Trezor signed a different transaction body");let Z=L.map(({pubKey:X,signature:$,type:W})=>{if(W!==M.CardanoTxWitnessType.SHELLEY_WITNESS||X.toLowerCase()!==J)throw B("Trezor returned a witness for an unexpected key");return{publicKey:F.decode(X),signature:F.decode($)}});return g(j,Z)}async function d({connect:j,derivationPath:q}){let[L,J,M,Q,Z]=q;if(q.length!==5||Q!==0||Z===void 0)throw new f({errorKey:"wallet_trezor_derivation_path_not_supported",info:{chain:Y.Cardano,derivationPath:q}});let X=A(q),$=A([L,J,M,2,0]),{derivationType:W,mainnet:U}=K(j),N=j.default,E=await N.cardanoGetPublicKey({bundle:[X,$].map((I)=>({derivationType:W,path:I}))});if(!E.success)throw new f({errorKey:"wallet_trezor_failed_to_get_address",info:{chain:Y.Cardano,derivationPath:q,error:E.payload.error}});let[V,S]=E.payload.map(({node:I})=>Buffer.from(I.public_key,"hex")),k=await O(V),D=await H(Buffer.concat([Buffer.from([U.networkId]),k,await O(S)]));async function w(I){let C=await v(I,{address:D,path:X,stakingPath:$},j),R=await N.cardanoSignTransaction(C);if(!R.success)throw B(R.payload.error);return y(I,R.payload,V.toString("hex"),j)}return{getAddress:()=>D,publicKey:V,publicKeyHash:k,signTransaction:w}}export{v as toTrezorCardanoTransaction,d as getCardanoSigner,y as addTrezorWitnesses};
2
-
3
- //# debugId=610DAB94A71C5BD564756E2164756E21
4
- //# sourceMappingURL=chunk-qjq7gvyx.js.map
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/trezor/cardanoSigner.ts"],
4
- "sourcesContent": [
5
- "import { hex } from \"@scure/base\";\nimport { Chain, type DerivationPathArray, derivationPathToString, SwapKitError } from \"@swapkit/helpers\";\nimport {\n addCardanoVkeyWitnesses,\n decodeCardanoTransaction,\n getCardanoAddressFromBytes,\n getCardanoPublicKeyHash,\n} from \"@swapkit/toolboxes/cardano\";\nimport type {\n CardanoAssetGroup,\n CardanoInput,\n CardanoOutput,\n CardanoSignedTxData,\n CardanoSignTransaction,\n PROTO,\n} from \"@trezor/connect-web\";\n\ntype CardanoAddressParams = { address: string; path: string; stakingPath: string };\nexport type TrezorConnectModule = typeof import(\"@trezor/connect-web\");\n\nfunction getConnectParams({ CARDANO, PROTO }: TrezorConnectModule) {\n return {\n // Trezor Suite default, same as the SwapKit keystore\n derivationType: PROTO.CardanoDerivationType.ICARUS,\n mainnet: { networkId: CARDANO.NETWORK_IDS.mainnet, protocolMagic: CARDANO.PROTOCOL_MAGICS.mainnet },\n };\n}\n\nconst BODY = { AUXILIARY_DATA_HASH: 7, FEE: 2, INPUTS: 0, OUTPUTS: 1, TTL: 3, VALIDITY_INTERVAL_START: 8 } as const;\nconst SET_TAG = 258;\n\nfunction notSupported(reason: string) {\n return new SwapKitError({ errorKey: \"wallet_trezor_method_not_supported\", info: { chain: Chain.Cardano, reason } });\n}\n\nfunction signFailed(error: string) {\n return new SwapKitError({\n errorKey: \"wallet_trezor_failed_to_sign_transaction\",\n info: { chain: Chain.Cardano, error },\n });\n}\n\nfunction toUint(value: unknown, field: string) {\n const isBigNumber = typeof value === \"object\" && value !== null && \"toFixed\" in value;\n const text = isBigNumber || Number.isSafeInteger(value) ? String((value as number).toFixed()) : \"\";\n if (!/^\\d+$/.test(text)) throw notSupported(`Invalid ${field} in Cardano transaction`);\n return text;\n}\n\nfunction toTokenBundle(multiAsset: Map<Uint8Array, Map<Uint8Array, unknown>>): CardanoAssetGroup[] {\n return [...multiAsset].map(([policyId, assets]) => ({\n policyId: hex.encode(policyId),\n tokenAmounts: [...assets].map(([assetName, amount]) => ({\n amount: toUint(amount, \"token amount\"),\n assetNameBytes: hex.encode(assetName),\n })),\n }));\n}\n\nasync function toTrezorOutput(\n output: unknown,\n own: CardanoAddressParams,\n proto: TrezorConnectModule[\"PROTO\"],\n): Promise<CardanoOutput> {\n let address: unknown;\n let value: unknown;\n let format: PROTO.CardanoTxOutputSerializationFormat;\n\n if (Array.isArray(output)) {\n if (output.length !== 2) throw notSupported(\"Trezor cannot sign Cardano outputs with a datum\");\n [address, value] = output;\n format = proto.CardanoTxOutputSerializationFormat.ARRAY_LEGACY;\n } else if (output instanceof Map) {\n if (output.has(2)) throw notSupported(\"Trezor cannot sign Cardano outputs with a datum\");\n if (output.has(3)) throw notSupported(\"Trezor cannot sign Cardano outputs with a reference script\");\n if (output.size !== 2) throw notSupported(\"Unsupported field in Cardano output\");\n address = output.get(0);\n value = output.get(1);\n format = proto.CardanoTxOutputSerializationFormat.MAP_BABBAGE;\n } else {\n throw notSupported(\"Invalid Cardano output\");\n }\n\n if (Array.isArray(value) && value.length !== 2) throw notSupported(\"Invalid Cardano output value\");\n const [coin, multiAsset] = Array.isArray(value) ? value : [value];\n const outputAddress = await getCardanoAddressFromBytes(address as Uint8Array);\n const destination =\n outputAddress === own.address\n ? {\n addressParameters: {\n addressType: proto.CardanoAddressType.BASE,\n path: own.path,\n stakingPath: own.stakingPath,\n },\n }\n : { address: outputAddress };\n\n return {\n ...destination,\n amount: toUint(coin, \"output amount\"),\n format,\n ...(multiAsset === undefined ? {} : { tokenBundle: toTokenBundle(multiAsset) }),\n };\n}\n\nfunction toTrezorInputs(inputs: unknown, path: string) {\n const isTagged =\n typeof inputs === \"object\" && inputs !== null && \"tag\" in inputs && inputs.tag === SET_TAG && \"value\" in inputs;\n const list = (isTagged ? inputs.value : inputs) as unknown[][];\n\n const trezorInputs: CardanoInput[] = list.map((input) => {\n if (input.length !== 2) throw notSupported(\"Invalid Cardano input\");\n const [txHash, index] = input as [Uint8Array, unknown];\n return { path, prev_hash: hex.encode(txHash), prev_index: Number(toUint(index, \"input index\")) };\n });\n\n return { inputs: trezorInputs, tagCborSets: isTagged };\n}\n\nexport async function toTrezorCardanoTransaction(\n txHex: string,\n own: CardanoAddressParams,\n connect: TrezorConnectModule,\n): Promise<CardanoSignTransaction> {\n const { body } = await decodeCardanoTransaction(txHex);\n const { derivationType, mainnet } = getConnectParams(connect);\n const { PROTO: proto } = connect;\n\n const supportedFields: unknown[] = Object.values(BODY);\n const unsupported = [...body.keys()].filter((field) => !supportedFields.includes(field));\n if (unsupported.length > 0) {\n throw notSupported(`Trezor cannot sign Cardano transactions with body fields ${unsupported.join(\", \")}`);\n }\n\n const outputs = body.get(BODY.OUTPUTS) as unknown[];\n const auxiliaryDataHash = body.get(BODY.AUXILIARY_DATA_HASH) as Uint8Array | undefined;\n\n const ttl = body.get(BODY.TTL);\n const validityIntervalStart = body.get(BODY.VALIDITY_INTERVAL_START);\n\n return {\n ...toTrezorInputs(body.get(BODY.INPUTS), own.path),\n ...mainnet,\n derivationType,\n fee: toUint(body.get(BODY.FEE), \"fee\"),\n outputs: await Promise.all(outputs.map((output) => toTrezorOutput(output, own, proto))),\n signingMode: proto.CardanoTxSigningMode.ORDINARY_TRANSACTION,\n ...(auxiliaryDataHash ? { auxiliaryData: { hash: hex.encode(auxiliaryDataHash) } } : {}),\n ...(ttl === undefined ? {} : { ttl: toUint(ttl, \"ttl\") }),\n ...(validityIntervalStart === undefined\n ? {}\n : { validityIntervalStart: toUint(validityIntervalStart, \"validity interval start\") }),\n };\n}\n\nexport async function addTrezorWitnesses(\n txHex: string,\n { hash, witnesses }: Pick<CardanoSignedTxData, \"hash\" | \"witnesses\">,\n publicKey: string,\n { PROTO: proto }: TrezorConnectModule,\n) {\n const { bodyHash } = await decodeCardanoTransaction(txHex);\n\n if (hash.toLowerCase() !== bodyHash) throw signFailed(\"Trezor signed a different transaction body\");\n\n const vkeyWitnesses = witnesses.map(({ pubKey, signature, type }) => {\n if (type !== proto.CardanoTxWitnessType.SHELLEY_WITNESS || pubKey.toLowerCase() !== publicKey) {\n throw signFailed(\"Trezor returned a witness for an unexpected key\");\n }\n return { publicKey: hex.decode(pubKey), signature: hex.decode(signature) };\n });\n\n return addCardanoVkeyWitnesses(txHex, vkeyWitnesses);\n}\n\nexport async function getCardanoSigner({\n connect,\n derivationPath,\n}: {\n connect: TrezorConnectModule;\n derivationPath: DerivationPathArray;\n}) {\n const [purpose, coinType, account, role, index] = derivationPath;\n if (derivationPath.length !== 5 || role !== 0 || index === undefined) {\n throw new SwapKitError({\n errorKey: \"wallet_trezor_derivation_path_not_supported\",\n info: { chain: Chain.Cardano, derivationPath },\n });\n }\n\n const path = derivationPathToString(derivationPath);\n const stakingPath = derivationPathToString([purpose, coinType, account, 2, 0] as DerivationPathArray);\n const { derivationType, mainnet } = getConnectParams(connect);\n const TrezorConnect = connect.default;\n\n // One device call: a second one right after would need a new Connect popup\n const keysResult = await TrezorConnect.cardanoGetPublicKey({\n bundle: [path, stakingPath].map((keyPath) => ({ derivationType, path: keyPath })),\n });\n if (!keysResult.success) {\n throw new SwapKitError({\n errorKey: \"wallet_trezor_failed_to_get_address\",\n info: { chain: Chain.Cardano, derivationPath, error: keysResult.payload.error },\n });\n }\n\n const [publicKey, stakingKey] = keysResult.payload.map(({ node }) => Buffer.from(node.public_key, \"hex\")) as [\n Buffer,\n Buffer,\n ];\n const publicKeyHash = await getCardanoPublicKeyHash(publicKey);\n const address = await getCardanoAddressFromBytes(\n Buffer.concat([Buffer.from([mainnet.networkId]), publicKeyHash, await getCardanoPublicKeyHash(stakingKey)]),\n );\n\n async function signTransaction(txHex: string) {\n const params = await toTrezorCardanoTransaction(txHex, { address, path, stakingPath }, connect);\n const result = await TrezorConnect.cardanoSignTransaction(params);\n\n if (!result.success) throw signFailed(result.payload.error);\n\n return addTrezorWitnesses(txHex, result.payload, publicKey.toString(\"hex\"), connect);\n }\n\n return { getAddress: () => address, publicKey, publicKeyHash, signTransaction };\n}\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "610DAB94A71C5BD564756E2164756E21",
9
- "names": []
10
- }