@swapkit/wallet-hardware 4.9.14 → 4.9.16
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/src/trezor/index.ts
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
type UTXOToolboxes,
|
|
23
23
|
type UTXOType,
|
|
24
24
|
} from "@swapkit/toolboxes/utxo";
|
|
25
|
-
import type { BTCNetwork, PCZT, Transaction, ZcashTransaction } from "@swapkit/utxo-signer";
|
|
25
|
+
import type { BTCNetwork, PCZT, Transaction, ZcashPSBT, ZcashTransaction } from "@swapkit/utxo-signer";
|
|
26
26
|
import { BCHSigHash, NETWORKS, ZcashConsensusBranchId, ZcashVersionGroupId } from "@swapkit/utxo-signer";
|
|
27
27
|
import { createWallet, getWalletSupportedChains, type HardwareExtendedPublicKeyInfo } from "@swapkit/wallet-core";
|
|
28
28
|
|
|
@@ -31,6 +31,7 @@ type TrezorCoreMode = "auto" | "iframe" | "popup" | "suite-desktop" | "suite-web
|
|
|
31
31
|
type TrezorTransport = "BridgeTransport" | "WebUsbTransport" | "NodeUsbTransport";
|
|
32
32
|
type ConnectTrezorOptions = { address?: string };
|
|
33
33
|
type TrezorAccountRefTransaction = { details: Record<string, never>; hex: string; txid: string };
|
|
34
|
+
type ZcashSignableTransaction = PCZT | ZcashPSBT | ZcashTransaction;
|
|
34
35
|
type TrezorExtendedPublicKeyInfo = {
|
|
35
36
|
accountIndex: number;
|
|
36
37
|
chainCode?: string;
|
|
@@ -275,7 +276,7 @@ function buildPCZTInputsForTrezor(
|
|
|
275
276
|
inputs.push({
|
|
276
277
|
address_n,
|
|
277
278
|
amount: input.value.toString(),
|
|
278
|
-
prev_hash: hexEncode.encode(
|
|
279
|
+
prev_hash: hexEncode.encode(input.txid),
|
|
279
280
|
prev_index: input.index,
|
|
280
281
|
script_type: "SPENDADDRESS" as const,
|
|
281
282
|
});
|
|
@@ -364,8 +365,8 @@ function buildZcashTxInputsForTrezor(
|
|
|
364
365
|
const utxoInfo = utxoInputs[i];
|
|
365
366
|
inputs.push({
|
|
366
367
|
address_n,
|
|
367
|
-
amount: utxoInfo?.value?.toString() || "0",
|
|
368
|
-
prev_hash: input.txid ? hexEncode.encode(
|
|
368
|
+
amount: utxoInfo?.value?.toString() || input.value?.toString() || "0",
|
|
369
|
+
prev_hash: input.txid ? hexEncode.encode(input.txid) : "",
|
|
369
370
|
prev_index: input.index ?? 0,
|
|
370
371
|
script_type: "SPENDADDRESS" as const,
|
|
371
372
|
});
|
|
@@ -467,7 +468,7 @@ function shouldUseTrezorSerializedSigner(chain: Chain) {
|
|
|
467
468
|
}
|
|
468
469
|
|
|
469
470
|
function buildTrezorRefTxs(chain: Chain, inputs: UTXOType[]): TrezorAccountRefTransaction[] | undefined {
|
|
470
|
-
if (
|
|
471
|
+
if (chain !== Chain.Dash) return undefined;
|
|
471
472
|
|
|
472
473
|
const refs = new Map<string, TrezorAccountRefTransaction>();
|
|
473
474
|
|
|
@@ -537,158 +538,140 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
537
538
|
return payload.address;
|
|
538
539
|
};
|
|
539
540
|
|
|
540
|
-
const address = await getAddress();
|
|
541
|
-
|
|
542
|
-
const signer = {
|
|
543
|
-
getAddress: async () => address,
|
|
544
|
-
|
|
545
|
-
signPCZT: async (pczt: PCZT): Promise<PCZT> => {
|
|
546
|
-
const TrezorConnect = (await import("@trezor/connect-web")).default;
|
|
547
|
-
const { hex: hexEncode } = await import("@scure/base");
|
|
548
|
-
const address_n = hardenDerivationPath(derivationPath);
|
|
549
|
-
const global = pczt.getGlobal();
|
|
550
|
-
|
|
551
|
-
const inputs = buildPCZTInputsForTrezor(pczt, address_n, hexEncode);
|
|
552
|
-
const outputs = await buildPCZTOutputsForTrezor(pczt, address_n, address, chain);
|
|
553
|
-
|
|
554
|
-
const result = await TrezorConnect.signTransaction({
|
|
555
|
-
branchId: global.consensusBranchId,
|
|
556
|
-
coin: "zcash",
|
|
557
|
-
expiry: global.expiryHeight,
|
|
558
|
-
inputs,
|
|
559
|
-
locktime: global.lockTime,
|
|
560
|
-
outputs: outputs as any,
|
|
561
|
-
overwintered: true,
|
|
562
|
-
version: global.txVersion,
|
|
563
|
-
versionGroupId: global.versionGroupId,
|
|
564
|
-
});
|
|
565
|
-
|
|
566
|
-
if (!result.success) {
|
|
567
|
-
throw new SwapKitError({
|
|
568
|
-
errorKey: "wallet_trezor_failed_to_sign_transaction",
|
|
569
|
-
info: { chain, error: (result.payload as { error: string; code?: string }).error },
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
return extractSignaturesFromSignedTx(result.payload.serializedTx, pczt);
|
|
574
|
-
},
|
|
541
|
+
const address = providedAddress ?? (await getAddress());
|
|
575
542
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
const inputs = buildZcashTxInputsForTrezor(tx, utxoInputs, address_n, hexEncode);
|
|
582
|
-
const outputs = buildZcashTxOutputsForTrezor(tx, address_n, address, chain);
|
|
583
|
-
|
|
584
|
-
const result = await TrezorConnect.signTransaction({
|
|
585
|
-
branchId: ZcashConsensusBranchId.NU6,
|
|
586
|
-
coin: "zcash",
|
|
587
|
-
expiry: 0,
|
|
588
|
-
inputs,
|
|
589
|
-
locktime: 0,
|
|
590
|
-
outputs: outputs as any,
|
|
591
|
-
overwintered: true,
|
|
592
|
-
version: 4,
|
|
593
|
-
versionGroupId: ZcashVersionGroupId.SAPLING,
|
|
594
|
-
});
|
|
543
|
+
const signPCZTWithSerializedTx = async (pczt: PCZT) => {
|
|
544
|
+
const TrezorConnect = (await import("@trezor/connect-web")).default;
|
|
545
|
+
const { hex: hexEncode } = await import("@scure/base");
|
|
546
|
+
const address_n = hardenDerivationPath(derivationPath);
|
|
547
|
+
const global = pczt.getGlobal();
|
|
595
548
|
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
549
|
+
const inputs = buildPCZTInputsForTrezor(pczt, address_n, hexEncode);
|
|
550
|
+
const outputs = await buildPCZTOutputsForTrezor(pczt, address_n, address, chain);
|
|
551
|
+
const result = await TrezorConnect.signTransaction({
|
|
552
|
+
branchId: global.consensusBranchId,
|
|
553
|
+
coin: "zcash",
|
|
554
|
+
expiry: global.expiryHeight,
|
|
555
|
+
inputs,
|
|
556
|
+
locktime: global.lockTime,
|
|
557
|
+
outputs: outputs as any,
|
|
558
|
+
overwintered: true,
|
|
559
|
+
version: global.txVersion,
|
|
560
|
+
versionGroupId: global.versionGroupId,
|
|
561
|
+
});
|
|
599
562
|
|
|
563
|
+
if (!result.success) {
|
|
600
564
|
throw new SwapKitError({
|
|
601
565
|
errorKey: "wallet_trezor_failed_to_sign_transaction",
|
|
602
566
|
info: { chain, error: (result.payload as { error: string; code?: string }).error },
|
|
603
567
|
});
|
|
604
|
-
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return {
|
|
571
|
+
serializedTx: result.payload.serializedTx,
|
|
572
|
+
signedPczt: await extractSignaturesFromSignedTx(result.payload.serializedTx, pczt),
|
|
573
|
+
};
|
|
605
574
|
};
|
|
606
575
|
|
|
607
|
-
const
|
|
576
|
+
const parseSignedZcashTransaction = async (signedTxHex: string) => {
|
|
577
|
+
const { ZcashTransaction: ZcashTx } = await import("@swapkit/utxo-signer");
|
|
578
|
+
return ZcashTx.fromHex(signedTxHex, { allowUnknownOutputs: true });
|
|
579
|
+
};
|
|
608
580
|
|
|
609
|
-
const
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
info: { address, recipient: params.recipient, wallet: WalletOption.TREZOR },
|
|
614
|
-
});
|
|
615
|
-
}
|
|
581
|
+
const signZcashTransactionWithSerializedTx = async (tx: ZcashTransaction) => {
|
|
582
|
+
const TrezorConnect = (await import("@trezor/connect-web")).default;
|
|
583
|
+
const { hex: hexEncode } = await import("@scure/base");
|
|
584
|
+
const address_n = hardenDerivationPath(derivationPath);
|
|
616
585
|
|
|
617
|
-
const
|
|
586
|
+
const inputs = buildZcashTxInputsForTrezor(tx, [], address_n, hexEncode);
|
|
587
|
+
const outputs = buildZcashTxOutputsForTrezor(tx, address_n, address, chain);
|
|
618
588
|
|
|
619
|
-
const
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
589
|
+
const result = await TrezorConnect.signTransaction({
|
|
590
|
+
branchId: ZcashConsensusBranchId.NU6,
|
|
591
|
+
coin: "zcash",
|
|
592
|
+
expiry: 0,
|
|
593
|
+
inputs,
|
|
594
|
+
locktime: 0,
|
|
595
|
+
outputs: outputs as any,
|
|
596
|
+
overwintered: true,
|
|
597
|
+
version: 4,
|
|
598
|
+
versionGroupId: ZcashVersionGroupId.SAPLING,
|
|
624
599
|
});
|
|
625
600
|
|
|
626
|
-
|
|
627
|
-
|
|
601
|
+
if (result.success) {
|
|
602
|
+
return {
|
|
603
|
+
serializedTx: result.payload.serializedTx,
|
|
604
|
+
signedTx: await parseSignedZcashTransaction(result.payload.serializedTx),
|
|
605
|
+
};
|
|
606
|
+
}
|
|
628
607
|
|
|
629
|
-
|
|
608
|
+
throw new SwapKitError({
|
|
609
|
+
errorKey: "wallet_trezor_failed_to_sign_transaction",
|
|
610
|
+
info: { chain, error: (result.payload as { error: string; code?: string }).error },
|
|
611
|
+
});
|
|
630
612
|
};
|
|
631
613
|
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
throw new SwapKitError({
|
|
635
|
-
errorKey: "wallet_missing_params",
|
|
636
|
-
info: { address, recipient: params.recipient, wallet: WalletOption.TREZOR },
|
|
637
|
-
});
|
|
638
|
-
}
|
|
614
|
+
const signer = {
|
|
615
|
+
getAddress: async () => address,
|
|
639
616
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
617
|
+
signPCZT: async (pczt: PCZT): Promise<PCZT> => {
|
|
618
|
+
return (await signPCZTWithSerializedTx(pczt)).signedPczt;
|
|
619
|
+
},
|
|
643
620
|
|
|
644
|
-
|
|
621
|
+
signTransaction: async (tx: ZcashSignableTransaction): Promise<ZcashTransaction> => {
|
|
622
|
+
if ("toPCZT" in tx) {
|
|
623
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx.toPCZT());
|
|
624
|
+
return parseSignedZcashTransaction(serializedTx);
|
|
625
|
+
}
|
|
645
626
|
|
|
646
|
-
|
|
627
|
+
if ("getGlobal" in tx) {
|
|
628
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx);
|
|
629
|
+
return parseSignedZcashTransaction(serializedTx);
|
|
630
|
+
}
|
|
647
631
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
fetchTxHex: false,
|
|
652
|
-
sender: address,
|
|
653
|
-
});
|
|
632
|
+
return (await signZcashTransactionWithSerializedTx(tx)).signedTx;
|
|
633
|
+
},
|
|
634
|
+
};
|
|
654
635
|
|
|
655
|
-
|
|
636
|
+
const toolbox = getUtxoToolbox(Chain.Zcash, { signer });
|
|
656
637
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
638
|
+
const signAndBroadcastTransaction = async (tx: ZcashSignableTransaction) => {
|
|
639
|
+
if ("toPCZT" in tx) {
|
|
640
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx.toPCZT());
|
|
641
|
+
return toolbox.broadcastTx(serializedTx);
|
|
642
|
+
}
|
|
662
643
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
txid: hexEncode.decode(utxoInput.hash).reverse() as unknown as Uint8Array,
|
|
667
|
-
value: BigInt(utxoInput.value),
|
|
668
|
-
});
|
|
644
|
+
if ("getGlobal" in tx) {
|
|
645
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx);
|
|
646
|
+
return toolbox.broadcastTx(serializedTx);
|
|
669
647
|
}
|
|
670
648
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
649
|
+
const { serializedTx } = await signZcashTransactionWithSerializedTx(tx);
|
|
650
|
+
return toolbox.broadcastTx(serializedTx);
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
const transfer = async ({ recipient, feeOptionKey, feeRate: paramFeeRate, ...rest }: GenericTransferParams) => {
|
|
654
|
+
if (!(address && recipient)) {
|
|
655
|
+
throw new SwapKitError({
|
|
656
|
+
errorKey: "wallet_missing_params",
|
|
657
|
+
info: { address, recipient, wallet: WalletOption.TREZOR },
|
|
658
|
+
});
|
|
674
659
|
}
|
|
675
660
|
|
|
676
|
-
const
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
661
|
+
const feeRate = paramFeeRate || (await toolbox.getFeeRates())[feeOptionKey || FeeOption.Fast];
|
|
662
|
+
const { tx } = await toolbox.createTransaction({
|
|
663
|
+
...rest,
|
|
664
|
+
feeRate,
|
|
665
|
+
fetchTxHex: false,
|
|
666
|
+
recipient,
|
|
667
|
+
sender: address,
|
|
668
|
+
});
|
|
669
|
+
const { serializedTx } = await signZcashTransactionWithSerializedTx(tx);
|
|
680
670
|
|
|
681
|
-
return
|
|
671
|
+
return toolbox.broadcastTx(serializedTx);
|
|
682
672
|
};
|
|
683
673
|
|
|
684
|
-
return {
|
|
685
|
-
...toolbox,
|
|
686
|
-
address,
|
|
687
|
-
signPCZT: signer.signPCZT,
|
|
688
|
-
signTransaction: signer.signTransaction,
|
|
689
|
-
transfer,
|
|
690
|
-
transferWithPCZT,
|
|
691
|
-
};
|
|
674
|
+
return { ...toolbox, address, signAndBroadcastTransaction, signPCZT: signer.signPCZT, transfer };
|
|
692
675
|
}
|
|
693
676
|
|
|
694
677
|
case Chain.Bitcoin:
|
|
@@ -1019,7 +1002,7 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1019
1002
|
const { tx, inputs: selectedInputs } = await toolbox.createTransaction({
|
|
1020
1003
|
assetValue: assetValue as any,
|
|
1021
1004
|
feeRate: txFeeRate,
|
|
1022
|
-
fetchTxHex:
|
|
1005
|
+
fetchTxHex: chain === Chain.Dash,
|
|
1023
1006
|
memo,
|
|
1024
1007
|
recipient,
|
|
1025
1008
|
sender: address,
|
|
@@ -1062,7 +1045,7 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1062
1045
|
const { tx, inputs } = await createTxMethod({
|
|
1063
1046
|
...rest,
|
|
1064
1047
|
feeRate,
|
|
1065
|
-
fetchTxHex:
|
|
1048
|
+
fetchTxHex: chain === Chain.Dash,
|
|
1066
1049
|
memo,
|
|
1067
1050
|
recipient,
|
|
1068
1051
|
sender: address,
|
|
@@ -1083,6 +1066,8 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1083
1066
|
const signAndBroadcastTransaction = shouldUseTrezorSerializedSigner(chain)
|
|
1084
1067
|
? async (tx: Transaction) => baseToolbox.broadcastTx(await signSerializedTransaction(tx))
|
|
1085
1068
|
: toolbox.signAndBroadcastTransaction;
|
|
1069
|
+
const walletSignTransaction = shouldUseTrezorPsbtSigner(chain) ? toolbox.signTransaction : signTransaction;
|
|
1070
|
+
const walletTransfer = shouldUseTrezorPsbtSigner(chain) ? toolbox.transfer : transfer;
|
|
1086
1071
|
|
|
1087
1072
|
async function getExtendedPublicKeyInfo({ accountIndex }: { accountIndex?: number } = {}) {
|
|
1088
1073
|
const TrezorConnect = (await import("@trezor/connect-web")).default;
|
|
@@ -1242,9 +1227,9 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1242
1227
|
getExtendedPublicKey,
|
|
1243
1228
|
getExtendedPublicKeyInfo,
|
|
1244
1229
|
signAndBroadcastTransaction,
|
|
1245
|
-
signTransaction,
|
|
1230
|
+
signTransaction: walletSignTransaction,
|
|
1246
1231
|
signTransactionWithMultipleInputs,
|
|
1247
|
-
transfer,
|
|
1232
|
+
transfer: walletTransfer,
|
|
1248
1233
|
transferFromMultipleAddresses,
|
|
1249
1234
|
};
|
|
1250
1235
|
}
|
|
@@ -1259,14 +1244,14 @@ export async function getTrezorExtendedPublicKey(
|
|
|
1259
1244
|
derivationPath?: DerivationPathArray,
|
|
1260
1245
|
{ accountIndex }: { accountIndex?: number } = {},
|
|
1261
1246
|
): Promise<HardwareExtendedPublicKeyInfo | undefined> {
|
|
1262
|
-
if (![Chain.BitcoinCash, Chain.Bitcoin, Chain.Dash, Chain.Dogecoin, Chain.Litecoin].includes(chain)) {
|
|
1247
|
+
if (![Chain.BitcoinCash, Chain.Bitcoin, Chain.Dash, Chain.Dogecoin, Chain.Litecoin, Chain.Zcash].includes(chain)) {
|
|
1263
1248
|
throw new SwapKitError({ errorKey: "wallet_chain_not_supported", info: { chain, wallet: WalletOption.TREZOR } });
|
|
1264
1249
|
}
|
|
1265
1250
|
|
|
1266
1251
|
const { TrezorConnect } = await initTrezorConnect();
|
|
1267
1252
|
const utxoChain = chain as UTXOChain;
|
|
1268
1253
|
const resolvedDerivationPath = derivationPath ?? (NetworkDerivationPath[chain] as DerivationPathArray);
|
|
1269
|
-
const coin = chain.toLowerCase();
|
|
1254
|
+
const coin = chain === Chain.Zcash ? "zcash" : chain.toLowerCase();
|
|
1270
1255
|
|
|
1271
1256
|
const resolvedAccountPath = getUTXOAccountPath({
|
|
1272
1257
|
accountIndex,
|
|
@@ -1388,7 +1373,7 @@ export const trezorWallet = createWallet({
|
|
|
1388
1373
|
[Chain.Optimism]: true,
|
|
1389
1374
|
[Chain.Polygon]: true,
|
|
1390
1375
|
[Chain.XLayer]: true,
|
|
1391
|
-
|
|
1376
|
+
[Chain.Zcash]: true,
|
|
1392
1377
|
},
|
|
1393
1378
|
getExtendedPublicKey: getTrezorExtendedPublicKey,
|
|
1394
1379
|
name: "connectTrezor",
|