Skip to content

Commit beda310

Browse files
chore(hardware-trezor): refactor TrezorKeyAgent to use Transform interface
1 parent bbc894c commit beda310

12 files changed

+180
-203
lines changed

packages/hardware-trezor/src/TrezorKeyAgent.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,13 @@ export class TrezorKeyAgent extends KeyAgentBase {
203203
}
204204

205205
async signTransaction(
206-
tx: Cardano.TxBodyWithHash,
206+
{ body, hash }: Cardano.TxBodyWithHash,
207207
{ knownAddresses, txInKeyPathMap }: SignTransactionContext
208208
): Promise<Cardano.Signatures> {
209209
try {
210210
await this.isTrezorInitialized;
211-
const trezorTxData = txToTrezor({
211+
const trezorTxData = await txToTrezor(body, {
212212
accountIndex: this.accountIndex,
213-
cardanoTxBody: tx.body,
214213
chainId: this.chainId,
215214
knownAddresses,
216215
txInKeyPathMap
@@ -226,7 +225,7 @@ export class TrezorKeyAgent extends KeyAgentBase {
226225

227226
const expectedPublicKeys = await Promise.all(
228227
util
229-
.ownSignatureKeyPaths(tx.body, knownAddresses, txInKeyPathMap)
228+
.ownSignatureKeyPaths(body, knownAddresses, txInKeyPathMap)
230229
.map((derivationPath) => this.derivePublicKey(derivationPath))
231230
);
232231

@@ -236,7 +235,7 @@ export class TrezorKeyAgent extends KeyAgentBase {
236235

237236
const signedData = result.payload;
238237

239-
if (signedData.hash !== tx.hash) {
238+
if (signedData.hash !== hash) {
240239
throw new errors.HwMappingError('Trezor computed a different transaction id');
241240
}
242241

packages/hardware-trezor/src/transformers/additionalWitnessRequests.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
import * as Trezor from '@trezor/connect';
2-
import { BIP32Path } from '@cardano-sdk/crypto';
2+
import { Cardano } from '@cardano-sdk/core';
3+
import { Transform, isNotNil } from '@cardano-sdk/util';
34
import { TrezorTxTransformerContext } from '../types';
4-
import { isNotNil } from '@cardano-sdk/util';
5+
import { resolvePaymentKeyPathForTxIn } from './keyPaths';
56
import { util } from '@cardano-sdk/key-management';
67
import isArray from 'lodash/isArray';
78
import uniq from 'lodash/uniq';
89

9-
export const mapAdditionalWitnessRequests = (inputs: Trezor.CardanoInput[], context: TrezorTxTransformerContext) => {
10-
const paymentKeyPaths = uniq<BIP32Path>(
10+
export const mapAdditionalWitnessRequests: Transform<
11+
Cardano.TxIn[],
12+
Trezor.DerivationPath[],
13+
TrezorTxTransformerContext
14+
> = (inputs, context) => {
15+
const paymentKeyPaths = uniq<Trezor.DerivationPath>(
1116
inputs
12-
.map((i) => i.path)
17+
.map((input) => resolvePaymentKeyPathForTxIn(input, context))
1318
.filter(isNotNil)
1419
.filter(isArray)
1520
);
16-
const additionalWitnessPaths: BIP32Path[] = [...paymentKeyPaths];
17-
if (context.knownAddresses.length > 0) {
21+
22+
const additionalWitnessPaths: Trezor.DerivationPath[] = [...paymentKeyPaths];
23+
24+
if (context?.knownAddresses?.length) {
1825
const stakeKeyPath = util.stakeKeyPathFromGroupedAddress(context.knownAddresses[0]);
1926
if (stakeKeyPath) additionalWitnessPaths.push(stakeKeyPath);
2027
}

packages/hardware-trezor/src/transformers/assets.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as Trezor from '@trezor/connect';
22
import { Cardano } from '@cardano-sdk/core';
3+
import { Transform } from '@cardano-sdk/util';
34

45
const compareAssetNameCanonically = (a: Trezor.CardanoToken, b: Trezor.CardanoToken) => {
56
if (a.assetNameBytes.length === b.assetNameBytes.length) {
@@ -12,7 +13,7 @@ const comparePolicyIdCanonically = (a: Trezor.CardanoAssetGroup, b: Trezor.Carda
1213
// PolicyId is always of the same length
1314
a.policyId > b.policyId ? 1 : -1;
1415

15-
const tokenMapToAssetGroup = (tokenMap: Cardano.TokenMap, isMint: boolean): Trezor.CardanoAssetGroup[] => {
16+
const tokenMapToAssetGroup: Transform<Cardano.TokenMap, Trezor.CardanoAssetGroup[]> = (tokenMap, isMint) => {
1617
const map = new Map<string, Array<Trezor.CardanoToken>>();
1718

1819
for (const [key, value] of tokenMap.entries()) {
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import * as Crypto from '@cardano-sdk/crypto';
22
import * as Trezor from '@trezor/connect';
3+
import { Transform } from '@cardano-sdk/util';
34

4-
export const mapAuxiliaryData = (auxiliaryDataHash: Crypto.Hash32ByteBase16): Trezor.CardanoAuxiliaryData => ({
5-
hash: auxiliaryDataHash
5+
export const mapAuxiliaryData: Transform<Crypto.Hash32ByteBase16, Trezor.CardanoAuxiliaryData> = (
6+
auxiliaryDataHash
7+
) => ({
8+
cVoteRegistrationParameters: undefined,
9+
hash: auxiliaryDataHash // Voting is not handled for now
610
});

packages/hardware-trezor/src/transformers/certificates.ts

+52-66
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,15 @@ import * as Trezor from '@trezor/connect';
33
import { BIP32Path } from '@cardano-sdk/crypto';
44
import { Cardano } from '@cardano-sdk/core';
55
import { GroupedAddress, util } from '@cardano-sdk/key-management';
6-
import { InvalidArgumentError /* , Transform*/ } from '@cardano-sdk/util';
6+
import { InvalidArgumentError, Transform } from '@cardano-sdk/util';
77
import { TrezorTxTransformerContext } from '../types';
88

9-
type StakeKeyCertificateType =
10-
| Trezor.PROTO.CardanoCertificateType.STAKE_REGISTRATION
11-
| Trezor.PROTO.CardanoCertificateType.STAKE_DEREGISTRATION;
12-
13-
type TrezorStakeKeyCertificate = {
14-
type: StakeKeyCertificateType;
15-
path?: BIP32Path;
9+
type CertCredentialsType = {
1610
scriptHash?: Crypto.Ed25519KeyHashHex;
1711
keyHash?: Crypto.Ed25519KeyHashHex;
18-
};
19-
20-
type TrezorDelegationCertificate = {
21-
type: Trezor.PROTO.CardanoCertificateType.STAKE_DELEGATION;
2212
path?: BIP32Path;
23-
scriptHash?: Crypto.Ed25519KeyHashHex;
24-
pool: string;
25-
};
26-
27-
type TrezorPoolRegistrationCertificate = {
28-
poolParameters: Trezor.CardanoPoolParameters;
29-
type: Trezor.PROTO.CardanoCertificateType.STAKE_POOL_REGISTRATION;
30-
};
31-
32-
type ScriptHashCertCredentials = {
33-
scriptHash: Crypto.Ed25519KeyHashHex;
34-
};
35-
36-
type KeyHashCertCredentials = {
37-
keyHash: Crypto.Ed25519KeyHashHex;
3813
};
3914

40-
type PathCertCredentials = {
41-
path: BIP32Path;
42-
};
43-
44-
type CertCredentialsType = ScriptHashCertCredentials | KeyHashCertCredentials | PathCertCredentials;
45-
4615
const getCertCredentials = (
4716
stakeKeyHash: Crypto.Ed25519KeyHashHex,
4817
knownAddresses: GroupedAddress[] | undefined
@@ -61,57 +30,73 @@ const getCertCredentials = (
6130
};
6231
};
6332

64-
const getStakeAddressCertificate = (
65-
certificate: Cardano.StakeAddressCertificate,
66-
context: TrezorTxTransformerContext,
67-
type: StakeKeyCertificateType
68-
): TrezorStakeKeyCertificate => {
33+
const toPoolMetadata = (metadataJson: Cardano.PoolMetadataJson): Trezor.CardanoPoolMetadata => ({
34+
hash: metadataJson.hash,
35+
url: metadataJson.url
36+
});
37+
38+
const getPoolOperatorKeyPath = (
39+
operator: Cardano.RewardAccount,
40+
context: TrezorTxTransformerContext
41+
): BIP32Path | null => {
42+
const knownAddress = context?.knownAddresses.find((address) => address.rewardAccount === operator);
43+
return util.stakeKeyPathFromGroupedAddress(knownAddress);
44+
};
45+
46+
export const getStakeAddressCertificate: Transform<
47+
Cardano.StakeAddressCertificate,
48+
Trezor.CardanoCertificate,
49+
TrezorTxTransformerContext
50+
> = (certificate, context) => {
6951
const credentials = getCertCredentials(
7052
certificate.stakeCredential.hash as unknown as Crypto.Ed25519KeyHashHex,
71-
context.knownAddresses
53+
context?.knownAddresses
7254
);
55+
const certificateType =
56+
certificate.__typename === Cardano.CertificateType.StakeRegistration
57+
? Trezor.PROTO.CardanoCertificateType.STAKE_REGISTRATION
58+
: Trezor.PROTO.CardanoCertificateType.STAKE_DEREGISTRATION;
7359
return {
74-
...credentials,
75-
type
60+
keyHash: credentials.keyHash,
61+
path: credentials.path,
62+
pool: undefined,
63+
poolParameters: undefined,
64+
scriptHash: credentials.scriptHash,
65+
type: certificateType
7666
};
7767
};
7868

79-
const getStakeDelegationCertificate = (
80-
certificate: Cardano.StakeDelegationCertificate,
81-
context: TrezorTxTransformerContext
82-
): TrezorDelegationCertificate => {
69+
export const getStakeDelegationCertificate: Transform<
70+
Cardano.StakeDelegationCertificate,
71+
Trezor.CardanoCertificate,
72+
TrezorTxTransformerContext
73+
> = (certificate, context) => {
8374
const poolIdKeyHash = Cardano.PoolId.toKeyHash(certificate.poolId);
8475
const credentials = getCertCredentials(
8576
certificate.stakeCredential.hash as unknown as Crypto.Ed25519KeyHashHex,
86-
context.knownAddresses
77+
context?.knownAddresses
8778
);
8879
return {
89-
...credentials,
80+
keyHash: credentials.keyHash,
81+
path: credentials.path,
9082
pool: poolIdKeyHash,
83+
poolParameters: undefined,
84+
scriptHash: credentials.scriptHash,
9185
type: Trezor.PROTO.CardanoCertificateType.STAKE_DELEGATION
9286
};
9387
};
9488

95-
const toPoolMetadata = (metadataJson: Cardano.PoolMetadataJson): Trezor.CardanoPoolMetadata => ({
96-
hash: metadataJson.hash,
97-
url: metadataJson.url
98-
});
99-
100-
const getPoolOperatorKeyPath = (
101-
operator: Cardano.RewardAccount,
102-
context: TrezorTxTransformerContext
103-
): BIP32Path | null => {
104-
const knownAddress = context?.knownAddresses.find((address) => address.rewardAccount === operator);
105-
return util.stakeKeyPathFromGroupedAddress(knownAddress);
106-
};
107-
108-
export const getPoolRegistrationCertificate = (
109-
certificate: Cardano.PoolRegistrationCertificate,
110-
context: TrezorTxTransformerContext
111-
): TrezorPoolRegistrationCertificate => {
89+
export const getPoolRegistrationCertificate: Transform<
90+
Cardano.PoolRegistrationCertificate,
91+
Trezor.CardanoCertificate,
92+
TrezorTxTransformerContext
93+
> = (certificate, context) => {
11294
if (!certificate.poolParameters.metadataJson)
11395
throw new InvalidArgumentError('certificate', 'Missing pool registration pool metadata.');
11496
return {
97+
keyHash: undefined,
98+
path: undefined,
99+
pool: undefined,
115100
poolParameters: {
116101
cost: certificate.poolParameters.cost.toString(),
117102
margin: {
@@ -153,16 +138,17 @@ export const getPoolRegistrationCertificate = (
153138
rewardAccount: certificate.poolParameters.rewardAccount,
154139
vrfKeyHash: certificate.poolParameters.vrf
155140
},
141+
scriptHash: undefined,
156142
type: Trezor.PROTO.CardanoCertificateType.STAKE_POOL_REGISTRATION
157143
};
158144
};
159145

160146
const toCert = (cert: Cardano.Certificate, context: TrezorTxTransformerContext) => {
161147
switch (cert.__typename) {
162148
case Cardano.CertificateType.StakeRegistration:
163-
return getStakeAddressCertificate(cert, context, Trezor.PROTO.CardanoCertificateType.STAKE_REGISTRATION);
149+
return getStakeAddressCertificate(cert, context);
164150
case Cardano.CertificateType.StakeDeregistration:
165-
return getStakeAddressCertificate(cert, context, Trezor.PROTO.CardanoCertificateType.STAKE_DEREGISTRATION);
151+
return getStakeAddressCertificate(cert, context);
166152
case Cardano.CertificateType.StakeDelegation:
167153
return getStakeDelegationCertificate(cert, context);
168154
case Cardano.CertificateType.PoolRegistration:

packages/hardware-trezor/src/transformers/keyPaths.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ export const resolvePaymentKeyPathForTxIn = (
1515
}
1616
};
1717

18-
// Resolves the stake key path for known addresses for the given reward address.
1918
export const resolveStakeKeyPath = (
2019
rewardAddress: Cardano.RewardAddress | undefined,
21-
context: TrezorTxTransformerContext
20+
context?: TrezorTxTransformerContext
2221
): BIP32Path | null => {
2322
if (!rewardAddress) return null;
24-
const knownAddress = context.knownAddresses.find(
23+
24+
const knownAddress = context?.knownAddresses.find(
2525
({ rewardAccount }) => rewardAccount === rewardAddress.toAddress().toBech32()
2626
);
2727
return util.stakeKeyPathFromGroupedAddress(knownAddress);

packages/hardware-trezor/src/transformers/requiredSigners.ts

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,48 @@
11
import * as Crypto from '@cardano-sdk/crypto';
22
import * as Trezor from '@trezor/connect';
33
import { Cardano } from '@cardano-sdk/core';
4+
import { Transform } from '@cardano-sdk/util';
45
import { TrezorTxTransformerContext } from '../types';
56
import { util } from '@cardano-sdk/key-management';
67

7-
export const toRequiredSigner = (
8-
signer: Crypto.Ed25519KeyHashHex,
9-
context: TrezorTxTransformerContext
10-
): Trezor.CardanoRequiredSigner => {
8+
export const toRequiredSigner: Transform<
9+
Crypto.Ed25519KeyHashHex,
10+
Trezor.CardanoRequiredSigner,
11+
TrezorTxTransformerContext
12+
> = (keyHash, context) => {
1113
const paymentCredKnownAddress = context?.knownAddresses.find((address) => {
1214
const paymentCredential = Cardano.Address.fromBech32(address.address)?.asBase()?.getPaymentCredential().hash;
13-
return paymentCredential && paymentCredential.toString() === signer;
15+
return paymentCredential && paymentCredential.toString() === keyHash;
1416
});
1517

1618
const stakeCredKnownAddress = context?.knownAddresses.find((address) => {
1719
const stakeCredential = Cardano.RewardAccount.toHash(address.rewardAccount);
18-
return stakeCredential && stakeCredential.toString() === signer;
20+
return stakeCredential && stakeCredential.toString() === keyHash;
1921
});
2022

2123
const paymentKeyPath = paymentCredKnownAddress
2224
? util.paymentKeyPathFromGroupedAddress(paymentCredKnownAddress)
2325
: null;
2426
const stakeKeyPath = stakeCredKnownAddress ? util.stakeKeyPathFromGroupedAddress(stakeCredKnownAddress) : null;
2527

26-
return paymentKeyPath ? { keyPath: paymentKeyPath } : stakeKeyPath ? { keyPath: stakeKeyPath } : { keyHash: signer };
28+
if (paymentKeyPath) {
29+
return {
30+
keyHash: undefined,
31+
keyPath: paymentKeyPath
32+
};
33+
}
34+
35+
if (stakeKeyPath) {
36+
return {
37+
keyHash: undefined,
38+
keyPath: stakeKeyPath
39+
};
40+
}
41+
42+
return {
43+
keyHash,
44+
keyPath: undefined
45+
};
2746
};
2847

2948
export const mapRequiredSigners = (

0 commit comments

Comments
 (0)