@swapkit/wallet-hardware 4.9.14 → 4.9.15
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,115 @@ 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 signZcashTransaction = 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 parseSignedZcashTransaction(result.payload.serializedTx);
|
|
603
|
+
}
|
|
628
604
|
|
|
629
|
-
|
|
605
|
+
throw new SwapKitError({
|
|
606
|
+
errorKey: "wallet_trezor_failed_to_sign_transaction",
|
|
607
|
+
info: { chain, error: (result.payload as { error: string; code?: string }).error },
|
|
608
|
+
});
|
|
630
609
|
};
|
|
631
610
|
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
throw new SwapKitError({
|
|
635
|
-
errorKey: "wallet_missing_params",
|
|
636
|
-
info: { address, recipient: params.recipient, wallet: WalletOption.TREZOR },
|
|
637
|
-
});
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
const { createPCZT, OutScript } = await import("@swapkit/utxo-signer");
|
|
641
|
-
const { hex: hexEncode } = await import("@scure/base");
|
|
642
|
-
const { getUtxoApi } = await import("@swapkit/toolboxes/utxo");
|
|
611
|
+
const signer = {
|
|
612
|
+
getAddress: async () => address,
|
|
643
613
|
|
|
644
|
-
|
|
614
|
+
signPCZT: async (pczt: PCZT): Promise<PCZT> => {
|
|
615
|
+
return (await signPCZTWithSerializedTx(pczt)).signedPczt;
|
|
616
|
+
},
|
|
645
617
|
|
|
646
|
-
|
|
618
|
+
signTransaction: async (tx: ZcashSignableTransaction): Promise<ZcashTransaction> => {
|
|
619
|
+
if ("toPCZT" in tx) {
|
|
620
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx.toPCZT());
|
|
621
|
+
return parseSignedZcashTransaction(serializedTx);
|
|
622
|
+
}
|
|
647
623
|
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
sender: address,
|
|
653
|
-
});
|
|
624
|
+
if ("getGlobal" in tx) {
|
|
625
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx);
|
|
626
|
+
return parseSignedZcashTransaction(serializedTx);
|
|
627
|
+
}
|
|
654
628
|
|
|
655
|
-
|
|
629
|
+
return signZcashTransaction(tx);
|
|
630
|
+
},
|
|
631
|
+
};
|
|
656
632
|
|
|
657
|
-
|
|
658
|
-
const utxo = utxos.find((u) => u.hash === utxoInput.hash && u.index === utxoInput.index);
|
|
659
|
-
const scriptPubkey = utxo?.witnessUtxo?.script
|
|
660
|
-
? new Uint8Array(utxo.witnessUtxo.script)
|
|
661
|
-
: OutScript.encode({ hash: hexEncode.decode((utxoInput as any).address || ""), type: "pkh" });
|
|
633
|
+
const toolbox = getUtxoToolbox(Chain.Zcash, { signer });
|
|
662
634
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
value: BigInt(utxoInput.value),
|
|
668
|
-
});
|
|
635
|
+
const signAndBroadcastTransaction = async (tx: ZcashSignableTransaction) => {
|
|
636
|
+
if ("toPCZT" in tx) {
|
|
637
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx.toPCZT());
|
|
638
|
+
return toolbox.broadcastTx(serializedTx);
|
|
669
639
|
}
|
|
670
640
|
|
|
671
|
-
|
|
672
|
-
const
|
|
673
|
-
|
|
641
|
+
if ("getGlobal" in tx) {
|
|
642
|
+
const { serializedTx } = await signPCZTWithSerializedTx(tx);
|
|
643
|
+
return toolbox.broadcastTx(serializedTx);
|
|
674
644
|
}
|
|
675
645
|
|
|
676
|
-
|
|
677
|
-
signedPczt.finalizeAllInputs();
|
|
678
|
-
const finalTx = signedPczt.extract();
|
|
679
|
-
const broadcastResult = await toolbox.broadcastTx(finalTx.toHex());
|
|
680
|
-
|
|
681
|
-
return broadcastResult;
|
|
646
|
+
return toolbox.signAndBroadcastTransaction(tx);
|
|
682
647
|
};
|
|
683
648
|
|
|
684
|
-
return {
|
|
685
|
-
...toolbox,
|
|
686
|
-
address,
|
|
687
|
-
signPCZT: signer.signPCZT,
|
|
688
|
-
signTransaction: signer.signTransaction,
|
|
689
|
-
transfer,
|
|
690
|
-
transferWithPCZT,
|
|
691
|
-
};
|
|
649
|
+
return { ...toolbox, address, signAndBroadcastTransaction, signPCZT: signer.signPCZT };
|
|
692
650
|
}
|
|
693
651
|
|
|
694
652
|
case Chain.Bitcoin:
|
|
@@ -1019,7 +977,7 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1019
977
|
const { tx, inputs: selectedInputs } = await toolbox.createTransaction({
|
|
1020
978
|
assetValue: assetValue as any,
|
|
1021
979
|
feeRate: txFeeRate,
|
|
1022
|
-
fetchTxHex:
|
|
980
|
+
fetchTxHex: chain === Chain.Dash,
|
|
1023
981
|
memo,
|
|
1024
982
|
recipient,
|
|
1025
983
|
sender: address,
|
|
@@ -1062,7 +1020,7 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1062
1020
|
const { tx, inputs } = await createTxMethod({
|
|
1063
1021
|
...rest,
|
|
1064
1022
|
feeRate,
|
|
1065
|
-
fetchTxHex:
|
|
1023
|
+
fetchTxHex: chain === Chain.Dash,
|
|
1066
1024
|
memo,
|
|
1067
1025
|
recipient,
|
|
1068
1026
|
sender: address,
|
|
@@ -1083,6 +1041,8 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1083
1041
|
const signAndBroadcastTransaction = shouldUseTrezorSerializedSigner(chain)
|
|
1084
1042
|
? async (tx: Transaction) => baseToolbox.broadcastTx(await signSerializedTransaction(tx))
|
|
1085
1043
|
: toolbox.signAndBroadcastTransaction;
|
|
1044
|
+
const walletSignTransaction = shouldUseTrezorPsbtSigner(chain) ? toolbox.signTransaction : signTransaction;
|
|
1045
|
+
const walletTransfer = shouldUseTrezorPsbtSigner(chain) ? toolbox.transfer : transfer;
|
|
1086
1046
|
|
|
1087
1047
|
async function getExtendedPublicKeyInfo({ accountIndex }: { accountIndex?: number } = {}) {
|
|
1088
1048
|
const TrezorConnect = (await import("@trezor/connect-web")).default;
|
|
@@ -1242,9 +1202,9 @@ async function getTrezorWallet<T extends Chain>({
|
|
|
1242
1202
|
getExtendedPublicKey,
|
|
1243
1203
|
getExtendedPublicKeyInfo,
|
|
1244
1204
|
signAndBroadcastTransaction,
|
|
1245
|
-
signTransaction,
|
|
1205
|
+
signTransaction: walletSignTransaction,
|
|
1246
1206
|
signTransactionWithMultipleInputs,
|
|
1247
|
-
transfer,
|
|
1207
|
+
transfer: walletTransfer,
|
|
1248
1208
|
transferFromMultipleAddresses,
|
|
1249
1209
|
};
|
|
1250
1210
|
}
|
|
@@ -1259,14 +1219,14 @@ export async function getTrezorExtendedPublicKey(
|
|
|
1259
1219
|
derivationPath?: DerivationPathArray,
|
|
1260
1220
|
{ accountIndex }: { accountIndex?: number } = {},
|
|
1261
1221
|
): Promise<HardwareExtendedPublicKeyInfo | undefined> {
|
|
1262
|
-
if (![Chain.BitcoinCash, Chain.Bitcoin, Chain.Dash, Chain.Dogecoin, Chain.Litecoin].includes(chain)) {
|
|
1222
|
+
if (![Chain.BitcoinCash, Chain.Bitcoin, Chain.Dash, Chain.Dogecoin, Chain.Litecoin, Chain.Zcash].includes(chain)) {
|
|
1263
1223
|
throw new SwapKitError({ errorKey: "wallet_chain_not_supported", info: { chain, wallet: WalletOption.TREZOR } });
|
|
1264
1224
|
}
|
|
1265
1225
|
|
|
1266
1226
|
const { TrezorConnect } = await initTrezorConnect();
|
|
1267
1227
|
const utxoChain = chain as UTXOChain;
|
|
1268
1228
|
const resolvedDerivationPath = derivationPath ?? (NetworkDerivationPath[chain] as DerivationPathArray);
|
|
1269
|
-
const coin = chain.toLowerCase();
|
|
1229
|
+
const coin = chain === Chain.Zcash ? "zcash" : chain.toLowerCase();
|
|
1270
1230
|
|
|
1271
1231
|
const resolvedAccountPath = getUTXOAccountPath({
|
|
1272
1232
|
accountIndex,
|
|
@@ -1388,7 +1348,7 @@ export const trezorWallet = createWallet({
|
|
|
1388
1348
|
[Chain.Optimism]: true,
|
|
1389
1349
|
[Chain.Polygon]: true,
|
|
1390
1350
|
[Chain.XLayer]: true,
|
|
1391
|
-
|
|
1351
|
+
[Chain.Zcash]: true,
|
|
1392
1352
|
},
|
|
1393
1353
|
getExtendedPublicKey: getTrezorExtendedPublicKey,
|
|
1394
1354
|
name: "connectTrezor",
|