@swapkit/wallet-hardware 6.1.1 → 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.
- package/dist/chunk-035dayv6.js +4 -0
- package/dist/chunk-035dayv6.js.map +10 -0
- package/dist/{chunk-yrxe491r.js → chunk-2jddegc1.js} +3 -3
- package/dist/{chunk-yrxe491r.js.map → chunk-2jddegc1.js.map} +1 -1
- package/dist/{chunk-gr3eswf1.js → chunk-42xrtarj.js} +3 -3
- package/dist/{chunk-gr3eswf1.js.map → chunk-42xrtarj.js.map} +1 -1
- package/dist/{chunk-3t17wpjg.js → chunk-545s1tsc.js} +3 -3
- package/dist/{chunk-3t17wpjg.js.map → chunk-545s1tsc.js.map} +1 -1
- package/dist/{chunk-1amf58aq.js → chunk-5xg0xc0g.js} +3 -3
- package/dist/{chunk-1amf58aq.js.map → chunk-5xg0xc0g.js.map} +1 -1
- package/dist/{chunk-xn0fnag5.js → chunk-71kfnwdp.js} +3 -3
- package/dist/{chunk-xn0fnag5.js.map → chunk-71kfnwdp.js.map} +1 -1
- package/dist/{chunk-xmvg4cds.js → chunk-7kwtpk70.js} +3 -3
- package/dist/{chunk-xmvg4cds.js.map → chunk-7kwtpk70.js.map} +1 -1
- package/dist/{chunk-0arpsm5f.js → chunk-7rbvcts9.js} +3 -3
- package/dist/{chunk-0arpsm5f.js.map → chunk-7rbvcts9.js.map} +1 -1
- package/dist/{chunk-k3thje6a.js → chunk-a47dwwv6.js} +3 -3
- package/dist/{chunk-k3thje6a.js.map → chunk-a47dwwv6.js.map} +1 -1
- package/dist/{chunk-5c7b7z2d.js → chunk-a6vcbcyd.js} +3 -3
- package/dist/{chunk-5c7b7z2d.js.map → chunk-a6vcbcyd.js.map} +1 -1
- package/dist/{chunk-wfbg89d3.js → chunk-b093ajcq.js} +3 -3
- package/dist/{chunk-wfbg89d3.js.map → chunk-b093ajcq.js.map} +1 -1
- package/dist/{chunk-ds2m83jp.js → chunk-b7htg03t.js} +3 -3
- package/dist/{chunk-ds2m83jp.js.map → chunk-b7htg03t.js.map} +1 -1
- package/dist/chunk-g6rrzxcx.js +5 -0
- package/dist/chunk-g6rrzxcx.js.map +10 -0
- package/dist/{chunk-jewm2ag3.js → chunk-j3n6fbqh.js} +4 -4
- package/dist/{chunk-jewm2ag3.js.map → chunk-j3n6fbqh.js.map} +1 -1
- package/dist/{chunk-nhva847d.js → chunk-kaw35ae2.js} +3 -3
- package/dist/{chunk-nhva847d.js.map → chunk-kaw35ae2.js.map} +1 -1
- package/dist/{chunk-dptbnkzm.js → chunk-mzan0m09.js} +4 -4
- package/dist/{chunk-dptbnkzm.js.map → chunk-mzan0m09.js.map} +1 -1
- package/dist/{chunk-jzrytcrf.js → chunk-rydhx4se.js} +3 -3
- package/dist/{chunk-jzrytcrf.js.map → chunk-rydhx4se.js.map} +1 -1
- package/dist/{chunk-09e51wma.js → chunk-s2akss77.js} +3 -3
- package/dist/{chunk-09e51wma.js.map → chunk-s2akss77.js.map} +1 -1
- package/dist/{chunk-tm47brht.js → chunk-s5a5v0m1.js} +3 -3
- package/dist/{chunk-tm47brht.js.map → chunk-s5a5v0m1.js.map} +1 -1
- package/dist/{chunk-8m2sn76p.js → chunk-sbebfr50.js} +3 -3
- package/dist/{chunk-8m2sn76p.js.map → chunk-sbebfr50.js.map} +1 -1
- package/dist/{chunk-xx7cwpzq.js → chunk-sp3dq5hr.js} +2 -2
- package/dist/{chunk-hg71hp4m.js → chunk-tecse0bj.js} +3 -3
- package/dist/{chunk-hg71hp4m.js.map → chunk-tecse0bj.js.map} +1 -1
- package/dist/chunk-tm5gk51g.js +4 -0
- package/dist/{chunk-eenx3cv6.js → chunk-x28a37pz.js} +3 -3
- package/dist/{chunk-eenx3cv6.js.map → chunk-x28a37pz.js.map} +1 -1
- package/dist/{chunk-3h1f3hyp.js → chunk-ys51wj1c.js} +3 -3
- package/dist/{chunk-3h1f3hyp.js.map → chunk-ys51wj1c.js.map} +1 -1
- package/dist/keepkey/index.cjs +2 -2
- package/dist/keepkey/index.cjs.map +3 -3
- package/dist/keepkey/index.js +2 -2
- package/dist/keepkey/index.js.map +3 -3
- package/dist/ledger/index.cjs +30 -30
- package/dist/ledger/index.cjs.map +11 -7
- package/dist/ledger/index.js +2 -2
- package/dist/ledger/index.js.map +10 -7
- package/dist/trezor/index.cjs +2 -2
- package/dist/trezor/index.cjs.map +6 -5
- package/dist/trezor/index.js +2 -2
- package/dist/trezor/index.js.map +3 -3
- package/dist/types/helpers/cardano.d.ts +35 -0
- package/dist/types/helpers/cardano.d.ts.map +1 -0
- package/dist/types/keepkey/index.d.ts +1 -0
- package/dist/types/keepkey/index.d.ts.map +1 -1
- package/dist/types/ledger/clients/cardano.d.ts +24 -0
- package/dist/types/ledger/clients/cardano.d.ts.map +1 -0
- package/dist/types/ledger/clients/evm.d.ts +1 -0
- package/dist/types/ledger/clients/evm.d.ts.map +1 -1
- package/dist/types/ledger/clients/stellar.d.ts +13 -0
- package/dist/types/ledger/clients/stellar.d.ts.map +1 -0
- package/dist/types/ledger/clients/ton.d.ts +13 -0
- package/dist/types/ledger/clients/ton.d.ts.map +1 -0
- package/dist/types/ledger/helpers/getLedgerAddress.d.ts.map +1 -1
- package/dist/types/ledger/helpers/getLedgerClient.d.ts +8 -1
- package/dist/types/ledger/helpers/getLedgerClient.d.ts.map +1 -1
- package/dist/types/ledger/index.d.ts +3 -2
- package/dist/types/ledger/index.d.ts.map +1 -1
- package/dist/types/ledger/types.d.ts +2 -2
- package/dist/types/ledger/types.d.ts.map +1 -1
- package/dist/types/trezor/cardanoSigner.d.ts.map +1 -1
- package/dist/types/trezor/index.d.ts +1 -0
- package/dist/types/trezor/index.d.ts.map +1 -1
- package/dist/types/trezor/stellarSigner.d.ts +1 -1
- package/package.json +16 -4
- package/src/helpers/cardano.ts +112 -0
- package/src/keepkey/index.ts +14 -14
- package/src/ledger/clients/cardano.ts +204 -0
- package/src/ledger/clients/evm.ts +4 -0
- package/src/ledger/clients/stellar.ts +83 -0
- package/src/ledger/clients/ton.ts +282 -0
- package/src/ledger/helpers/getLedgerAddress.ts +16 -0
- package/src/ledger/helpers/getLedgerClient.ts +13 -0
- package/src/ledger/index.ts +100 -28
- package/src/ledger/types.ts +2 -0
- package/src/trezor/cardanoSigner.ts +24 -80
- package/src/trezor/index.ts +86 -64
- package/dist/chunk-5p3ttw6y.js +0 -4
- package/dist/chunk-qjq7gvyx.js +0 -4
- package/dist/chunk-qjq7gvyx.js.map +0 -10
- /package/dist/{chunk-xx7cwpzq.js.map → chunk-sp3dq5hr.js.map} +0 -0
- /package/dist/{chunk-5p3ttw6y.js.map → chunk-tm5gk51g.js.map} +0 -0
package/src/ledger/index.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type Transport from "@ledgerhq/hw-transport";
|
|
2
2
|
import { hex } from "@scure/base";
|
|
3
3
|
import {
|
|
4
|
-
|
|
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
|
|
package/src/ledger/types.ts
CHANGED
|
@@ -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
|
-
|
|
41
|
+
{ address, amount, format, tokenGroups }: CardanoOutputFields,
|
|
62
42
|
own: CardanoAddressParams,
|
|
63
43
|
proto: TrezorConnectModule["PROTO"],
|
|
64
44
|
): Promise<CardanoOutput> {
|
|
65
|
-
|
|
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
|
|
101
|
-
format
|
|
102
|
-
|
|
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
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
package/src/trezor/index.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
764
|
+
const request = {
|
|
732
765
|
branchId: tx.consensusBranchId,
|
|
733
|
-
coin: "zcash",
|
|
734
766
|
expiry: 0,
|
|
735
767
|
inputs,
|
|
736
768
|
locktime: 0,
|
|
737
|
-
outputs
|
|
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
|
-
|
|
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
|
|
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,
|
package/dist/chunk-5p3ttw6y.js
DELETED
package/dist/chunk-qjq7gvyx.js
DELETED
|
@@ -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
|
-
}
|
|
File without changes
|
|
File without changes
|