diff --git a/packages/e2e/package.json b/packages/e2e/package.json index 9614ff6a0f1..bf7e21320b5 100644 --- a/packages/e2e/package.json +++ b/packages/e2e/package.json @@ -78,7 +78,7 @@ "access": "public" }, "dependencies": { - "@cardano-foundation/ledgerjs-hw-app-cardano": "^6.0.0", + "@cardano-foundation/ledgerjs-hw-app-cardano": "^7.0.0", "@cardano-ogmios/client": "5.6.0", "@cardano-sdk/cardano-services": "workspace:~", "@cardano-sdk/cardano-services-client": "workspace:~", diff --git a/packages/hardware-ledger/src/LedgerKeyAgent.ts b/packages/hardware-ledger/src/LedgerKeyAgent.ts index 64f078023d5..6bc223402f1 100644 --- a/packages/hardware-ledger/src/LedgerKeyAgent.ts +++ b/packages/hardware-ledger/src/LedgerKeyAgent.ts @@ -21,11 +21,11 @@ import TransportNodeHid from '@ledgerhq/hw-transport-node-hid-noevents'; import _LedgerConnection, { Certificate, CertificateType, + CredentialParams, + CredentialParamsType, GetVersionResponse, PoolKeyType, PoolOwnerType, - StakeCredentialParams, - StakeCredentialParamsType, Transaction, TransactionSigningMode, TxOutputDestinationType @@ -127,12 +127,12 @@ const parseEstablishDeviceConnectionSecondParam = ( }; interface StakeCredentialCertificateParams { - stakeCredential: StakeCredentialParams; + stakeCredential: CredentialParams; } const containsOnlyScriptHashCreds = (tx: Transaction): boolean => { const withdrawalsAllScriptHash = !tx.withdrawals?.some( - (withdrawal) => withdrawal.stakeCredential.type !== StakeCredentialParamsType.SCRIPT_HASH + (withdrawal) => withdrawal.stakeCredential.type !== CredentialParamsType.SCRIPT_HASH ); if (tx.certificates) { @@ -140,7 +140,7 @@ const containsOnlyScriptHashCreds = (tx: Transaction): boolean => { if (!stakeCredentialCert(cert)) return false; const certParams = cert.params as unknown as StakeCredentialCertificateParams; - if (certParams.stakeCredential.type !== StakeCredentialParamsType.SCRIPT_HASH) return false; + if (certParams.stakeCredential.type !== CredentialParamsType.SCRIPT_HASH) return false; } } diff --git a/packages/hardware-ledger/src/transformers/certificates.ts b/packages/hardware-ledger/src/transformers/certificates.ts index 22b6148f1c7..c5eda015a37 100644 --- a/packages/hardware-ledger/src/transformers/certificates.ts +++ b/packages/hardware-ledger/src/transformers/certificates.ts @@ -2,9 +2,9 @@ import * as Crypto from '@cardano-sdk/crypto'; import * as Ledger from '@cardano-foundation/ledgerjs-hw-app-cardano'; import { Cardano } from '@cardano-sdk/core'; +import { GroupedAddress, util } from '@cardano-sdk/key-management'; import { InvalidArgumentError, Transform } from '@cardano-sdk/util'; import { LedgerTxTransformerContext } from '../types'; -import { util } from '@cardano-sdk/key-management'; const mapAnchorToParams = (certificate: Cardano.Certificate) => ({ ...('anchor' in certificate && @@ -43,65 +43,106 @@ const credentialMapper = ( return credentialParams; }; -const stakeCredentialMapper = ( - credential: Cardano.Credential, - context: LedgerTxTransformerContext -): Ledger.CredentialParams => { - const knownAddress = context?.knownAddresses.find( +const drepParamsMapper = ( + drep: Cardano.Credential, + credentialType: Cardano.CredentialType | Ledger.CredentialParamsType.SCRIPT_HASH, + path: Crypto.BIP32Path | null +): Ledger.KeyPathDRepParams | Ledger.KeyHashDRepParams | Ledger.ScriptHashDRepParams => { + let dRepParams: Ledger.DRepParams; + + switch (credentialType) { + case Cardano.CredentialType.KeyHash: { + dRepParams = path + ? { + keyPath: path, + type: Ledger.DRepParamsType.KEY_PATH + } + : { + keyHashHex: drep.hash, + type: Ledger.DRepParamsType.KEY_HASH + }; + break; + } + case Cardano.CredentialType.ScriptHash: + default: { + dRepParams = { + scriptHashHex: drep.hash, + type: Ledger.DRepParamsType.SCRIPT_HASH + }; + } + } + + return dRepParams; +}; + +const getKnownAddress = (credential: Cardano.Credential, context: LedgerTxTransformerContext) => + context?.knownAddresses.find( (address) => Cardano.RewardAccount.toHash(address.rewardAccount) === (credential.hash as unknown as Crypto.Ed25519KeyHashHex) ); +const getCredentialType = (knownAddress: GroupedAddress | undefined) => { const rewardAddress = knownAddress ? Cardano.Address.fromBech32(knownAddress.rewardAccount)?.asReward() : null; + return rewardAddress ? rewardAddress.getPaymentCredential().type : Ledger.CredentialParamsType.SCRIPT_HASH; +}; + +const stakeCredentialMapper = (credential: Cardano.Credential, context: LedgerTxTransformerContext) => { + const knownAddress = getKnownAddress(credential, context); + const credentialType = getCredentialType(knownAddress); const path = util.stakeKeyPathFromGroupedAddress(knownAddress); - const credentialType = rewardAddress - ? rewardAddress.getPaymentCredential().type - : Ledger.CredentialParamsType.SCRIPT_HASH; return credentialMapper(credential, credentialType, path); }; -const getStakeAddressCertificate = ( - certificate: Cardano.StakeAddressCertificate, - context: LedgerTxTransformerContext, - type: Ledger.CertificateType.STAKE_REGISTRATION | Ledger.CertificateType.STAKE_DEREGISTRATION -): Ledger.Certificate => ({ +const getStakeAddressCertificate: Transform< + Cardano.StakeAddressCertificate, + Ledger.Certificate, + LedgerTxTransformerContext +> = (certificate, context): Ledger.Certificate => ({ params: { - stakeCredential: stakeCredentialMapper(certificate.stakeCredential, context) + stakeCredential: stakeCredentialMapper(certificate.stakeCredential, context!) }, - type + type: + certificate.__typename === Cardano.CertificateType.StakeRegistration + ? Ledger.CertificateType.STAKE_REGISTRATION + : Ledger.CertificateType.STAKE_DEREGISTRATION }); -const getNewStakeAddressCertificate = ( - certificate: Cardano.NewStakeAddressCertificate, - context: LedgerTxTransformerContext, - type: Ledger.CertificateType.STAKE_REGISTRATION_CONWAY | Ledger.CertificateType.STAKE_DEREGISTRATION_CONWAY -): Ledger.Certificate => ({ +const getNewStakeAddressCertificate: Transform< + Cardano.NewStakeAddressCertificate, + Ledger.Certificate, + LedgerTxTransformerContext +> = (certificate, context): Ledger.Certificate => ({ params: { deposit: certificate.deposit, - stakeCredential: stakeCredentialMapper(certificate.stakeCredential, context) + stakeCredential: stakeCredentialMapper(certificate.stakeCredential, context!) }, - type + type: + certificate.__typename === Cardano.CertificateType.Registration + ? Ledger.CertificateType.STAKE_REGISTRATION_CONWAY + : Ledger.CertificateType.STAKE_DEREGISTRATION_CONWAY }); -const getAuthorizeCommitteeHotCertificate = ( - certificate: Cardano.AuthorizeCommitteeHotCertificate, - context: LedgerTxTransformerContext -): Ledger.Certificate => ({ +const getAuthorizeCommitteeHotCertificate: Transform< + Cardano.AuthorizeCommitteeHotCertificate, + Ledger.Certificate, + LedgerTxTransformerContext +> = (certificate, context): Ledger.Certificate => ({ params: { - coldCredential: stakeCredentialMapper(certificate.coldCredential, context), - hotCredential: stakeCredentialMapper(certificate.hotCredential, context) + coldCredential: stakeCredentialMapper(certificate.coldCredential, context!), + hotCredential: stakeCredentialMapper(certificate.hotCredential, context!) }, type: Ledger.CertificateType.AUTHORIZE_COMMITTEE_HOT }); -const getResignCommitteeColdCertificate = ( - certificate: Cardano.ResignCommitteeColdCertificate, - context: LedgerTxTransformerContext -): Ledger.Certificate => ({ +const getResignCommitteeColdCertificate: Transform< + Cardano.ResignCommitteeColdCertificate, + Ledger.Certificate, + LedgerTxTransformerContext +> = (certificate, context): Ledger.Certificate => ({ params: { ...mapAnchorToParams(certificate), - coldCredential: stakeCredentialMapper(certificate.coldCredential, context) + coldCredential: stakeCredentialMapper(certificate.coldCredential, context!) }, type: Ledger.CertificateType.RESIGN_COMMITTEE_COLD }); @@ -257,14 +298,11 @@ const checkDrepPublicKeyAgainstCredential = ( } }; -const drepRegistrationCertificate = ( - certificate: Cardano.RegisterDelegateRepresentativeCertificate | Cardano.UnRegisterDelegateRepresentativeCertificate, - context: LedgerTxTransformerContext, - type: Extract< - Ledger.CertificateType, - Ledger.CertificateType.DREP_REGISTRATION | Ledger.CertificateType.DREP_DEREGISTRATION - > -): Ledger.Certificate => { +const drepRegistrationCertificate: Transform< + Cardano.RegisterDelegateRepresentativeCertificate | Cardano.UnRegisterDelegateRepresentativeCertificate, + Ledger.Certificate, + LedgerTxTransformerContext +> = (certificate, context): Ledger.Certificate => { checkDrepPublicKeyAgainstCredential(context?.dRepPublicKey, certificate.dRepCredential.hash); const params: Ledger.DRepRegistrationParams = { @@ -275,43 +313,14 @@ const drepRegistrationCertificate = ( return { params, - type + type: + certificate.__typename === Cardano.CertificateType.RegisterDelegateRepresentative + ? Ledger.CertificateType.DREP_REGISTRATION + : Ledger.CertificateType.DREP_DEREGISTRATION }; }; -const drepParamsMapper = ( - drep: Cardano.Credential, - path: Crypto.BIP32Path | null -): Ledger.KeyPathDRepParams | Ledger.KeyHashDRepParams | Ledger.ScriptHashDRepParams => { - let dRepParams: Ledger.DRepParams; - - switch (drep.type) { - case Cardano.CredentialType.KeyHash: { - dRepParams = path - ? { - keyPath: path, - type: Ledger.DRepParamsType.KEY_PATH - } - : { - keyHashHex: drep.hash, - type: Ledger.DRepParamsType.KEY_HASH - }; - break; - } - case Cardano.CredentialType.ScriptHash: - default: { - dRepParams = { - scriptHashHex: drep.hash, - type: Ledger.DRepParamsType.SCRIPT_HASH - }; - } - } - - return dRepParams; -}; - -// TODO: do we need to do the same as in stakeCredentialMapper? -const drepMapper = (drep: Cardano.DelegateRepresentative): Ledger.DRepParams => { +const drepMapper = (drep: Cardano.DelegateRepresentative, context: LedgerTxTransformerContext): Ledger.DRepParams => { if (Cardano.isDRepAlwaysAbstain(drep)) { return { type: Ledger.DRepParamsType.ABSTAIN @@ -321,18 +330,33 @@ const drepMapper = (drep: Cardano.DelegateRepresentative): Ledger.DRepParams => type: Ledger.DRepParamsType.NO_CONFIDENCE }; } else if (Cardano.isDRepCredential(drep)) { - // TODO: review - return drepParamsMapper(drep, null); + return drepParamsMapper( + drep, + drep.type, + util.accountKeyDerivationPathToBip32Path(context.accountIndex, util.DREP_KEY_DERIVATION_PATH) + ); } throw new Error('incorrect drep supplied'); }; +export const voteDelegationCertificate: Transform< + Cardano.VoteDelegationCertificate, + Ledger.Certificate, + LedgerTxTransformerContext +> = (certificate, context): Ledger.Certificate => ({ + params: { + dRep: drepMapper(certificate.dRep, context!), + stakeCredential: stakeCredentialMapper(certificate.stakeCredential, context!) + }, + type: Ledger.CertificateType.VOTE_DELEGATION +}); + const toCert = (cert: Cardano.Certificate, context: LedgerTxTransformerContext): Ledger.Certificate => { switch (cert.__typename) { case Cardano.CertificateType.StakeRegistration: - return getStakeAddressCertificate(cert, context, Ledger.CertificateType.STAKE_REGISTRATION); + return getStakeAddressCertificate(cert, context); case Cardano.CertificateType.StakeDeregistration: - return getStakeAddressCertificate(cert, context, Ledger.CertificateType.STAKE_DEREGISTRATION); + return getStakeAddressCertificate(cert, context); case Cardano.CertificateType.StakeDelegation: return stakeDelegationCertificate(cert, context); case Cardano.CertificateType.PoolRegistration: @@ -342,26 +366,19 @@ const toCert = (cert: Cardano.Certificate, context: LedgerTxTransformerContext): // Conway Era Certs case Cardano.CertificateType.Registration: - return getNewStakeAddressCertificate(cert, context, Ledger.CertificateType.STAKE_DEREGISTRATION_CONWAY); + return getNewStakeAddressCertificate(cert, context); case Cardano.CertificateType.Unregistration: - return getNewStakeAddressCertificate(cert, context, Ledger.CertificateType.STAKE_DEREGISTRATION_CONWAY); + return getNewStakeAddressCertificate(cert, context); case Cardano.CertificateType.VoteDelegation: - return { - params: { - // TODO: review - dRep: drepMapper(cert.dRep), - stakeCredential: stakeCredentialMapper(cert.stakeCredential, context) - }, - type: Ledger.CertificateType.VOTE_DELEGATION - }; + return voteDelegationCertificate(cert, context); case Cardano.CertificateType.AuthorizeCommitteeHot: return getAuthorizeCommitteeHotCertificate(cert, context); case Cardano.CertificateType.ResignCommitteeCold: return getResignCommitteeColdCertificate(cert, context); case Cardano.CertificateType.RegisterDelegateRepresentative: - return drepRegistrationCertificate(cert, context, Ledger.CertificateType.DREP_REGISTRATION); + return drepRegistrationCertificate(cert, context); case Cardano.CertificateType.UnregisterDelegateRepresentative: - return drepRegistrationCertificate(cert, context, Ledger.CertificateType.DREP_DEREGISTRATION); + return drepRegistrationCertificate(cert, context); case Cardano.CertificateType.UpdateDelegateRepresentative: default: throw new InvalidArgumentError('cert', `Certificate ${cert.__typename} not supported.`); diff --git a/packages/wallet/package.json b/packages/wallet/package.json index 3f1259b1c0d..d45bf440241 100644 --- a/packages/wallet/package.json +++ b/packages/wallet/package.json @@ -41,7 +41,7 @@ "test:e2e": "echo 'test:e2e' command not implemented yet" }, "devDependencies": { - "@cardano-foundation/ledgerjs-hw-app-cardano": "^6.0.0", + "@cardano-foundation/ledgerjs-hw-app-cardano": "^7.0.0", "@cardano-ogmios/client": "5.6.0", "@cardano-sdk/cardano-services-client": "workspace:~", "@cardano-sdk/ogmios": "workspace:~", diff --git a/yarn-project.nix b/yarn-project.nix index e64e812e15f..fb5f0fb53eb 100644 --- a/yarn-project.nix +++ b/yarn-project.nix @@ -383,7 +383,6 @@ cacheEntries = { "@blockfrost/blockfrost-js@npm:5.2.0" = { filename = "@blockfrost-blockfrost-js-npm-5.2.0-5dd47056e0-285a000e95.zip"; sha512 = "285a000e95c83be4d10da903f4a2a145b4c8d01ba8a3fce37e6f1b3211e97c5d1f317d923fe81dc6b8beff5e1eeee2b68728db589f8ec46eb6c00069f306bdf2"; }; "@blockfrost/blockfrost-utils@npm:2.0.0" = { filename = "@blockfrost-blockfrost-utils-npm-2.0.0-d53fbe4bc6-51e613d14e.zip"; sha512 = "51e613d14e792a957e339bfcf0e428127e659a199a4a6a3deff41751155befb1869c3d6da29afab11a2bd431dfa4839b0e812e8c38eb89b1584661a092bf8885"; }; "@blockfrost/openapi@npm:0.1.49" = { filename = "@blockfrost-openapi-npm-0.1.49-88a1c99db2-cab0b3ec06.zip"; sha512 = "cab0b3ec0677d9a82e0cb0a6b02b5e7a4d5b0ad7ba5e6bf969142e6262eacf947f94c4d0bed397fb38e9983c20b78ed66b4b1dfab7bab7d19b38605156ee693d"; }; -"@cardano-foundation/ledgerjs-hw-app-cardano@npm:6.0.0" = { filename = "@cardano-foundation-ledgerjs-hw-app-cardano-npm-6.0.0-615cff0cfb-6767792e68.zip"; sha512 = "6767792e68bd72333423eda25203b69a9686ee12602503e98037c68fc95abb74ceefc4cc1661579720fa3ecb822c4d30e0f0979fee9c8ef476668d4ee99df561"; }; "@cardano-foundation/ledgerjs-hw-app-cardano@npm:7.0.1" = { filename = "@cardano-foundation-ledgerjs-hw-app-cardano-npm-7.0.1-77358e2504-6ed9ae6804.zip"; sha512 = "6ed9ae68049a45b7175d027bb76c02f67dde10d454b35b1f34960195c90d99a867b5ec2dc2ff8dc5c54f0da9df5c2da33c6e2dcf491ab1fce284f4f74d89fd7a"; }; "@cardano-ogmios/client@npm:5.6.0" = { filename = "@cardano-ogmios-client-npm-5.6.0-e3f0ec5f2b-4d15f7a1c6.zip"; sha512 = "4d15f7a1c6178d3f83d13a8fc9af8fc054d552a5db322ff2ec952d4876f131a0d2940a4ecd9663d4497e00392743f5a04867654984ca8f466b2253cd76d09d05"; }; "@cardano-ogmios/schema@npm:5.6.0" = { filename = "@cardano-ogmios-schema-npm-5.6.0-6e5d8ece12-82d9ba119f.zip"; sha512 = "82d9ba119fd0bb54e1857bc436778f9677c99bb1ca2fe213567b05758e2fbd6bbef540c83bce53850db1f16a50c62e6522b7d792e7bd85f058a835399520b70a"; }; diff --git a/yarn.lock b/yarn.lock index 432c4d6731e..1f44e81967a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3072,18 +3072,6 @@ __metadata: languageName: node linkType: hard -"@cardano-foundation/ledgerjs-hw-app-cardano@npm:^6.0.0": - version: 6.0.0 - resolution: "@cardano-foundation/ledgerjs-hw-app-cardano@npm:6.0.0" - dependencies: - "@ledgerhq/hw-transport": ^6.27.10 - base-x: ^3.0.5 - bech32: ^1.1.4 - int64-buffer: ^1.0.1 - checksum: 6767792e68bd72333423eda25203b69a9686ee12602503e98037c68fc95abb74ceefc4cc1661579720fa3ecb822c4d30e0f0979fee9c8ef476668d4ee99df561 - languageName: node - linkType: hard - "@cardano-foundation/ledgerjs-hw-app-cardano@npm:^7.0.0": version: 7.0.1 resolution: "@cardano-foundation/ledgerjs-hw-app-cardano@npm:7.0.1" @@ -3321,7 +3309,7 @@ __metadata: "@babel/core": ^7.18.2 "@babel/preset-env": ^7.18.2 "@babel/preset-typescript": ^7.17.12 - "@cardano-foundation/ledgerjs-hw-app-cardano": ^6.0.0 + "@cardano-foundation/ledgerjs-hw-app-cardano": ^7.0.0 "@cardano-ogmios/client": 5.6.0 "@cardano-sdk/cardano-services": "workspace:~" "@cardano-sdk/cardano-services-client": "workspace:~" @@ -3751,7 +3739,7 @@ __metadata: version: 0.0.0-use.local resolution: "@cardano-sdk/wallet@workspace:packages/wallet" dependencies: - "@cardano-foundation/ledgerjs-hw-app-cardano": ^6.0.0 + "@cardano-foundation/ledgerjs-hw-app-cardano": ^7.0.0 "@cardano-ogmios/client": 5.6.0 "@cardano-sdk/cardano-services-client": "workspace:~" "@cardano-sdk/core": "workspace:~"