From 4d56f43890f90e870eb5ca894798ff280f359e10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Maz=C3=A1k?= <42575685+janmazak@users.noreply.github.com> Date: Tue, 19 Dec 2023 00:47:53 +0100 Subject: [PATCH] conway: add tx body items --- .cspell.json | 1 + CHANGELOG.md | 15 + example-node/index.ts | 8 +- package.json | 2 +- src/errors/invalidDataReason.ts | 50 +- src/interactions/getVersion.ts | 22 +- .../poolRegistrationCertificate.ts | 9 +- .../serialization/txCertificate.ts | 113 +- src/interactions/serialization/txInit.ts | 14 +- src/interactions/serialization/txOther.ts | 64 +- src/interactions/serialization/txOutput.ts | 4 +- src/interactions/signTx.ts | 253 +++- src/parsing/certificate.ts | 146 +- src/parsing/output.ts | 10 +- src/parsing/poolRegistration.ts | 14 +- src/parsing/transaction.ts | 279 +++- src/types/internal.ts | 211 ++- src/types/public.ts | 411 +++++- src/utils/parse.ts | 94 +- src/utils/serialize.ts | 63 +- test/integration/__fixtures__/signTx.ts | 1292 ++++++++++++++--- test/integration/__fixtures__/signTxPlutus.ts | 6 +- .../__fixtures__/signTxPoolRegistration.ts | 6 +- .../integration/__fixtures__/signTxRejects.ts | 38 +- test/integration/getVersion.test.ts | 3 +- test/integration/signTx.test.ts | 15 + 26 files changed, 2609 insertions(+), 534 deletions(-) diff --git a/.cspell.json b/.cspell.json index c53b417d..1876423d 100644 --- a/.cspell.json +++ b/.cspell.json @@ -41,6 +41,7 @@ "deregistration", "DEVEL", "dpkg", + "DREP", "endians", "financials", "hwsfile", diff --git a/CHANGELOG.md b/CHANGELOG.md index 72190957..ff147760 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [7.0.0](TBD) - [TBD] + +Support for Conway era + +### Added + +- export of Conway-era keys (DReps, Constitutional Committee Hot and Cold keys) +- Conway era transaction body items (new certificates, voting procedures, treasury, donation) +- support for reduced features on Nano S (since Ledger app v7, due to memory limits) + +### Changed + +- names of credential types (e.g. StakeCredentialParamsType -> CredentialParamsType) + + ## [6.0.0](TBD) - [TBD] Support for CIP0036 voting diff --git a/example-node/index.ts b/example-node/index.ts index ee2a3b41..b2b8ff92 100644 --- a/example-node/index.ts +++ b/example-node/index.ts @@ -4,7 +4,7 @@ import SpeculosTransport from '@ledgerhq/hw-transport-node-speculos' import { Certificate, - StakeCredentialParamsType, + CredentialParamsType, TxInput, TxOutput, Withdrawal, @@ -216,7 +216,7 @@ const signTransaction = async (appAda: Ada) => { type: CertificateType.STAKE_REGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: [1852 + HARDENED, 1815 + HARDENED, 0 + HARDENED, 2, 0], }, }, @@ -225,7 +225,7 @@ const signTransaction = async (appAda: Ada) => { type: CertificateType.STAKE_DELEGATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: [1852 + HARDENED, 1815 + HARDENED, 0 + HARDENED, 2, 0], }, poolKeyHashHex: @@ -237,7 +237,7 @@ const signTransaction = async (appAda: Ada) => { const withdrawals: Withdrawal[] = [ { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: [1852 + HARDENED, 1815 + HARDENED, 0 + HARDENED, 2, 0], }, amount: '1000', diff --git a/package.json b/package.json index 77577dc7..bd6178aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@cardano-foundation/ledgerjs-hw-app-cardano", - "version": "6.0.0", + "version": "7.0.0", "files": [ "dist" ], diff --git a/src/errors/invalidDataReason.ts b/src/errors/invalidDataReason.ts index fd1dc6fd..c405a480 100644 --- a/src/errors/invalidDataReason.ts +++ b/src/errors/invalidDataReason.ts @@ -57,12 +57,17 @@ export enum InvalidDataReason { CERTIFICATES_NOT_ARRAY = 'certificates not an array', + CERTIFICATE_INVALID_TYPE = 'invalid certificate type', CERTIFICATE_INVALID_PATH = 'one of the certificates contains an invalid path', - CERTIFICATE_INVALID_SCRIPT_HASH = 'one of the certificates contains an invalid script hash', - CERTIFICATE_INVALID_STAKE_CREDENTIAL = 'one of the certificates contains both a path and a scripthash or neither', + CERTIFICATE_INVALID_STAKE_CREDENTIAL = 'one of the certificates contains an invalid stake credential', + CERTIFICATE_INVALID_COMMITTEE_CREDENTIAL = 'one of the certificates contains invalid constitutional committee credential', + CERTIFICATE_INVALID_DREP_CREDENTIAL = 'one of the certificates contains an invalid DRep credential', CERTIFICATE_INVALID_POOL_KEY_HASH = 'one of the certificates contains an invalid pool key hash', CERTIFICATE_SUPERFLUOUS_POOL_KEY_HASH = 'superfluous pool key hash in a certificate', - CERTIFICATE_INVALID_TYPE = 'invalid certificate type', + CERTIFICATE_INVALID_DEPOSIT = 'one of the certificates contains an invalid deposit', + CERTIFICATE_INVALID_DREP = 'one of the certificates contains an invalid DRep', + ANCHOR_INVALID_URL = 'anchor with an invalid URL', + ANCHOR_INVALID_HASH = 'anchor with an invalid data hash', POOL_REGISTRATION_INVALID_VRF_KEY_HASH = 'invalid vrf key hash in a pool registration certificate', POOL_REGISTRATION_INVALID_PLEDGE = 'invalid pledge in a pool registration certificate', @@ -140,43 +145,63 @@ export enum InvalidDataReason { REFERENCE_INPUTS_NOT_ARRAY = 'reference inputs not an array', + VOTING_PROCEDURES_NOT_ARRAY = 'voting procedures not an array', + VOTER_VOTES_NOT_ARRAY = "voter's votes not an array", + VOTER_INVALID = 'invalid voter in voting procedures', + GOV_ACTION_ID_INVALID_TX_HASH = 'invalid governance action id tx hash', + GOV_ACTION_ID_INVALID_INDEX = 'invalid governance action id index', + VOTING_PROCEDURES_INVALID_NUMBER_OF_VOTERS = 'there must be exactly 1 voter in voting procedures', + VOTING_PROCEDURES_INVALID_NUMBER_OF_VOTES = 'there must be exactly 1 voting procedure per voter', + + TREASURY_NOT_VALID = 'treasury amount not valid', + + DONATION_NOT_VALID = 'treasury donation not valid', + SIGN_MODE_UNKNOWN = 'unknown signing mode', SIGN_MODE_ORDINARY__POOL_REGISTRATION_NOT_ALLOWED = 'pool registration not allowed in TransactionSigningMode.ORDINARY_TRANSACTION', SIGN_MODE_ORDINARY__CERTIFICATE_STAKE_CREDENTIAL_ONLY_AS_PATH = 'certificate stake credential must be given as a staking path in TransactionSigningMode.ORDINARY_TRANSACTION', + SIGN_MODE_ORDINARY__CERTIFICATE_COMMITTEE_COLD_CREDENTIAL_ONLY_AS_PATH = 'certificate constitutional committee cold credential must be given as a path in TransactionSigningMode.ORDINARY_TRANSACTION', + SIGN_MODE_ORDINARY__CERTIFICATE_DREP_CREDENTIAL_ONLY_AS_PATH = 'certificate DRep credential must be given as a path in TransactionSigningMode.ORDINARY_TRANSACTION', SIGN_MODE_ORDINARY__WITHDRAWAL_ONLY_AS_PATH = 'withdrawal must be given as a path in TransactionSigningMode.ORDINARY_TRANSACTION', SIGN_MODE_ORDINARY__COLLATERAL_INPUTS_NOT_ALLOWED = 'collateral inputs not allowed in TransactionSigningMode.ORDINARY_TRANSACTION', SIGN_MODE_ORDINARY__COLLATERAL_OUTPUT_NOT_ALLOWED = 'collateral output not allowed in TransactionSigningMode.ORDINARY_TRANSACTION', SIGN_MODE_ORDINARY__TOTAL_COLLATERAL_NOT_ALLOWED = 'total collateral not allowed in TransactionSigningMode.ORDINARY_TRANSACTION', SIGN_MODE_ORDINARY__REFERENCE_INPUTS_NOT_ALLOWED = 'reference inputs not allowed in TransactionSigningMode.ORDINARY_TRANSACTION', + SIGN_MODE_ORDINARY__VOTER_ONLY_AS_PATH = 'voter credential in voting procedures must be given as a path in TransactionSigningMode.ORDINARY_TRANSACTION', SIGN_MODE_MULTISIG__POOL_REGISTRATION_NOT_ALLOWED = 'pool registration not allowed in TransactionSigningMode.MULTISIG_TRANSACTION', SIGN_MODE_MULTISIG__POOL_RETIREMENT_NOT_ALLOWED = 'pool retirement not allowed in TransactionSigningMode.MULTISIG_TRANSACTION', SIGN_MODE_MULTISIG__DEVICE_OWNED_ADDRESS_NOT_ALLOWED = 'outputs given by path not allowed in TransactionSigningMode.MULTISIG_TRANSACTION', - SIGN_MODE_MULTISIG__CERTIFICATE_STAKE_CREDENTIAL_ONLY_AS_SCRIPT = 'certificate stake credential must be given as a script hash in TransactionSigningMode.MULTISIG_TRANSACTION', - SIGN_MODE_MULTISIG__WITHDRAWAL_ONLY_AS_SCRIPT = 'withdrawal must be given as a script hash in TransactionSigningMode.MULTISIG_TRANSACTION', + SIGN_MODE_MULTISIG__CERTIFICATE_CREDENTIAL_ONLY_AS_SCRIPT = 'certificate credential must be a script hash in TransactionSigningMode.MULTISIG_TRANSACTION', + SIGN_MODE_MULTISIG__WITHDRAWAL_ONLY_AS_SCRIPT = 'withdrawal must be a script hash in TransactionSigningMode.MULTISIG_TRANSACTION', SIGN_MODE_MULTISIG__COLLATERAL_INPUTS_NOT_ALLOWED = 'collateral inputs not allowed in TransactionSigningMode.MULTISIG_TRANSACTION', SIGN_MODE_MULTISIG__COLLATERAL_OUTPUT_NOT_ALLOWED = 'collateral output not allowed in TransactionSigningMode.MULTISIG_TRANSACTION', SIGN_MODE_MULTISIG__TOTAL_COLLATERAL_NOT_ALLOWED = 'total collateral not allowed in TransactionSigningMode.MULTISIG_TRANSACTION', SIGN_MODE_MULTISIG__REFERENCE_INPUTS_NOT_ALLOWED = 'reference inputs not allowed in TransactionSigningMode.MULTISIG_TRANSACTION', + SIGN_MODE_MULTISIG__VOTER_ONLY_AS_SCRIPT = 'voter credential in voting procedures must be a script hash in TransactionSigningMode.MULTISIG_TRANSACTION', + SIGN_MODE_POOL_OWNER__INPUT_WITH_PATH_NOT_ALLOWED = 'inputs with path not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__DEVICE_OWNED_ADDRESS_NOT_ALLOWED = 'outputs given by path are not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__DATUM_NOT_ALLOWED = 'datum in outputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__REFERENCE_SCRIPT_NOT_ALLOWED = 'reference script in outputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', - SIGN_MODE_POOL_OWNER__INPUT_WITH_PATH_NOT_ALLOWED = 'inputs with path not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__SINGLE_POOL_REG_CERTIFICATE_REQUIRED = 'single pool registration certificate is expected in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', + SIGN_MODE_POOL_OWNER__THIRD_PARTY_POOL_KEY_REQUIRED = 'third party pool key is required in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__SINGLE_DEVICE_OWNER_REQUIRED = 'single device-owned pool owner is expected in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__WITHDRAWALS_NOT_ALLOWED = 'withdrawals not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__MINT_NOT_ALLOWED = 'mint not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__SCRIPT_DATA_HASH_NOT_ALLOWED = 'script data hash not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__COLLATERAL_INPUTS_NOT_ALLOWED = 'collateral inputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', + SIGN_MODE_POOL_OWNER__COLLATERAL_OUTPUT_NOT_ALLOWED = 'reference inputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__TOTAL_COLLATERAL_NOT_ALLOWED = 'total collateral not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__REQUIRED_SIGNERS_NOT_ALLOWED = 'required signers not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', - SIGN_MODE_POOL_OWNER__THIRD_PARTY_POOL_KEY_REQUIRED = 'third party pool key is required in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', - - SIGN_MODE_POOL_OWNER__COLLATERAL_OUTPUT_NOT_ALLOWED = 'reference inputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', SIGN_MODE_POOL_OWNER__REFERENCE_INPUTS_NOT_ALLOWED = 'reference inputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', + SIGN_MODE_POOL_OWNER__VOTING_PROCEDURES_NOT_ALLOWED = 'voting procedures not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', + SIGN_MODE_POOL_OWNER__TREASURY_NOT_ALLOWED = 'treasury amount not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', + SIGN_MODE_POOL_OWNER__DONATION_NOT_ALLOWED = 'treasury donation not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OWNER', + SIGN_MODE_POOL_OPERATOR__DATUM_NOT_ALLOWED = 'datum in outputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', + SIGN_MODE_POOL_OPERATOR__REFERENCE_SCRIPT_NOT_ALLOWED = 'reference script in outputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__SINGLE_POOL_REG_CERTIFICATE_REQUIRED = 'single pool registration certificate is expected in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__DEVICE_OWNED_POOL_KEY_REQUIRED = 'device owned pool key is required in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__DEVICE_OWNED_POOL_OWNER_NOT_ALLOWED = 'device-owned pool owner not expected in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', @@ -184,12 +209,13 @@ export enum InvalidDataReason { SIGN_MODE_POOL_OPERATOR__MINT_NOT_ALLOWED = 'mint not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__SCRIPT_DATA_HASH_NOT_ALLOWED = 'script data hash not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__COLLATERAL_INPUTS_NOT_ALLOWED = 'collateral inputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', - SIGN_MODE_POOL_OPERATOR__REQUIRED_SIGNERS_NOT_ALLOWED = 'required signers not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', - SIGN_MODE_POOL_OPERATOR__DATUM_NOT_ALLOWED = 'datum in outputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', - SIGN_MODE_POOL_OPERATOR__REFERENCE_SCRIPT_NOT_ALLOWED = 'reference script in outputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__COLLATERAL_OUTPUT_NOT_ALLOWED = 'collateral output not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__TOTAL_COLLATERAL_NOT_ALLOWED = 'total collateral not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', + SIGN_MODE_POOL_OPERATOR__REQUIRED_SIGNERS_NOT_ALLOWED = 'required signers not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_POOL_OPERATOR__REFERENCE_INPUTS_NOT_ALLOWED = 'reference inputs not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', + SIGN_MODE_POOL_OPERATOR__VOTING_PROCEDURES_NOT_ALLOWED = 'voting procedures not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', + SIGN_MODE_POOL_OPERATOR__TREASURY_NOT_ALLOWED = 'treasury amount not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', + SIGN_MODE_POOL_OPERATOR__DONATION_NOT_ALLOWED = 'treasury donation not allowed in TransactionSigningMode.POOL_REGISTRATION_AS_OPERATOR', SIGN_MODE_PLUTUS__DEVICE_OWNED_ADDRESS_NOT_ALLOWED = 'outputs given by path not allowed in TransactionSigningMode.PLUTUS_TRANSACTION', SIGN_MODE_PLUTUS__POOL_REGISTRATION_NOT_ALLOWED = 'pool registration not allowed in TransactionSigningMode.PLUTUS_TRANSACTION', diff --git a/src/interactions/getVersion.ts b/src/interactions/getVersion.ts index 8dbe58ab..62ede5e1 100644 --- a/src/interactions/getVersion.ts +++ b/src/interactions/getVersion.ts @@ -63,34 +63,37 @@ export function getCompatibility(version: Version): DeviceCompatibility { // We restrict forward compatibility only to backward-compatible semver changes const v2_2 = isLedgerAppVersionAtLeast(version, 2, 2) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) const v2_3 = isLedgerAppVersionAtLeast(version, 2, 3) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) const v2_4 = isLedgerAppVersionAtLeast(version, 2, 4) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) const v3_0 = isLedgerAppVersionAtLeast(version, 3, 0) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) const v4_0 = isLedgerAppVersionAtLeast(version, 4, 0) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) const v4_1 = isLedgerAppVersionAtLeast(version, 4, 1) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) const v5_0 = isLedgerAppVersionAtLeast(version, 5, 0) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) const v6_0 = isLedgerAppVersionAtLeast(version, 6, 0) && - isLedgerAppVersionAtMost(version, 6, Infinity) + isLedgerAppVersionAtMost(version, 7, Infinity) + const v7_0 = + isLedgerAppVersionAtLeast(version, 7, 0) && + isLedgerAppVersionAtMost(version, 7, Infinity) const isAppXS = version.flags.isAppXS return { isCompatible: v2_2, - recommendedVersion: v2_2 ? null : '6.0', + recommendedVersion: v2_2 ? null : '7.0', supportsByronAddressDerivation: v2_2 && !isAppXS, supportsMary: v2_2, supportsCatalystRegistration: v2_3, // CIP-15 @@ -106,6 +109,7 @@ export function getCompatibility(version: Version): DeviceCompatibility { supportsReqSignersInOrdinaryTx: v4_1, supportsBabbage: v5_0, supportsCIP36Vote: v6_0, + supportsConway: v7_0, } } diff --git a/src/interactions/serialization/poolRegistrationCertificate.ts b/src/interactions/serialization/poolRegistrationCertificate.ts index a2869281..763db14c 100644 --- a/src/interactions/serialization/poolRegistrationCertificate.ts +++ b/src/interactions/serialization/poolRegistrationCertificate.ts @@ -22,6 +22,7 @@ import { uint16_to_buf, uint32_to_buf, uint64_to_buf, + serializeCoin, } from '../../utils/serialize' const SignTxIncluded = Object.freeze({ @@ -43,8 +44,8 @@ export function serializePoolInitialParamsLegacy( // eslint-disable-next-line @typescript-eslint/no-use-before-define serializePoolKeyLegacy(pool.poolKey), hex_to_buf(pool.vrfHashHex), - uint64_to_buf(pool.pledge), - uint64_to_buf(pool.cost), + serializeCoin(pool.pledge), + serializeCoin(pool.cost), uint64_to_buf(pool.margin.numerator), uint64_to_buf(pool.margin.denominator), // eslint-disable-next-line @typescript-eslint/no-use-before-define @@ -56,8 +57,8 @@ export function serializePoolInitialParamsLegacy( export function serializeFinancials(pool: ParsedPoolParams): Buffer { return Buffer.concat([ - uint64_to_buf(pool.pledge), - uint64_to_buf(pool.cost), + serializeCoin(pool.pledge), + serializeCoin(pool.cost), uint64_to_buf(pool.margin.numerator), uint64_to_buf(pool.margin.denominator), ]) diff --git a/src/interactions/serialization/txCertificate.ts b/src/interactions/serialization/txCertificate.ts index 145f4492..f4533fde 100644 --- a/src/interactions/serialization/txCertificate.ts +++ b/src/interactions/serialization/txCertificate.ts @@ -1,16 +1,47 @@ -import {InvalidDataReason} from '../../errors/invalidDataReason' -import type {ParsedCertificate, Uint8_t, Version} from '../../types/internal' -import {StakeCredentialType, CertificateType} from '../../types/internal' +import { + DRepType, + Uint8_t, + CredentialType, + CertificateType, +} from '../../types/internal' +import type {ParsedCertificate, ParsedDRep, Version} from '../../types/internal' import {assert, unreachable} from '../../utils/assert' import { hex_to_buf, path_to_buf, - stake_credential_to_buf, + serializeCredential, uint8_to_buf, uint64_to_buf, + serializeCoin, + serializeAnchor, } from '../../utils/serialize' import {getCompatibility} from '../getVersion' +export function serializeDRep(dRep: ParsedDRep): Buffer { + switch (dRep.type) { + case DRepType.KEY_PATH: + return Buffer.concat([ + uint8_to_buf(dRep.type as Uint8_t), + path_to_buf(dRep.path), + ]) + case DRepType.KEY_HASH: + return Buffer.concat([ + uint8_to_buf(dRep.type as Uint8_t), + hex_to_buf(dRep.keyHashHex), + ]) + case DRepType.SCRIPT_HASH: + return Buffer.concat([ + uint8_to_buf(dRep.type as Uint8_t), + hex_to_buf(dRep.scriptHashHex), + ]) + case DRepType.ABSTAIN: + case DRepType.NO_CONFIDENCE: + return Buffer.concat([uint8_to_buf(dRep.type as Uint8_t)]) + default: + unreachable(dRep) + } +} + export function serializeTxCertificatePreMultisig( certificate: ParsedCertificate, ) { @@ -18,8 +49,8 @@ export function serializeTxCertificatePreMultisig( case CertificateType.STAKE_REGISTRATION: case CertificateType.STAKE_DEREGISTRATION: { assert( - certificate.stakeCredential.type === StakeCredentialType.KEY_PATH, - InvalidDataReason.CERTIFICATE_INVALID_STAKE_CREDENTIAL, + certificate.stakeCredential.type === CredentialType.KEY_PATH, + 'invalid stake credential', ) return Buffer.concat([ uint8_to_buf(certificate.type as Uint8_t), @@ -28,8 +59,8 @@ export function serializeTxCertificatePreMultisig( } case CertificateType.STAKE_DELEGATION: { assert( - certificate.stakeCredential.type === StakeCredentialType.KEY_PATH, - InvalidDataReason.CERTIFICATE_INVALID_STAKE_CREDENTIAL, + certificate.stakeCredential.type === CredentialType.KEY_PATH, + 'invalid stake credential', ) return Buffer.concat([ uint8_to_buf(certificate.type as Uint8_t), @@ -47,6 +78,17 @@ export function serializeTxCertificatePreMultisig( uint64_to_buf(certificate.retirementEpoch), ]) } + case CertificateType.STAKE_REGISTRATION_CONWAY: + case CertificateType.STAKE_DEREGISTRATION_CONWAY: + case CertificateType.VOTE_DELEGATION: + case CertificateType.AUTHORIZE_COMMITTEE_HOT: + case CertificateType.RESIGN_COMMITTEE_COLD: + case CertificateType.DREP_REGISTRATION: + case CertificateType.DREP_DEREGISTRATION: + case CertificateType.DREP_UPDATE: { + assert(false, 'Conway certificates in pre-multisig serialization') + break + } default: unreachable(certificate) } @@ -65,16 +107,67 @@ export function serializeTxCertificate( case CertificateType.STAKE_DEREGISTRATION: { return Buffer.concat([ uint8_to_buf(certificate.type as Uint8_t), - stake_credential_to_buf(certificate.stakeCredential), + serializeCredential(certificate.stakeCredential), + ]) + } + case CertificateType.STAKE_REGISTRATION_CONWAY: + case CertificateType.STAKE_DEREGISTRATION_CONWAY: { + return Buffer.concat([ + uint8_to_buf(certificate.type as Uint8_t), + serializeCredential(certificate.stakeCredential), + serializeCoin(certificate.deposit), ]) } case CertificateType.STAKE_DELEGATION: { return Buffer.concat([ uint8_to_buf(certificate.type as Uint8_t), - stake_credential_to_buf(certificate.stakeCredential), + serializeCredential(certificate.stakeCredential), hex_to_buf(certificate.poolKeyHashHex), ]) } + case CertificateType.VOTE_DELEGATION: { + return Buffer.concat([ + uint8_to_buf(certificate.type as Uint8_t), + serializeCredential(certificate.stakeCredential), + serializeDRep(certificate.dRep), + ]) + } + case CertificateType.AUTHORIZE_COMMITTEE_HOT: { + return Buffer.concat([ + uint8_to_buf(certificate.type as Uint8_t), + serializeCredential(certificate.coldCredential), + serializeCredential(certificate.hotCredential), + ]) + } + case CertificateType.RESIGN_COMMITTEE_COLD: { + return Buffer.concat([ + uint8_to_buf(certificate.type as Uint8_t), + serializeCredential(certificate.coldCredential), + serializeAnchor(certificate.anchor), + ]) + } + case CertificateType.DREP_REGISTRATION: { + return Buffer.concat([ + uint8_to_buf(certificate.type as Uint8_t), + serializeCredential(certificate.dRepCredential), + serializeCoin(certificate.deposit), + serializeAnchor(certificate.anchor), + ]) + } + case CertificateType.DREP_DEREGISTRATION: { + return Buffer.concat([ + uint8_to_buf(certificate.type as Uint8_t), + serializeCredential(certificate.dRepCredential), + serializeCoin(certificate.deposit), + ]) + } + case CertificateType.DREP_UPDATE: { + return Buffer.concat([ + uint8_to_buf(certificate.type as Uint8_t), + serializeCredential(certificate.dRepCredential), + serializeAnchor(certificate.anchor), + ]) + } case CertificateType.STAKE_POOL_REGISTRATION: { return Buffer.concat([uint8_to_buf(certificate.type as Uint8_t)]) } diff --git a/src/interactions/serialization/txInit.ts b/src/interactions/serialization/txInit.ts index 6da77344..884030f4 100644 --- a/src/interactions/serialization/txInit.ts +++ b/src/interactions/serialization/txInit.ts @@ -35,7 +35,7 @@ export function serializeTxInit( ) { const appAwareOfMint = getCompatibility(version).supportsMint || version.flags.isAppXS - // even though XS app doesn't support minting, it does expect the flag value + // even if XS app doesn't support minting, it does expect the flag value // (we want to keep the APDU serialization uniform) const mintBuffer = appAwareOfMint ? serializeOptionFlag(tx.mint != null) @@ -63,6 +63,15 @@ export function serializeTxInit( const referenceInputsBuffer = getCompatibility(version).supportsBabbage ? uint32_to_buf(tx.referenceInputs.length as Uint32_t) : Buffer.from([]) + const votingProceduresBuffer = getCompatibility(version).supportsConway + ? uint32_to_buf(tx.votingProcedures.length as Uint32_t) + : Buffer.from([]) + const includeTreasuryBuffer = getCompatibility(version).supportsConway + ? serializeOptionFlag(tx.treasury != null) + : Buffer.from([]) + const includeDonationBuffer = getCompatibility(version).supportsConway + ? serializeOptionFlag(tx.donation != null) + : Buffer.from([]) // we have re-ordered numWitnesses in wireDataBuffer since Babbage const witnessBufferLegacy = getCompatibility(version).supportsBabbage @@ -83,6 +92,8 @@ export function serializeTxInit( includeNetworkIdBuffer, includeCollateralOutputBuffer, includeTotalCollateralBuffer, + includeTreasuryBuffer, + includeDonationBuffer, _serializeSigningMode(signingMode), uint32_to_buf(tx.inputs.length as Uint32_t), uint32_to_buf(tx.outputs.length as Uint32_t), @@ -92,6 +103,7 @@ export function serializeTxInit( collateralInputsBuffer, requiredSignersBuffer, referenceInputsBuffer, + votingProceduresBuffer, witnessBufferBabbage, ]) } diff --git a/src/interactions/serialization/txOther.ts b/src/interactions/serialization/txOther.ts index 0aa42d36..2df9d5a1 100644 --- a/src/interactions/serialization/txOther.ts +++ b/src/interactions/serialization/txOther.ts @@ -1,3 +1,4 @@ +import {VoterType} from '../../types/public' import {InvalidDataReason} from '../../errors/invalidDataReason' import type { Int64_str, @@ -11,16 +12,20 @@ import type { Uint64_str, ValidBIP32Path, Version, + ParsedVoterVotes, + ParsedVoter, } from '../../types/internal' -import {RequiredSignerType, StakeCredentialType} from '../../types/internal' +import {RequiredSignerType, CredentialType} from '../../types/internal' import {assert, unreachable} from '../../utils/assert' import { hex_to_buf, path_to_buf, - stake_credential_to_buf, + serializeCredential, uint8_to_buf, uint32_to_buf, uint64_to_buf, + serializeCoin, + serializeAnchor, } from '../../utils/serialize' import {getCompatibility} from '../getVersion' import type {SerializeTokenAmountFn} from '../signTx' @@ -38,26 +43,22 @@ export function serializeTxWithdrawal( ): Buffer { if (getCompatibility(version).supportsMultisigTransaction) { return Buffer.concat([ - uint64_to_buf(withdrawal.amount), - stake_credential_to_buf(withdrawal.stakeCredential), + serializeCoin(withdrawal.amount), + serializeCredential(withdrawal.stakeCredential), ]) } else { // pre-multisig assert( - withdrawal.stakeCredential.type === StakeCredentialType.KEY_PATH, + withdrawal.stakeCredential.type === CredentialType.KEY_PATH, InvalidDataReason.WITHDRAWAL_INVALID_STAKE_CREDENTIAL, ) return Buffer.concat([ - uint64_to_buf(withdrawal.amount), + serializeCoin(withdrawal.amount), path_to_buf(withdrawal.stakeCredential.path), ]) } } -export function serializeTxFee(fee: Uint64_str): Buffer { - return Buffer.concat([uint64_to_buf(fee)]) -} - export function serializeTxTtl(ttl: Uint64_str): Buffer { return Buffer.concat([uint64_to_buf(ttl)]) } @@ -117,6 +118,45 @@ export function serializeRequiredSigner( } } -export function serializeTotalCollateral(totalCollateral: Uint64_str): Buffer { - return Buffer.concat([uint64_to_buf(totalCollateral)]) +function serializeVoter(voter: ParsedVoter): Buffer { + switch (voter.type) { + case VoterType.COMMITTEE_KEY_HASH: + case VoterType.DREP_KEY_HASH: + case VoterType.STAKE_POOL_KEY_HASH: + return Buffer.concat([ + uint8_to_buf(voter.type as Uint8_t), + hex_to_buf(voter.keyHashHex), + ]) + case VoterType.COMMITTEE_KEY_PATH: + case VoterType.DREP_KEY_PATH: + case VoterType.STAKE_POOL_KEY_PATH: + return Buffer.concat([ + uint8_to_buf(voter.type as Uint8_t), + path_to_buf(voter.keyPath), + ]) + case VoterType.COMMITTEE_SCRIPT_HASH: + case VoterType.DREP_SCRIPT_HASH: + return Buffer.concat([ + uint8_to_buf(voter.type as Uint8_t), + hex_to_buf(voter.scriptHashHex), + ]) + default: + unreachable(voter) + } +} + +export function serializeVoterVotes(voterVotes: ParsedVoterVotes): Buffer { + assert(voterVotes.votes.length === 1, 'too few / too many votes') + const vote = voterVotes.votes[0] + return Buffer.concat([ + serializeVoter(voterVotes.voter), + Buffer.concat([ + hex_to_buf(vote.govActionId.txHashHex), + uint32_to_buf(vote.govActionId.govActionIndex), + ]), + Buffer.concat([ + uint8_to_buf(vote.votingProcedure.vote as Uint8_t), + serializeAnchor(vote.votingProcedure.anchor), + ]), + ]) } diff --git a/src/interactions/serialization/txOutput.ts b/src/interactions/serialization/txOutput.ts index 47aa4759..31df3b76 100644 --- a/src/interactions/serialization/txOutput.ts +++ b/src/interactions/serialization/txOutput.ts @@ -15,7 +15,7 @@ import { serializeOptionFlag, uint8_to_buf, uint32_to_buf, - uint64_to_buf, + serializeCoin, } from '../../utils/serialize' import {getCompatibility} from '../getVersion' import {serializeAddressParams} from './addressParams' @@ -68,7 +68,7 @@ export function serializeTxOutputBasicParams( return Buffer.concat([ serializationFormatBuffer, serializeTxOutputDestination(output.destination, version), - uint64_to_buf(output.amount), + serializeCoin(output.amount), uint32_to_buf(output.tokenBundle.length as Uint32_t), includeDatumBuffer, includeScriptBuffer, diff --git a/src/interactions/signTx.ts b/src/interactions/signTx.ts index c04dd509..847502b7 100644 --- a/src/interactions/signTx.ts +++ b/src/interactions/signTx.ts @@ -10,6 +10,7 @@ import type { ParsedSigningRequest, ParsedTransaction, ParsedTxAuxiliaryData, + ParsedVoterVotes, ParsedWithdrawal, ScriptDataHash, Uint32_t, @@ -23,7 +24,7 @@ import { ED25519_SIGNATURE_LENGTH, PoolOwnerType, RequiredSignerType, - StakeCredentialType, + CredentialType, TX_HASH_LENGTH, } from '../types/internal' import type { @@ -40,6 +41,7 @@ import { TxAuxiliaryDataType, TxOutputDestinationType, TxOutputFormat, + VoterType, } from '../types/public' import {getVersionString} from '../utils' import {assert} from '../utils/assert' @@ -47,6 +49,7 @@ import { buf_to_hex, hex_to_buf, int64_to_buf, + serializeCoin, uint32_to_buf, uint64_to_buf, } from '../utils/serialize' @@ -80,13 +83,12 @@ import { serializeMintBasicParams, serializeRequiredSigner, serializeToken, - serializeTotalCollateral, - serializeTxFee, serializeTxInput, serializeTxTtl, serializeTxValidityStart, serializeTxWithdrawal, serializeTxWitnessRequest, + serializeVoterVotes, } from './serialization/txOther' import { MAX_CHUNK_SIZE, @@ -113,6 +115,9 @@ const enum P1 { STAGE_COLLATERAL_OUTPUT = 0x12, STAGE_TOTAL_COLLATERAL = 0x10, STAGE_REFERENCE_INPUTS = 0x11, + STAGE_VOTING_PROCEDURES = 0x13, + STAGE_TREASURY = 0x15, + STAGE_DONATION = 0x16, STAGE_CONFIRM = 0x0a, STAGE_WITNESSES = 0x0f, } @@ -479,7 +484,7 @@ function* signTx_setFee(fee: Uint64_str): Interaction { yield send({ p1: P1.STAGE_FEE, p2: P2.UNUSED, - data: serializeTxFee(fee), + data: serializeCoin(fee), expectedResponseLength: 0, }) } @@ -774,7 +779,7 @@ function* signTx_addTotalCollateral( yield send({ p1: P1.STAGE_TOTAL_COLLATERAL, p2: P2.UNUSED, - data: serializeTotalCollateral(totalCollateral), + data: serializeCoin(totalCollateral), expectedResponseLength: 0, }) } @@ -793,6 +798,44 @@ function* signTx_addReferenceInput( }) } +function* signTx_addVoterVotes( + voterVotes: ParsedVoterVotes, +): Interaction { + const enum P2 { + UNUSED = 0x00, + } + yield send({ + p1: P1.STAGE_VOTING_PROCEDURES, + p2: P2.UNUSED, + data: serializeVoterVotes(voterVotes), + expectedResponseLength: 0, + }) +} + +function* signTx_addTreasury(treasury: Uint64_str): Interaction { + const enum P2 { + UNUSED = 0x00, + } + yield send({ + p1: P1.STAGE_TREASURY, + p2: P2.UNUSED, + data: serializeCoin(treasury), + expectedResponseLength: 0, + }) +} + +function* signTx_addDonation(donation: Uint64_str): Interaction { + const enum P2 { + UNUSED = 0x00, + } + yield send({ + p1: P1.STAGE_DONATION, + p2: P2.UNUSED, + data: serializeCoin(donation), + expectedResponseLength: 0, + }) +} + function* signTx_awaitConfirm(): Interaction<{txHashHex: string}> { const enum P2 { UNUSED = 0x00, @@ -856,13 +899,33 @@ function gatherWitnessPaths(request: ParsedSigningRequest): ValidBIP32Path[] { // certificate witnesses for (const cert of tx.certificates) { switch (cert.type) { - case CertificateType.STAKE_DELEGATION: + // for CertificateType.STAKE_REGISTRATION, we do not provide the witness automatically + // it can be obtained via SignTransactionRequest.additionalWitnessPaths + case CertificateType.STAKE_REGISTRATION_CONWAY: case CertificateType.STAKE_DEREGISTRATION: - if (cert.stakeCredential.type === StakeCredentialType.KEY_PATH) { + case CertificateType.STAKE_DEREGISTRATION_CONWAY: + case CertificateType.STAKE_DELEGATION: + case CertificateType.VOTE_DELEGATION: + if (cert.stakeCredential.type === CredentialType.KEY_PATH) { witnessPaths.push(cert.stakeCredential.path) } break + case CertificateType.AUTHORIZE_COMMITTEE_HOT: + case CertificateType.RESIGN_COMMITTEE_COLD: + if (cert.coldCredential.type === CredentialType.KEY_PATH) { + witnessPaths.push(cert.coldCredential.path) + } + break + + case CertificateType.DREP_REGISTRATION: + case CertificateType.DREP_DEREGISTRATION: + case CertificateType.DREP_UPDATE: + if (cert.dRepCredential.type === CredentialType.KEY_PATH) { + witnessPaths.push(cert.dRepCredential.path) + } + break + case CertificateType.STAKE_POOL_REGISTRATION: cert.pool.owners.forEach((owner) => { if (owner.type === PoolOwnerType.DEVICE_OWNED) { @@ -887,7 +950,7 @@ function gatherWitnessPaths(request: ParsedSigningRequest): ValidBIP32Path[] { // withdrawal witnesses for (const withdrawal of tx.withdrawals) { - if (withdrawal.stakeCredential.type === StakeCredentialType.KEY_PATH) { + if (withdrawal.stakeCredential.type === CredentialType.KEY_PATH) { witnessPaths.push(withdrawal.stakeCredential.path) } } @@ -898,7 +961,6 @@ function gatherWitnessPaths(request: ParsedSigningRequest): ValidBIP32Path[] { case RequiredSignerType.PATH: witnessPaths.push(signer.path) break - default: break } @@ -910,6 +972,19 @@ function gatherWitnessPaths(request: ParsedSigningRequest): ValidBIP32Path[] { witnessPaths.push(collateral.path) } } + + // voting procedures witnesses + for (const voterVotes of tx.votingProcedures) { + switch (voterVotes.voter.type) { + case VoterType.COMMITTEE_KEY_PATH: + case VoterType.DREP_KEY_PATH: + case VoterType.STAKE_POOL_KEY_PATH: + witnessPaths.push(voterVotes.voter.keyPath) + break + default: + break + } + } } // Note: if anything from tx body is added here, it should be covered by tests too @@ -920,22 +995,22 @@ function gatherWitnessPaths(request: ParsedSigningRequest): ValidBIP32Path[] { return uniquify(witnessPaths) } -function hasStakeCredentialInCertificates( +function hasCredentialInCertificatesPreConway( tx: ParsedTransaction, - stakeCredentialType: StakeCredentialType, + credentialType: CredentialType, ) { return tx.certificates.some( (c) => (c.type === CertificateType.STAKE_DELEGATION || - c.type === CertificateType.STAKE_DEREGISTRATION || - c.type === CertificateType.STAKE_REGISTRATION) && - c.stakeCredential.type === stakeCredentialType, + c.type === CertificateType.STAKE_REGISTRATION || + c.type === CertificateType.STAKE_DEREGISTRATION) && + c.stakeCredential.type === credentialType, ) } -function hasStakeCredentialInWithdrawals( +function hasCredentialInWithdrawals( tx: ParsedTransaction, - stakeCredentialType: StakeCredentialType, + stakeCredentialType: CredentialType, ) { return tx.withdrawals.some( (w) => w.stakeCredential.type === stakeCredentialType, @@ -1019,7 +1094,7 @@ function ensureRequestSupportedByAppVersion( const hasByronAddressParam = request.tx.outputs.some(isOutputByron) || isOutputByron(request.tx.collateralOutput) - // Byron collateral outputs forbidden by the security policy + // Byron collateral outputs forbidden by the security policy if ( hasByronAddressParam && !getCompatibility(version).supportsByronAddressDerivation @@ -1071,30 +1146,6 @@ function ensureRequestSupportedByAppVersion( ) } - if ( - hasStakeCredentialInWithdrawals( - request.tx, - StakeCredentialType.SCRIPT_HASH, - ) && - !getCompatibility(version).supportsMultisigTransaction - ) { - throw new DeviceVersionUnsupported( - `Script hash in withdrawal not supported by Ledger app version ${getVersionString( - version, - )}.`, - ) - } - if ( - hasStakeCredentialInWithdrawals(request.tx, StakeCredentialType.KEY_HASH) && - !getCompatibility(version).supportsAlonzo - ) { - throw new DeviceVersionUnsupported( - `Key hash in withdrawal not supported by Ledger app version ${getVersionString( - version, - )}.`, - ) - } - const hasPoolRegistration = request.tx.certificates.some( (c) => c.type === CertificateType.STAKE_POOL_REGISTRATION, ) @@ -1119,10 +1170,32 @@ function ensureRequestSupportedByAppVersion( )}.`, ) } + + const conwayCertificateTypes = [ + CertificateType.STAKE_REGISTRATION_CONWAY, + CertificateType.STAKE_DEREGISTRATION_CONWAY, + CertificateType.VOTE_DELEGATION, + CertificateType.AUTHORIZE_COMMITTEE_HOT, + CertificateType.RESIGN_COMMITTEE_COLD, + CertificateType.DREP_REGISTRATION, + CertificateType.DREP_DEREGISTRATION, + CertificateType.DREP_UPDATE, + ] + const hasConwayCertificates = request.tx.certificates.some((c) => + conwayCertificateTypes.includes(c.type), + ) + if (hasConwayCertificates && !getCompatibility(version).supportsConway) { + throw new DeviceVersionUnsupported( + `Conway era certificates not supported by Ledger app version ${getVersionString( + version, + )}.`, + ) + } + if ( - hasStakeCredentialInCertificates( + hasCredentialInCertificatesPreConway( request.tx, - StakeCredentialType.SCRIPT_HASH, + CredentialType.SCRIPT_HASH, ) && !getCompatibility(version).supportsMultisigTransaction ) { @@ -1133,10 +1206,7 @@ function ensureRequestSupportedByAppVersion( ) } if ( - hasStakeCredentialInCertificates( - request.tx, - StakeCredentialType.KEY_HASH, - ) && + hasCredentialInCertificatesPreConway(request.tx, CredentialType.KEY_HASH) && !getCompatibility(version).supportsAlonzo ) { throw new DeviceVersionUnsupported( @@ -1146,14 +1216,35 @@ function ensureRequestSupportedByAppVersion( ) } - if (request.tx?.mint && !getCompatibility(version).supportsMint) { + if ( + hasCredentialInWithdrawals(request.tx, CredentialType.SCRIPT_HASH) && + !getCompatibility(version).supportsMultisigTransaction + ) { + throw new DeviceVersionUnsupported( + `Script hash in withdrawal not supported by Ledger app version ${getVersionString( + version, + )}.`, + ) + } + if ( + hasCredentialInWithdrawals(request.tx, CredentialType.KEY_HASH) && + !getCompatibility(version).supportsAlonzo + ) { + throw new DeviceVersionUnsupported( + `Key hash in withdrawal not supported by Ledger app version ${getVersionString( + version, + )}.`, + ) + } + + if (request.tx?.mint !== null && !getCompatibility(version).supportsMint) { throw new DeviceVersionUnsupported( `Mint not supported by Ledger app version ${getVersionString(version)}.`, ) } if ( - request.tx.validityIntervalStart && + request.tx.validityIntervalStart !== null && !getCompatibility(version).supportsMary ) { throw new DeviceVersionUnsupported( @@ -1164,7 +1255,7 @@ function ensureRequestSupportedByAppVersion( } if ( - request.tx.scriptDataHashHex && + request.tx.scriptDataHashHex !== null && !getCompatibility(version).supportsAlonzo ) { throw new DeviceVersionUnsupported( @@ -1214,7 +1305,7 @@ function ensureRequestSupportedByAppVersion( } if ( - request.tx.includeNetworkId && + request.tx.includeNetworkId !== null && !getCompatibility(version).supportsAlonzo ) { throw new DeviceVersionUnsupported( @@ -1225,7 +1316,7 @@ function ensureRequestSupportedByAppVersion( } if ( - request.tx.collateralOutput && + request.tx.collateralOutput !== null && !getCompatibility(version).supportsBabbage ) { throw new DeviceVersionUnsupported( @@ -1236,7 +1327,7 @@ function ensureRequestSupportedByAppVersion( } if ( - request.tx.totalCollateral && + request.tx.totalCollateral !== null && !getCompatibility(version).supportsBabbage ) { throw new DeviceVersionUnsupported( @@ -1257,6 +1348,39 @@ function ensureRequestSupportedByAppVersion( ) } + if ( + request.tx.votingProcedures.length > 0 && + !getCompatibility(version).supportsConway + ) { + throw new DeviceVersionUnsupported( + `Voting procedures not supported by Ledger app version ${getVersionString( + version, + )}.`, + ) + } + + if ( + request.tx.treasury !== null && + !getCompatibility(version).supportsConway + ) { + throw new DeviceVersionUnsupported( + `Treasury amount not supported by Ledger app version ${getVersionString( + version, + )}.`, + ) + } + + if ( + request.tx.donation !== null && + !getCompatibility(version).supportsConway + ) { + throw new DeviceVersionUnsupported( + `Treasury donation not supported by Ledger app version ${getVersionString( + version, + )}.`, + ) + } + // catalyst/CIP36 registration is a specific type of auxiliary data that requires a HW wallet signature const auxiliaryData = request.tx?.auxiliaryData const hasCIP15Registration = @@ -1401,11 +1525,24 @@ export function* signTransaction( yield* signTx_addTotalCollateral(tx.totalCollateral) } - // reference input - if (tx.referenceInputs != null) { - for (const referenceInput of tx.referenceInputs) { - yield* signTx_addReferenceInput(referenceInput) - } + // reference inputs + for (const referenceInput of tx.referenceInputs) { + yield* signTx_addReferenceInput(referenceInput) + } + + // voting procedures + for (const voterVotes of tx.votingProcedures) { + yield* signTx_addVoterVotes(voterVotes) + } + + // treasury + if (tx.treasury != null) { + yield* signTx_addTreasury(tx.treasury) + } + + // donation + if (tx.donation != null) { + yield* signTx_addDonation(tx.donation) } // confirm diff --git a/src/parsing/certificate.ts b/src/parsing/certificate.ts index 84467cdd..250f6b0e 100644 --- a/src/parsing/certificate.ts +++ b/src/parsing/certificate.ts @@ -1,34 +1,98 @@ +import {unreachable} from '../utils/assert' import {InvalidData} from '../errors' import {InvalidDataReason} from '../errors/invalidDataReason' +import { + DRepType, + ParsedDRep, + SCRIPT_HASH_LENGTH, + CertificateType, + KEY_HASH_LENGTH, + Uint64_str, +} from '../types/internal' import type {ParsedCertificate} from '../types/internal' -import {CertificateType, KEY_HASH_LENGTH} from '../types/internal' +import {bigint_like, DRepParams, DRepParamsType} from '../types/public' import type {Certificate} from '../types/public' import { parseBIP32Path, parseHexStringOfLength, - parseStakeCredential, + parseCredential, parseUint64_str, + parseAnchor, + parseCoin, } from '../utils/parse' import {parsePoolParams} from './poolRegistration' +function parseDRep(dRep: DRepParams, errMsg: InvalidDataReason): ParsedDRep { + switch (dRep.type) { + case DRepParamsType.KEY_PATH: + return { + type: DRepType.KEY_PATH, + path: parseBIP32Path(dRep.keyPath, errMsg), + } + case DRepParamsType.KEY_HASH: + return { + type: DRepType.KEY_HASH, + keyHashHex: parseHexStringOfLength( + dRep.keyHashHex, + KEY_HASH_LENGTH, + errMsg, + ), + } + case DRepParamsType.SCRIPT_HASH: + return { + type: DRepType.SCRIPT_HASH, + scriptHashHex: parseHexStringOfLength( + dRep.scriptHashHex, + SCRIPT_HASH_LENGTH, + errMsg, + ), + } + case DRepParamsType.ABSTAIN: + return { + type: DRepType.ABSTAIN, + } + case DRepParamsType.NO_CONFIDENCE: + return { + type: DRepType.NO_CONFIDENCE, + } + default: + unreachable(dRep) + } +} + +function parseDeposit(deposit: bigint_like): Uint64_str { + return parseCoin(deposit, InvalidDataReason.CERTIFICATE_INVALID_DEPOSIT) +} + export function parseCertificate(cert: Certificate): ParsedCertificate { switch (cert.type) { case CertificateType.STAKE_REGISTRATION: case CertificateType.STAKE_DEREGISTRATION: { return { type: cert.type, - stakeCredential: parseStakeCredential( + stakeCredential: parseCredential( cert.params.stakeCredential, - InvalidDataReason.CERTIFICATE_INVALID_SCRIPT_HASH, + InvalidDataReason.CERTIFICATE_INVALID_STAKE_CREDENTIAL, ), } } + case CertificateType.STAKE_REGISTRATION_CONWAY: + case CertificateType.STAKE_DEREGISTRATION_CONWAY: { + return { + type: cert.type, + stakeCredential: parseCredential( + cert.params.stakeCredential, + InvalidDataReason.CERTIFICATE_INVALID_STAKE_CREDENTIAL, + ), + deposit: parseDeposit(cert.params.deposit), + } + } case CertificateType.STAKE_DELEGATION: { return { type: cert.type, - stakeCredential: parseStakeCredential( + stakeCredential: parseCredential( cert.params.stakeCredential, - InvalidDataReason.CERTIFICATE_INVALID_SCRIPT_HASH, + InvalidDataReason.CERTIFICATE_INVALID_STAKE_CREDENTIAL, ), poolKeyHashHex: parseHexStringOfLength( cert.params.poolKeyHashHex, @@ -37,6 +101,76 @@ export function parseCertificate(cert: Certificate): ParsedCertificate { ), } } + case CertificateType.VOTE_DELEGATION: { + return { + type: cert.type, + stakeCredential: parseCredential( + cert.params.stakeCredential, + InvalidDataReason.CERTIFICATE_INVALID_STAKE_CREDENTIAL, + ), + dRep: parseDRep( + cert.params.dRep, + InvalidDataReason.CERTIFICATE_INVALID_DREP, + ), + } + } + case CertificateType.AUTHORIZE_COMMITTEE_HOT: { + return { + type: cert.type, + coldCredential: parseCredential( + cert.params.coldCredential, + InvalidDataReason.CERTIFICATE_INVALID_COMMITTEE_CREDENTIAL, + ), + hotCredential: parseCredential( + cert.params.hotCredential, + InvalidDataReason.CERTIFICATE_INVALID_COMMITTEE_CREDENTIAL, + ), + } + } + case CertificateType.RESIGN_COMMITTEE_COLD: { + return { + type: cert.type, + coldCredential: parseCredential( + cert.params.coldCredential, + InvalidDataReason.CERTIFICATE_INVALID_COMMITTEE_CREDENTIAL, + ), + anchor: + cert.params.anchor == null ? null : parseAnchor(cert.params.anchor), + } + } + case CertificateType.DREP_REGISTRATION: { + return { + type: cert.type, + dRepCredential: parseCredential( + cert.params.dRepCredential, + InvalidDataReason.CERTIFICATE_INVALID_DREP_CREDENTIAL, + ), + deposit: parseDeposit(cert.params.deposit), + anchor: + cert.params.anchor == null ? null : parseAnchor(cert.params.anchor), + } + } + case CertificateType.DREP_DEREGISTRATION: { + return { + type: cert.type, + dRepCredential: parseCredential( + cert.params.dRepCredential, + InvalidDataReason.CERTIFICATE_INVALID_DREP_CREDENTIAL, + ), + deposit: parseDeposit(cert.params.deposit), + } + } + case CertificateType.DREP_UPDATE: { + return { + type: cert.type, + dRepCredential: parseCredential( + cert.params.dRepCredential, + InvalidDataReason.CERTIFICATE_INVALID_DREP_CREDENTIAL, + ), + anchor: + cert.params.anchor == null ? null : parseAnchor(cert.params.anchor), + } + } case CertificateType.STAKE_POOL_REGISTRATION: { return { type: cert.type, diff --git a/src/parsing/output.ts b/src/parsing/output.ts index e0229911..8ab3e633 100644 --- a/src/parsing/output.ts +++ b/src/parsing/output.ts @@ -27,17 +27,14 @@ import { } from '../types/public' import { isArray, + parseCoin, parseHexString, parseHexStringOfLength, parseUint64_str, validate, } from '../utils/parse' import {parseAddress} from './address' -import { - ASSET_GROUPS_MAX, - MAX_LOVELACE_SUPPLY_STR, - TOKENS_IN_GROUP_MAX, -} from './constants' +import {ASSET_GROUPS_MAX, TOKENS_IN_GROUP_MAX} from './constants' type ParseTokenAmountFn = ( val: unknown, @@ -241,9 +238,8 @@ export function parseTxOutput( ? TxOutputFormat.MAP_BABBAGE : TxOutputFormat.ARRAY_LEGACY - const amount = parseUint64_str( + const amount = parseCoin( output.amount, - {max: MAX_LOVELACE_SUPPLY_STR}, InvalidDataReason.OUTPUT_INVALID_AMOUNT, ) diff --git a/src/parsing/poolRegistration.ts b/src/parsing/poolRegistration.ts index 90a18cbd..d4814901 100644 --- a/src/parsing/poolRegistration.ts +++ b/src/parsing/poolRegistration.ts @@ -18,6 +18,8 @@ import { RelayType, REWARD_ACCOUNT_HEX_LENGTH, VRF_KEY_HASH_LENGTH, + MAX_DNS_NAME_LENGTH, + MAX_URL_LENGTH, } from '../types/internal' import type { MultiHostRelayParams, @@ -46,10 +48,10 @@ import { parseIntFromStr, parseUint64_str, validate, + parseCoin, } from '../utils/parse' import {hex_to_buf} from '../utils/serialize' import { - MAX_LOVELACE_SUPPLY_STR, POOL_REGISTRATION_OWNERS_MAX, POOL_REGISTRATION_RELAYS_MAX, } from './constants' @@ -211,7 +213,7 @@ function parseDnsName( errMsg: InvalidDataReason, ): VarLenAsciiString { validate(isString(dnsName), errMsg) - validate(dnsName.length <= 64, errMsg) + validate(dnsName.length <= MAX_DNS_NAME_LENGTH, errMsg) validate(dnsName.length > 0, errMsg) // eslint-disable-next-line no-control-regex validate(/^[\x00-\x7F]*$/.test(dnsName), errMsg) @@ -283,7 +285,7 @@ function parsePoolMetadataParams( ) // Additional length check validate( - url.length <= 64, + url.length <= MAX_URL_LENGTH, InvalidDataReason.POOL_REGISTRATION_METADATA_INVALID_URL, ) @@ -309,14 +311,12 @@ export function parsePoolParams( VRF_KEY_HASH_LENGTH, InvalidDataReason.POOL_REGISTRATION_INVALID_VRF_KEY_HASH, ) - const pledge = parseUint64_str( + const pledge = parseCoin( params.pledge, - {max: MAX_LOVELACE_SUPPLY_STR}, InvalidDataReason.POOL_REGISTRATION_INVALID_PLEDGE, ) - const cost = parseUint64_str( + const cost = parseCoin( params.cost, - {max: MAX_LOVELACE_SUPPLY_STR}, InvalidDataReason.POOL_REGISTRATION_INVALID_COST, ) const margin = parseMargin(params.margin) diff --git a/src/parsing/transaction.ts b/src/parsing/transaction.ts index 7bd54d07..54272903 100644 --- a/src/parsing/transaction.ts +++ b/src/parsing/transaction.ts @@ -1,30 +1,32 @@ import {InvalidData} from '../errors' import {InvalidDataReason} from '../errors/invalidDataReason' -import type { +import type {ParsedSigningRequest, ParsedTransaction} from '../types/internal' +import { ParsedCertificate, ParsedInput, ParsedRequiredSigner, - ParsedSigningRequest, - ParsedTransaction, + ParsedVote, + ParsedVoter, + ParsedVoterVotes, ParsedWithdrawal, -} from '../types/internal' -import { + SCRIPT_HASH_LENGTH, CertificateType, KEY_HASH_LENGTH, RequiredSignerType, SCRIPT_DATA_HASH_LENGTH, - StakeCredentialType, + CredentialType, TX_HASH_LENGTH, } from '../types/internal' -import type { +import type {SignTransactionRequest, Transaction} from '../types/public' +import { Certificate, RequiredSigner, - SignTransactionRequest, - Transaction, TxInput, + Vote, + Voter, + VoterType, + VoterVotes, Withdrawal, -} from '../types/public' -import { PoolKeyType, PoolOwnerType, TransactionSigningMode, @@ -37,10 +39,12 @@ import { parseBIP32Path, parseHexStringOfLength, parseInt64_str, - parseStakeCredential, + parseCredential, parseUint32_t, parseUint64_str, validate, + parseAnchor, + parseCoin, } from '../utils/parse' import {parseCertificate} from './certificate' import {MAX_LOVELACE_SUPPLY_STR} from './constants' @@ -85,12 +89,11 @@ function parseTxInput(input: TxInput): ParsedInput { function parseWithdrawal(params: Withdrawal): ParsedWithdrawal { return { - amount: parseUint64_str( + amount: parseCoin( params.amount, - {max: MAX_LOVELACE_SUPPLY_STR}, InvalidDataReason.WITHDRAWAL_INVALID_AMOUNT, ), - stakeCredential: parseStakeCredential( + stakeCredential: parseCredential( params.stakeCredential, InvalidDataReason.WITHDRAWAL_INVALID_STAKE_CREDENTIAL, ), @@ -123,6 +126,75 @@ function parseRequiredSigner( } } +function parseVoter(voter: Voter): ParsedVoter { + const errMsg = InvalidDataReason.VOTER_INVALID + switch (voter.type) { + case VoterType.COMMITTEE_KEY_HASH: + case VoterType.DREP_KEY_HASH: + case VoterType.STAKE_POOL_KEY_HASH: + return { + type: voter.type, + keyHashHex: parseHexStringOfLength( + voter.keyHashHex, + KEY_HASH_LENGTH, + errMsg, + ), + } + case VoterType.COMMITTEE_KEY_PATH: + case VoterType.DREP_KEY_PATH: + case VoterType.STAKE_POOL_KEY_PATH: + return { + type: voter.type, + keyPath: parseBIP32Path(voter.keyPath, errMsg), + } + + case VoterType.DREP_SCRIPT_HASH: + case VoterType.COMMITTEE_SCRIPT_HASH: + return { + type: voter.type, + scriptHashHex: parseHexStringOfLength( + voter.scriptHashHex, + SCRIPT_HASH_LENGTH, + errMsg, + ), + } + + default: + unreachable(voter) + } +} + +function parseVote(vote: Vote): ParsedVote { + return { + govActionId: { + txHashHex: parseHexStringOfLength( + vote.govActionId.txHashHex, + TX_HASH_LENGTH, + InvalidDataReason.GOV_ACTION_ID_INVALID_TX_HASH, + ), + govActionIndex: parseUint32_t( + vote.govActionId.govActionIndex, + InvalidDataReason.GOV_ACTION_ID_INVALID_INDEX, + ), + }, + votingProcedure: { + vote: vote.votingProcedure.vote, + anchor: + vote.votingProcedure.anchor == null + ? null + : parseAnchor(vote.votingProcedure.anchor), + }, + } +} + +function parseVoterVotes(voterVotes: VoterVotes): ParsedVoterVotes { + validate(isArray(voterVotes.votes), InvalidDataReason.VOTER_VOTES_NOT_ARRAY) + return { + voter: parseVoter(voterVotes.voter), + votes: voterVotes.votes.map((v) => parseVote(v)), + } +} + export function parseSigningMode( mode: TransactionSigningMode, ): TransactionSigningMode { @@ -149,11 +221,7 @@ export function parseTransaction(tx: Transaction): ParsedTransaction { const outputs = tx.outputs.map((o) => parseTxOutput(o, tx.network)) // fee - const fee = parseUint64_str( - tx.fee, - {max: MAX_LOVELACE_SUPPLY_STR}, - InvalidDataReason.FEE_INVALID, - ) + const fee = parseCoin(tx.fee, InvalidDataReason.FEE_INVALID) // ttl const ttl = @@ -251,9 +319,8 @@ export function parseTransaction(tx: Transaction): ParsedTransaction { const totalCollateral = tx.totalCollateral == null ? null - : parseUint64_str( + : parseCoin( tx.totalCollateral, - {max: MAX_LOVELACE_SUPPLY_STR}, InvalidDataReason.TOTAL_COLLATERAL_NOT_VALID, ) @@ -266,6 +333,41 @@ export function parseTransaction(tx: Transaction): ParsedTransaction { parseTxInput(ri), ) + // voting procedures + validate( + isArray(tx.votingProcedures ?? []), + InvalidDataReason.VOTING_PROCEDURES_NOT_ARRAY, + ) + const votingProcedures = (tx.votingProcedures ?? []).map((x) => + parseVoterVotes(x), + ) + validate( + votingProcedures.length <= 1, + InvalidDataReason.VOTING_PROCEDURES_INVALID_NUMBER_OF_VOTERS, + ) + for (const voterVotes of votingProcedures) { + validate( + voterVotes.votes.length === 1, + InvalidDataReason.VOTING_PROCEDURES_INVALID_NUMBER_OF_VOTES, + ) + } + + // treasury + const treasury = + tx.treasury == null + ? null + : parseCoin(tx.treasury, InvalidDataReason.TREASURY_NOT_VALID) + + // donation + const donation = + tx.donation == null + ? null + : parseUint64_str( + tx.donation, + {min: '1', max: MAX_LOVELACE_SUPPLY_STR}, + InvalidDataReason.DONATION_NOT_VALID, + ) + return { network, inputs, @@ -284,6 +386,9 @@ export function parseTransaction(tx: Transaction): ParsedTransaction { collateralOutput, totalCollateral, referenceInputs, + votingProcedures, + treasury, + donation, } } @@ -312,16 +417,18 @@ export function parseSignTransactionRequest( ), InvalidDataReason.SIGN_MODE_ORDINARY__POOL_REGISTRATION_NOT_ALLOWED, ) - // certificate stake credentials given by paths + // certificate credentials given by paths validate( tx.certificates.every((certificate) => { switch (certificate.type) { case CertificateType.STAKE_REGISTRATION: + case CertificateType.STAKE_REGISTRATION_CONWAY: case CertificateType.STAKE_DEREGISTRATION: + case CertificateType.STAKE_DEREGISTRATION_CONWAY: case CertificateType.STAKE_DELEGATION: + case CertificateType.VOTE_DELEGATION: return ( - certificate.stakeCredential.type === - StakeCredentialType.KEY_PATH + certificate.stakeCredential.type === CredentialType.KEY_PATH ) default: return true @@ -329,11 +436,37 @@ export function parseSignTransactionRequest( }), InvalidDataReason.SIGN_MODE_ORDINARY__CERTIFICATE_STAKE_CREDENTIAL_ONLY_AS_PATH, ) + validate( + tx.certificates.every((certificate) => { + switch (certificate.type) { + case CertificateType.AUTHORIZE_COMMITTEE_HOT: + case CertificateType.RESIGN_COMMITTEE_COLD: + return certificate.coldCredential.type === CredentialType.KEY_PATH + default: + return true + } + }), + InvalidDataReason.SIGN_MODE_ORDINARY__CERTIFICATE_COMMITTEE_COLD_CREDENTIAL_ONLY_AS_PATH, + ) + validate( + tx.certificates.every((certificate) => { + switch (certificate.type) { + case CertificateType.DREP_REGISTRATION: + case CertificateType.DREP_DEREGISTRATION: + case CertificateType.DREP_UPDATE: + return certificate.dRepCredential.type === CredentialType.KEY_PATH + default: + return true + } + }), + InvalidDataReason.SIGN_MODE_ORDINARY__CERTIFICATE_DREP_CREDENTIAL_ONLY_AS_PATH, + ) + // withdrawals as paths validate( tx.withdrawals.every( (withdrawal) => - withdrawal.stakeCredential.type === StakeCredentialType.KEY_PATH, + withdrawal.stakeCredential.type === CredentialType.KEY_PATH, ), InvalidDataReason.SIGN_MODE_ORDINARY__WITHDRAWAL_ONLY_AS_PATH, ) @@ -361,6 +494,21 @@ export function parseSignTransactionRequest( InvalidDataReason.SIGN_MODE_ORDINARY__REFERENCE_INPUTS_NOT_ALLOWED, ) + // voting procedure voter must be given by path + validate( + tx.votingProcedures.every((voterVotes) => { + switch (voterVotes.voter.type) { + case VoterType.COMMITTEE_KEY_PATH: + case VoterType.DREP_KEY_PATH: + case VoterType.STAKE_POOL_KEY_PATH: + return true + default: + return false + } + }), + InvalidDataReason.SIGN_MODE_ORDINARY__VOTER_ONLY_AS_PATH, + ) + break } @@ -389,28 +537,41 @@ export function parseSignTransactionRequest( ), InvalidDataReason.SIGN_MODE_MULTISIG__POOL_RETIREMENT_NOT_ALLOWED, ) - // certificate stake credentials given by scripts + // certificate credentials given by scripts validate( tx.certificates.every((certificate) => { switch (certificate.type) { case CertificateType.STAKE_REGISTRATION: + case CertificateType.STAKE_REGISTRATION_CONWAY: case CertificateType.STAKE_DEREGISTRATION: + case CertificateType.STAKE_DEREGISTRATION_CONWAY: case CertificateType.STAKE_DELEGATION: + case CertificateType.VOTE_DELEGATION: + return ( + certificate.stakeCredential.type === CredentialType.SCRIPT_HASH + ) + case CertificateType.AUTHORIZE_COMMITTEE_HOT: + case CertificateType.RESIGN_COMMITTEE_COLD: + return ( + certificate.coldCredential.type === CredentialType.SCRIPT_HASH + ) + case CertificateType.DREP_REGISTRATION: + case CertificateType.DREP_DEREGISTRATION: + case CertificateType.DREP_UPDATE: return ( - certificate.stakeCredential.type === - StakeCredentialType.SCRIPT_HASH + certificate.dRepCredential.type === CredentialType.SCRIPT_HASH ) default: return true } }), - InvalidDataReason.SIGN_MODE_MULTISIG__CERTIFICATE_STAKE_CREDENTIAL_ONLY_AS_SCRIPT, + InvalidDataReason.SIGN_MODE_MULTISIG__CERTIFICATE_CREDENTIAL_ONLY_AS_SCRIPT, ) // withdrawals as scripts validate( tx.withdrawals.every( (withdrawal) => - withdrawal.stakeCredential.type === StakeCredentialType.SCRIPT_HASH, + withdrawal.stakeCredential.type === CredentialType.SCRIPT_HASH, ), InvalidDataReason.SIGN_MODE_MULTISIG__WITHDRAWAL_ONLY_AS_SCRIPT, ) @@ -432,12 +593,26 @@ export function parseSignTransactionRequest( InvalidDataReason.SIGN_MODE_MULTISIG__TOTAL_COLLATERAL_NOT_ALLOWED, ) - // cannot have reference input in the tx + // cannot have reference inputs in the tx validate( tx.referenceInputs.length === 0, InvalidDataReason.SIGN_MODE_MULTISIG__REFERENCE_INPUTS_NOT_ALLOWED, ) + // voting procedure voter must be given by script hash + validate( + tx.votingProcedures.every((voterVotes) => { + switch (voterVotes.voter.type) { + case VoterType.COMMITTEE_SCRIPT_HASH: + case VoterType.DREP_SCRIPT_HASH: + return true + default: + return false + } + }), + InvalidDataReason.SIGN_MODE_MULTISIG__VOTER_ONLY_AS_SCRIPT, + ) + break } @@ -535,12 +710,30 @@ export function parseSignTransactionRequest( InvalidDataReason.SIGN_MODE_POOL_OWNER__TOTAL_COLLATERAL_NOT_ALLOWED, ) - // cannot have reference input in the tx + // cannot have reference inputs in the tx validate( tx.referenceInputs.length === 0, InvalidDataReason.SIGN_MODE_POOL_OWNER__REFERENCE_INPUTS_NOT_ALLOWED, ) + // cannot have voting procedures in the tx + validate( + tx.votingProcedures.length === 0, + InvalidDataReason.SIGN_MODE_POOL_OWNER__VOTING_PROCEDURES_NOT_ALLOWED, + ) + + // cannot have treasury in the tx + validate( + tx.treasury == null, + InvalidDataReason.SIGN_MODE_POOL_OWNER__TREASURY_NOT_ALLOWED, + ) + + // cannot have donation in the tx + validate( + tx.donation == null, + InvalidDataReason.SIGN_MODE_POOL_OWNER__DONATION_NOT_ALLOWED, + ) + break } @@ -624,12 +817,30 @@ export function parseSignTransactionRequest( InvalidDataReason.SIGN_MODE_POOL_OPERATOR__TOTAL_COLLATERAL_NOT_ALLOWED, ) - // cannot have reference input in the tx + // cannot have reference inputs in the tx validate( tx.referenceInputs.length === 0, InvalidDataReason.SIGN_MODE_POOL_OPERATOR__REFERENCE_INPUTS_NOT_ALLOWED, ) + // cannot have voting procedures in the tx + validate( + tx.votingProcedures.length === 0, + InvalidDataReason.SIGN_MODE_POOL_OPERATOR__VOTING_PROCEDURES_NOT_ALLOWED, + ) + + // cannot have treasury in the tx + validate( + tx.treasury == null, + InvalidDataReason.SIGN_MODE_POOL_OPERATOR__TREASURY_NOT_ALLOWED, + ) + + // cannot have donation in the tx + validate( + tx.donation == null, + InvalidDataReason.SIGN_MODE_POOL_OPERATOR__DONATION_NOT_ALLOWED, + ) + break } diff --git a/src/types/internal.ts b/src/types/internal.ts index 4fe1deca..bf96cb80 100644 --- a/src/types/internal.ts +++ b/src/types/internal.ts @@ -14,6 +14,8 @@ import { TxAuxiliaryDataType, TxOutputDestinationType, TxOutputFormat, + VoteOption, + VoterType, } from './public' // Basic primitives @@ -65,42 +67,126 @@ export const REWARD_ACCOUNT_HEX_LENGTH = 29 export const ED25519_SIGNATURE_LENGTH = 64 export const SCRIPT_DATA_HASH_LENGTH = 32 export const DATUM_HASH_LENGTH = 32 +export const ANCHOR_HASH_LENGTH = 32 -export const enum StakeCredentialType { +export const MAX_URL_LENGTH = 64 +export const MAX_DNS_NAME_LENGTH = 64 + +export type ParsedInput = { + txHashHex: FixLenHexString + outputIndex: Uint32_t + path: ValidBIP32Path | null +} + +export const enum CredentialType { // enum values are affected by backwards-compatibility KEY_PATH = 0, KEY_HASH = 2, SCRIPT_HASH = 1, } -export type ParsedStakeCredential = +export type ParsedCredential = | { - type: StakeCredentialType.KEY_PATH + type: CredentialType.KEY_PATH path: ValidBIP32Path } | { - type: StakeCredentialType.KEY_HASH + type: CredentialType.KEY_HASH keyHashHex: FixLenHexString } | { - type: StakeCredentialType.SCRIPT_HASH + type: CredentialType.SCRIPT_HASH scriptHashHex: FixLenHexString } +export const enum DRepType { + KEY_HASH = 0, + KEY_PATH = 100, + SCRIPT_HASH = 1, + ABSTAIN = 2, + NO_CONFIDENCE = 3, +} + +export type ParsedDRep = + | { + type: DRepType.KEY_PATH + path: ValidBIP32Path + } + | { + type: DRepType.KEY_HASH + keyHashHex: FixLenHexString + } + | { + type: DRepType.SCRIPT_HASH + scriptHashHex: FixLenHexString + } + | { + type: DRepType.ABSTAIN + } + | { + type: DRepType.NO_CONFIDENCE + } + +export type ParsedAnchor = { + url: VarLenAsciiString + hashHex: FixLenHexString +} & {__brand: 'anchor'} + export type ParsedCertificate = | { type: CertificateType.STAKE_REGISTRATION - stakeCredential: ParsedStakeCredential + stakeCredential: ParsedCredential + } + | { + type: CertificateType.STAKE_REGISTRATION_CONWAY + stakeCredential: ParsedCredential + deposit: Uint64_str } | { type: CertificateType.STAKE_DEREGISTRATION - stakeCredential: ParsedStakeCredential + stakeCredential: ParsedCredential + } + | { + type: CertificateType.STAKE_DEREGISTRATION_CONWAY + stakeCredential: ParsedCredential + deposit: Uint64_str } | { type: CertificateType.STAKE_DELEGATION - stakeCredential: ParsedStakeCredential + stakeCredential: ParsedCredential poolKeyHashHex: FixLenHexString } + | { + type: CertificateType.VOTE_DELEGATION + stakeCredential: ParsedCredential + dRep: ParsedDRep + } + | { + type: CertificateType.AUTHORIZE_COMMITTEE_HOT + coldCredential: ParsedCredential + hotCredential: ParsedCredential + } + | { + type: CertificateType.RESIGN_COMMITTEE_COLD + coldCredential: ParsedCredential + anchor: ParsedAnchor | null + } + | { + type: CertificateType.DREP_REGISTRATION + dRepCredential: ParsedCredential + deposit: Uint64_str + anchor: ParsedAnchor | null + } + | { + type: CertificateType.DREP_DEREGISTRATION + dRepCredential: ParsedCredential + deposit: Uint64_str + } + | { + type: CertificateType.DREP_UPDATE + dRepCredential: ParsedCredential + anchor: ParsedAnchor | null + } | { type: CertificateType.STAKE_POOL_REGISTRATION pool: ParsedPoolParams @@ -124,9 +210,78 @@ export type ParsedAssetGroup = { tokens: Array> } -export type ParsedNetwork = { - protocolMagic: Uint32_t - networkId: Uint8_t +export type ParsedWithdrawal = { + amount: Uint64_str + stakeCredential: ParsedCredential +} + +export const enum RequiredSignerType { + PATH = 0, + HASH = 1, +} + +export type ParsedRequiredSigner = + | { + type: RequiredSignerType.HASH + hashHex: FixLenHexString + } + | { + type: RequiredSignerType.PATH + path: ValidBIP32Path + } + +export type ParsedGovActionId = { + txHashHex: FixLenHexString + govActionIndex: Uint32_t +} + +export type ParsedVotingProcedure = { + vote: VoteOption + anchor: ParsedAnchor | null +} + +export type ParsedVote = { + govActionId: ParsedGovActionId + votingProcedure: ParsedVotingProcedure +} + +export type ParsedVoter = + | { + type: VoterType.COMMITTEE_KEY_HASH + keyHashHex: FixLenHexString + } + | { + type: VoterType.COMMITTEE_KEY_PATH + keyPath: ValidBIP32Path + } + | { + type: VoterType.COMMITTEE_SCRIPT_HASH + scriptHashHex: FixLenHexString + } + | { + type: VoterType.DREP_KEY_HASH + keyHashHex: FixLenHexString + } + | { + type: VoterType.DREP_KEY_PATH + keyPath: ValidBIP32Path + } + | { + type: VoterType.DREP_SCRIPT_HASH + scriptHashHex: FixLenHexString + } + | { + type: VoterType.STAKE_POOL_KEY_HASH + keyHashHex: FixLenHexString + } + | { + type: VoterType.STAKE_POOL_KEY_PATH + keyPath: ValidBIP32Path + } + +export type ParsedVoterVotes = { + voter: ParsedVoter + votes: Array } export const CVOTE_PUBLIC_KEY_LENGTH = 32 @@ -166,6 +321,11 @@ export type ParsedCVoteDelegation = weight: Uint32_t } +export type ParsedNetwork = { + protocolMagic: Uint32_t + networkId: Uint8_t +} + export type ParsedTransaction = { network: ParsedNetwork inputs: ParsedInput[] @@ -184,6 +344,9 @@ export type ParsedTransaction = { collateralOutput: ParsedOutput | null totalCollateral: Uint64_str | null referenceInputs: ParsedInput[] + votingProcedures: ParsedVoterVotes[] + treasury: Uint64_str | null + donation: Uint64_str | null } export type ParsedSigningRequest = { @@ -192,34 +355,8 @@ export type ParsedSigningRequest = { additionalWitnessPaths: ValidBIP32Path[] } -export type ParsedInput = { - txHashHex: FixLenHexString - outputIndex: Uint32_t - path: ValidBIP32Path | null -} - -export type ParsedWithdrawal = { - amount: Uint64_str - stakeCredential: ParsedStakeCredential -} - export type ScriptDataHash = FixLenHexString -export const enum RequiredSignerType { - PATH = 0, - HASH = 1, -} - -export type ParsedRequiredSigner = - | { - type: RequiredSignerType.HASH - hashHex: FixLenHexString - } - | { - type: RequiredSignerType.PATH - path: ValidBIP32Path - } - export type ParsedMargin = { numerator: Uint64_str denominator: Uint64_str diff --git a/src/types/public.ts b/src/types/public.ts index e470eeb3..6d871859 100644 --- a/src/types/public.ts +++ b/src/types/public.ts @@ -81,6 +81,46 @@ export enum CertificateType { * @see [[PoolRegistrationParams]] */ STAKE_POOL_RETIREMENT = 4, + /** + * Staking key registration certificate with deposit + * @see [[StakeRegistrationConwayParams]] + */ + STAKE_REGISTRATION_CONWAY = 7, + /** + * Staking key deregistration certificate with deposit + * @see [[StakeDeregistrationConwayParams]] + */ + STAKE_DEREGISTRATION_CONWAY = 8, + /** + * Vote delegation certificate + * @see [[VoteDelegationParams]] + */ + VOTE_DELEGATION = 9, + /** + * Authorize constitutional committee member hot certificate + * @see [[AuthorizeCommitteeParams]] + */ + AUTHORIZE_COMMITTEE_HOT = 14, + /** + * Resign from constitutional committee certificate + * @see [[ResignCommitteeParams]] + */ + RESIGN_COMMITTEE_COLD = 15, + /** + * DRep registration certificate + * @see [[DRepRegistrationParams]] + */ + DREP_REGISTRATION = 16, + /** + * DRep deregistration certificate + * @see [[DRepDeregistrationParams]] + */ + DREP_DEREGISTRATION = 17, + /** + * DRep update certificate + * @see [[DRepUpdateParams]] + */ + DREP_UPDATE = 18, } /** @@ -760,31 +800,85 @@ export type PoolRetirementParams = { retirementEpoch: bigint_like } -export enum StakeCredentialParamsType { +export enum CredentialParamsType { + KEY_PATH, + KEY_HASH, + SCRIPT_HASH, +} + +export type KeyPathCredentialParams = { + type: CredentialParamsType.KEY_PATH + keyPath: BIP32Path +} + +export type KeyHashCredentialParams = { + type: CredentialParamsType.KEY_HASH + keyHashHex: string +} + +export type ScriptHashCredentialParams = { + type: CredentialParamsType.SCRIPT_HASH + scriptHashHex: string +} + +export type CredentialParams = + | KeyPathCredentialParams + | KeyHashCredentialParams + | ScriptHashCredentialParams + +export enum DRepParamsType { KEY_PATH, KEY_HASH, SCRIPT_HASH, + ABSTAIN, + NO_CONFIDENCE, } -export type KeyPathStakeCredentialParams = { - type: StakeCredentialParamsType.KEY_PATH +export type KeyPathDRepParams = { + type: DRepParamsType.KEY_PATH keyPath: BIP32Path } -export type KeyHashStakeCredentialParams = { - type: StakeCredentialParamsType.KEY_HASH +export type KeyHashDRepParams = { + type: DRepParamsType.KEY_HASH keyHashHex: string } -export type ScriptStakeCredentialParams = { - type: StakeCredentialParamsType.SCRIPT_HASH +export type ScriptHashDRepParams = { + type: DRepParamsType.SCRIPT_HASH scriptHashHex: string } -export type StakeCredentialParams = - | KeyPathStakeCredentialParams - | KeyHashStakeCredentialParams - | ScriptStakeCredentialParams +export type AbstainDRepParams = { + type: DRepParamsType.ABSTAIN +} + +export type NoConfidenceParams = { + type: DRepParamsType.NO_CONFIDENCE +} + +export type DRepParams = + | KeyPathDRepParams + | KeyHashDRepParams + | ScriptHashDRepParams + | AbstainDRepParams + | NoConfidenceParams + +/** + * Anchor for committee and DRep certificates + * @category Shelley + * @see [[Certificate]] + */ +export type AnchorParams = { + /** + * Anchor URL + */ + url: string + /** + * Anchor data hash in hex + */ + hashHex: string +} /** * Stake key registration certificate parameters @@ -795,7 +889,23 @@ export type StakeRegistrationParams = { /** * Id to be registered */ - stakeCredential: StakeCredentialParams + stakeCredential: CredentialParams +} + +/** + * Stake key registration certificate parameters since Conway era + * @category Shelley + * @see [[Certificate]] + */ +export type StakeRegistrationConwayParams = { + /** + * Id to be registered + */ + stakeCredential: CredentialParams + /** + * Deposit (in Lovelace). + */ + deposit: bigint_like } /** @@ -807,7 +917,23 @@ export type StakeDeregistrationParams = { /** * Id to be deregistered */ - stakeCredential: StakeCredentialParams + stakeCredential: CredentialParams +} + +/** + * Stake key deregistration certificate parameters since Conway era + * @category Shelley + * @see [[Certificate]] + */ +export type StakeDeregistrationConwayParams = { + /** + * Id to be deregistered + */ + stakeCredential: CredentialParams + /** + * Deposit (in Lovelace). + */ + deposit: bigint_like } /** @@ -819,13 +945,113 @@ export type StakeDelegationParams = { /** * Id of the staking entity / reward account that wants to delegate */ - stakeCredential: StakeCredentialParams + stakeCredential: CredentialParams /** * Pool ID user wants to delegate to */ poolKeyHashHex: string } +/** + * Vote delegation certificate parameters + * @category Shelley + * @see [[Certificate]] + * */ +export type VoteDelegationParams = { + /** + * Id of the staking entity that wants to delegate + */ + stakeCredential: CredentialParams + /** + * DRep to delegate to + */ + dRep: DRepParams +} + +/** + * Authorize committee hot key certificate parameters + * @category Shelley + * @see [[Certificate]] + * */ +export type AuthorizeCommitteeParams = { + /** + * Credential of the committee member that wants to authorize a hot key + */ + coldCredential: CredentialParams + /** + * Credential for the hot key + */ + hotCredential: CredentialParams +} + +/** + * Resign from committee certificate parameters + * @category Shelley + * @see [[Certificate]] + * */ +export type ResignCommitteeParams = { + /** + * Credential of the committee member that wants to resign + */ + coldCredential: CredentialParams + /** + * Anchor + */ + anchor?: AnchorParams | null +} + +/** + * DRep registration certificate parameters + * @category Shelley + * @see [[Certificate]] + * */ +export type DRepRegistrationParams = { + /** + * Credential of the DRep that wants to register + */ + dRepCredential: CredentialParams + /** + * Deposit (in Lovelace). + */ + deposit: bigint_like + /** + * Anchor + */ + anchor?: AnchorParams | null +} + +/** + * DRep deregistration certificate parameters + * @category Shelley + * @see [[Certificate]] + * */ +export type DRepDeregistrationParams = { + /** + * Credential of the DRep that wants to deregister + */ + dRepCredential: CredentialParams + /** + * Deposit (in Lovelace). + */ + deposit: bigint_like +} + +/** + * DRep update certificate parameters + * @category Shelley + * @see [[Certificate]] + * */ +export type DRepUpdateParams = { + /** + * Credential of the DRep that wants to register + */ + dRepCredential: CredentialParams + /** + * Anchor + */ + anchor?: AnchorParams | null +} + /** * Certificate. Can be one of multiple options. * @category Shelley @@ -841,10 +1067,42 @@ export type Certificate = type: CertificateType.STAKE_DEREGISTRATION params: StakeDeregistrationParams } + | { + type: CertificateType.STAKE_REGISTRATION_CONWAY + params: StakeRegistrationConwayParams + } + | { + type: CertificateType.STAKE_DEREGISTRATION_CONWAY + params: StakeDeregistrationConwayParams + } | { type: CertificateType.STAKE_DELEGATION params: StakeDelegationParams } + | { + type: CertificateType.VOTE_DELEGATION + params: VoteDelegationParams + } + | { + type: CertificateType.AUTHORIZE_COMMITTEE_HOT + params: AuthorizeCommitteeParams + } + | { + type: CertificateType.RESIGN_COMMITTEE_COLD + params: ResignCommitteeParams + } + | { + type: CertificateType.DREP_REGISTRATION + params: DRepRegistrationParams + } + | { + type: CertificateType.DREP_DEREGISTRATION + params: DRepDeregistrationParams + } + | { + type: CertificateType.DREP_UPDATE + params: DRepUpdateParams + } | { type: CertificateType.STAKE_POOL_REGISTRATION params: PoolRegistrationParams @@ -863,7 +1121,7 @@ export type Withdrawal = { /** * Path to rewards account being withdrawn */ - stakeCredential: StakeCredentialParams + stakeCredential: CredentialParams /** * Amount (in Lovelace) being withdrawn. * Note that Amount *must* be all accumulated rewards. @@ -972,6 +1230,10 @@ export type DeviceCompatibility = { * Whether we support CIP-36 voting (signing vote-casts by HW devices) */ supportsCIP36Vote: boolean + /** + * Whether we support Conway era transaction elements + */ + supportsConway: boolean } /** @@ -1231,6 +1493,111 @@ export type RequiredSigner = hashHex: string } +export enum VoterType { + COMMITTEE_KEY_HASH = 0, + COMMITTEE_KEY_PATH = 100, + COMMITTEE_SCRIPT_HASH = 1, + DREP_KEY_HASH = 2, + DREP_KEY_PATH = 102, + DREP_SCRIPT_HASH = 3, + STAKE_POOL_KEY_HASH = 4, + STAKE_POOL_KEY_PATH = 104, +} + +export type CommitteeKeyHashVoter = { + type: VoterType.COMMITTEE_KEY_HASH + keyHashHex: string +} + +export type CommitteeKeyPathVoter = { + type: VoterType.COMMITTEE_KEY_PATH + keyPath: BIP32Path +} + +export type CommitteeScriptHashVoter = { + type: VoterType.COMMITTEE_SCRIPT_HASH + scriptHashHex: string +} + +export type DRepKeyHashVoter = { + type: VoterType.DREP_KEY_HASH + keyHashHex: string +} + +export type DRepKeyPathVoter = { + type: VoterType.DREP_KEY_PATH + keyPath: BIP32Path +} + +export type DRepScriptHashVoter = { + type: VoterType.DREP_SCRIPT_HASH + scriptHashHex: string +} + +export type StakePoolKeyHashVoter = { + type: VoterType.STAKE_POOL_KEY_HASH + keyHashHex: string +} + +export type StakePoolKeyPathVoter = { + type: VoterType.STAKE_POOL_KEY_PATH + keyPath: BIP32Path +} + +export type Voter = + | CommitteeKeyHashVoter + | CommitteeKeyPathVoter + | CommitteeScriptHashVoter + | DRepKeyHashVoter + | DRepKeyPathVoter + | DRepScriptHashVoter + | StakePoolKeyHashVoter + | StakePoolKeyPathVoter + +export enum VoteOption { + NO = 0, + YES = 1, + ABSTAIN = 2, +} + +export type VotingProcedure = { + /** + * Vote + */ + vote: VoteOption + /** + * Anchor (optional) + */ + anchor?: AnchorParams | null +} + +export type GovActionId = { + /** + * UTxO's hash of the transaction + */ + txHashHex: string + /** + * UTxO's governance action index + */ + govActionIndex: number +} + +export type Vote = { + /** + * Governance action to vote about + */ + govActionId: GovActionId + /** + * Voting procedure + */ + votingProcedure: VotingProcedure +} + +export type VoterVotes = { + voter: Voter + votes: Array +} + /** * Represents transaction to be signed by the device. * Note that this represents a *superset* of what Ledger can sign due to certain hardware app/security limitations. @@ -1317,6 +1684,18 @@ export type Transaction = { * Reference inputs (UTxOs). Visible to Plutus scripts, but not spent. */ referenceInputs?: Array | null + /** + * Voting procedures. + */ + votingProcedures?: Array | null + /** + * Treasury amount (in Lovelace). + */ + treasury?: bigint_like | null + /** + * Treasury donation (in Lovelace). + */ + donation?: bigint_like | null } /** @@ -1344,7 +1723,7 @@ export enum TransactionSigningMode { * The API witnesses * - all non-null [[TxInput.path]] on `inputs` * - all [[Withdrawal.path]] on `withdrawals` - * - all [[StakeCredentialParams.path]] properties on `certificates` for Stake registering/deregistering/delegating certificate. + * - all [[CredentialParams.path]] properties on `certificates` for Stake registering/deregistering/delegating certificate. */ ORDINARY_TRANSACTION = 'ordinary_transaction', diff --git a/src/utils/parse.ts b/src/utils/parse.ts index 70fa831e..a6703c75 100644 --- a/src/utils/parse.ts +++ b/src/utils/parse.ts @@ -1,5 +1,5 @@ -import {InvalidData} from '../errors' -import type {InvalidDataReason} from '../errors/index' +import {MAX_LOVELACE_SUPPLY_STR} from '../parsing/constants' +import {InvalidData, InvalidDataReason} from '../errors/index' import type { _Int64_bigint, _Int64_num, @@ -8,21 +8,24 @@ import type { FixLenHexString, HexString, Int64_str, - ParsedStakeCredential, + ParsedCredential, Uint8_t, Uint16_t, Uint32_t, Uint64_str, ValidBIP32Path, VarLenAsciiString, + ParsedAnchor, } from '../types/internal' import { + ANCHOR_HASH_LENGTH, KEY_HASH_LENGTH, SCRIPT_HASH_LENGTH, - StakeCredentialType, + CredentialType, + MAX_URL_LENGTH, } from '../types/internal' -import type {StakeCredentialParams} from '../types/public' -import {StakeCredentialParamsType} from '../types/public' +import type {AnchorParams, bigint_like, CredentialParams} from '../types/public' +import {CredentialParamsType} from '../types/public' import {unreachable} from './assert' export const MAX_UINT_64_STR = '18446744073709551615' @@ -258,50 +261,75 @@ export function parseBIP32Path( return value } -export function parseStakeCredential( - stakeCredential: StakeCredentialParams, +export function parseIntFromStr( + str: string, + errMsg: InvalidDataReason, +): number { + validate(isString(str), errMsg) + const i = parseInt(str, 10) + // Check that we parsed everything + validate(`${i}` === str, errMsg) + // Could be invalid + validate(!isNaN(i), errMsg) + // Could still be float + validate(isInteger(i), errMsg) + return i +} + +export function parseCoin( + coin: bigint_like, + errMsg: InvalidDataReason, +): Uint64_str { + return parseUint64_str(coin, {max: MAX_LOVELACE_SUPPLY_STR}, errMsg) +} + +export function parseCredential( + credential: CredentialParams, errMsg: InvalidDataReason, -): ParsedStakeCredential { - switch (stakeCredential.type) { - case StakeCredentialParamsType.KEY_PATH: +): ParsedCredential { + switch (credential.type) { + case CredentialParamsType.KEY_PATH: return { - type: StakeCredentialType.KEY_PATH, - path: parseBIP32Path(stakeCredential.keyPath, errMsg), + type: CredentialType.KEY_PATH, + path: parseBIP32Path(credential.keyPath, errMsg), } - case StakeCredentialParamsType.KEY_HASH: + case CredentialParamsType.KEY_HASH: return { - type: StakeCredentialType.KEY_HASH, + type: CredentialType.KEY_HASH, keyHashHex: parseHexStringOfLength( - stakeCredential.keyHashHex, + credential.keyHashHex, KEY_HASH_LENGTH, errMsg, ), } - case StakeCredentialParamsType.SCRIPT_HASH: + case CredentialParamsType.SCRIPT_HASH: return { - type: StakeCredentialType.SCRIPT_HASH, + type: CredentialType.SCRIPT_HASH, scriptHashHex: parseHexStringOfLength( - stakeCredential.scriptHashHex, + credential.scriptHashHex, SCRIPT_HASH_LENGTH, errMsg, ), } default: - unreachable(stakeCredential) + unreachable(credential) } } -export function parseIntFromStr( - str: string, - errMsg: InvalidDataReason, -): number { - validate(isString(str), errMsg) - const i = parseInt(str, 10) - // Check that we parsed everything - validate(`${i}` === str, errMsg) - // Could be invalid - validate(!isNaN(i), errMsg) - // Could still be float - validate(isInteger(i), errMsg) - return i +export function parseAnchor(params: AnchorParams): ParsedAnchor | null { + const url = parseAscii(params.url, InvalidDataReason.ANCHOR_INVALID_URL) + // Additional length check + validate(url.length <= MAX_URL_LENGTH, InvalidDataReason.ANCHOR_INVALID_URL) + + const hashHex = parseHexStringOfLength( + params.hashHex, + ANCHOR_HASH_LENGTH, + InvalidDataReason.ANCHOR_INVALID_HASH, + ) + + return { + url, + hashHex, + __brand: 'anchor' as const, + } } diff --git a/src/utils/serialize.ts b/src/utils/serialize.ts index 46617d46..ee13521c 100644 --- a/src/utils/serialize.ts +++ b/src/utils/serialize.ts @@ -4,13 +4,14 @@ import type { FixLenHexString, HexString, Int64_str, - ParsedStakeCredential, + ParsedCredential, Uint8_t, Uint16_t, Uint32_t, Uint64_str, + ParsedAnchor, } from '../types/internal' -import {StakeCredentialType} from '../types/internal' +import {CredentialType} from '../types/internal' import {assert, unreachable} from './assert' import { isHexString, @@ -98,37 +99,51 @@ export function path_to_buf(path: Array): Buffer { return data } -export function stake_credential_to_buf( - stakeCredential: ParsedStakeCredential, -): Buffer { - switch (stakeCredential.type) { - case StakeCredentialType.KEY_PATH: +export function serializeOptionFlag(included: boolean): Buffer { + const SignTxIncluded = { + NO: 1 as Uint8_t, + YES: 2 as Uint8_t, + } + + const value = included ? SignTxIncluded.YES : SignTxIncluded.NO + + return uint8_to_buf(value) +} + +export function serializeCoin(coin: Uint64_str): Buffer { + return Buffer.concat([uint64_to_buf(coin)]) +} + +export function serializeCredential(credential: ParsedCredential): Buffer { + switch (credential.type) { + case CredentialType.KEY_PATH: return Buffer.concat([ - uint8_to_buf(stakeCredential.type as Uint8_t), - path_to_buf(stakeCredential.path), + uint8_to_buf(credential.type as Uint8_t), + path_to_buf(credential.path), ]) - case StakeCredentialType.KEY_HASH: + case CredentialType.KEY_HASH: return Buffer.concat([ - uint8_to_buf(stakeCredential.type as Uint8_t), - hex_to_buf(stakeCredential.keyHashHex), + uint8_to_buf(credential.type as Uint8_t), + hex_to_buf(credential.keyHashHex), ]) - case StakeCredentialType.SCRIPT_HASH: + case CredentialType.SCRIPT_HASH: return Buffer.concat([ - uint8_to_buf(stakeCredential.type as Uint8_t), - hex_to_buf(stakeCredential.scriptHashHex), + uint8_to_buf(credential.type as Uint8_t), + hex_to_buf(credential.scriptHashHex), ]) default: - unreachable(stakeCredential) + unreachable(credential) } } -export function serializeOptionFlag(included: boolean) { - const SignTxIncluded = { - NO: 1 as Uint8_t, - YES: 2 as Uint8_t, +export function serializeAnchor(anchor: ParsedAnchor | null): Buffer { + if (anchor == null) { + return Buffer.concat([serializeOptionFlag(false)]) + } else { + return Buffer.concat([ + serializeOptionFlag(true), + hex_to_buf(anchor.hashHex), + Buffer.from(anchor.url, 'ascii'), + ]) } - - const value = included ? SignTxIncluded.YES : SignTxIncluded.NO - - return uint8_to_buf(value) } diff --git a/test/integration/__fixtures__/signTx.ts b/test/integration/__fixtures__/signTx.ts index 6bd41bf9..3989616d 100644 --- a/test/integration/__fixtures__/signTx.ts +++ b/test/integration/__fixtures__/signTx.ts @@ -4,8 +4,11 @@ import { BIP32Path, SignedTransactionData, TxRequiredSignerType, - StakeCredentialParamsType, + CredentialParamsType, TransactionSigningMode, + DRepParamsType, + VoterType, + VoteOption, } from '../../../src/types/public' import {str_to_path} from '../../../src/utils/address' import { @@ -301,7 +304,7 @@ export const testsShelleyNoCertificates: SignTxTestCase[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, amount: 111, @@ -364,7 +367,8 @@ export const testsShelleyNoCertificates: SignTxTestCase[] = [ export const testsShelleyWithCertificates: SignTxTestCase[] = [ { - testName: 'Sign tx with a stake registration path certificate', + testName: + 'Sign tx with a stake registration path certificate --- pre-Conway', tx: { ...shelleyBase, certificates: [ @@ -372,7 +376,7 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ type: CertificateType.STAKE_REGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, }, @@ -397,19 +401,18 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ }, }, { - testName: 'Sign tx with a stake delegation path certificate', + testName: + 'Sign tx with a stake deregistration path certificate --- pre-Conway', tx: { ...shelleyBase, certificates: [ { - type: CertificateType.STAKE_DELEGATION, + type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, - poolKeyHashHex: - 'f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', }, }, ], @@ -417,37 +420,39 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, additionalWitnessPaths: [], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048183028200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c581cf61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048182018200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c', expectedResult: { txHashHex: - '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c808b3a8aa', + '8b143fae3b37748fee1decdc10fbfa554158b58fbc99623ecdd2ba7aa709e471', witnesses: [ { path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - 'd94c8f8fe73946c25f3bd0919d05a60b8373ef0a7261fa73eefe1f2a20e8a4c3401feb5eea701222184fceab2c45b47bd823ac76123e2d17f804d3e4ed2df909', + '6136510eb91449474f6137c8d1c7c69eb518e3844a3e63a626be8cf4af91afa24e12f4fa578398bf0e7992e22dcfc5f9773fb8546b88c19e3abfdaa3bbe7a304', }, { path: str_to_path("1852'/1815'/0'/2/0"), witnessSignatureHex: - '035b4e6ae6f7a8089f2a302ddcb60bc56d48bcf267fdcb071844da5ce3086d51e816777a6fb5eabfcb326a32b830674ac0de40ee1b2360a69adba4b64c662404', + '77210ce6533a76db3673af1076bf3933747a8d81cabda80c8bc9c852c78685f8a42c9372721bdfe9b47611039364afb3391031211b5c427cfec0c5c505cfec0c', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with a stake deregistration path certificate', + testName: 'Sign tx with a stake delegation path certificate', tx: { ...shelleyBase, certificates: [ { - type: CertificateType.STAKE_DEREGISTRATION, + type: CertificateType.STAKE_DELEGATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, + poolKeyHashHex: + 'f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', }, }, ], @@ -455,20 +460,20 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, additionalWitnessPaths: [], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048182018200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048183028200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c581cf61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', expectedResult: { txHashHex: - '8b143fae3b37748fee1decdc10fbfa554158b58fbc99623ecdd2ba7aa709e471', + '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c808b3a8aa', witnesses: [ { path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '6136510eb91449474f6137c8d1c7c69eb518e3844a3e63a626be8cf4af91afa24e12f4fa578398bf0e7992e22dcfc5f9773fb8546b88c19e3abfdaa3bbe7a304', + 'd94c8f8fe73946c25f3bd0919d05a60b8373ef0a7261fa73eefe1f2a20e8a4c3401feb5eea701222184fceab2c45b47bd823ac76123e2d17f804d3e4ed2df909', }, { path: str_to_path("1852'/1815'/0'/2/0"), witnessSignatureHex: - '77210ce6533a76db3673af1076bf3933747a8d81cabda80c8bc9c852c78685f8a42c9372721bdfe9b47611039364afb3391031211b5c427cfec0c5c505cfec0c', + '035b4e6ae6f7a8089f2a302ddcb60bc56d48bcf267fdcb071844da5ce3086d51e816777a6fb5eabfcb326a32b830674ac0de40ee1b2360a69adba4b64c662404', }, ], auxiliaryDataSupplement: null, @@ -483,7 +488,7 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, }, @@ -492,7 +497,7 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, }, @@ -546,7 +551,7 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ type: CertificateType.STAKE_REGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, }, @@ -601,7 +606,7 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, }, @@ -638,481 +643,924 @@ export const testsShelleyWithCertificates: SignTxTestCase[] = [ }, ] -export const testsMultisig: SignTxTestCase[] = [ +export const testsConwayWithCertificates: SignTxTestCase[] = [ { - testName: 'Sign tx without change address with Shelley scripthash output', + testName: 'Sign tx with a stake registration path certificate --- Conway', tx: { - ...testnetFeeTtl, - inputs: [inputs.utxoShelley], - outputs: [outputs.externalShelleyBaseScripthashKeyhash], + ...shelleyBase, + certificates: [ + { + type: CertificateType.STAKE_REGISTRATION_CONWAY, + params: { + stakeCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/2/0"), + }, + deposit: '17', + }, + }, + ], }, - signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, - additionalWitnessPaths: [str_to_path("1854'/1815'/0'/0/0")], + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], txBody: - 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839105e2f080eb93bad86d401545e0ce5f2221096d6477e11e6643922fa8d2ed495234dc0d667c1316ff84e572310e265edb31330448b36b7179e0102182a030a', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048183078200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c11', expectedResult: { txHashHex: - '1e994755bafebf435f91e34655ba6a66ee92de64529dc811dce7001d92b0a44a', + '26ab8ebe60e70fffd59eb186ed6903ccd5a27c2468da72c5033b596dd41d1745', witnesses: [ { - path: str_to_path("1854'/1815'/0'/0/0"), + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '9c06b237c35be528a3f550e469e38c32c29a58417d489d8d4f1276a2111b2f6feca9b84d658f5e51ee7921512fe935e11defc7a1ff6152f76ea590baca04f307', + '128c993b5873029f98df738191462c6e8903ec2a765f7ddcc3a5722b5555e4ef2cccc4464bbdfb606627fe48e97f2db94f68c9d71b4076c93db682bd357ffa0b', + }, + { + path: str_to_path("1852'/1815'/0'/2/0"), + witnessSignatureHex: + 'bf22ca4b78fa64692a8cfbc375611deb1d60043db880ff000aeba7e4970492daa4e814c79960977816a91f9dd179bec6f127d37b8955589674e385b9a757d507', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with script based withdrawal', + testName: 'Sign tx with a stake deregistration path certificate --- Conway', tx: { ...shelleyBase, - withdrawals: [ + certificates: [ { - stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, - scriptHashHex: - '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + type: CertificateType.STAKE_DEREGISTRATION_CONWAY, + params: { + stakeCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/2/0"), + }, + deposit: '17', }, - amount: 111, }, ], }, - signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, - additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a05a1581df1122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277186f', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048183088200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c11', expectedResult: { txHashHex: - '87de2c36e5a222f796b392a290717316d039dc42dc2150873e86ec9b0c870357', + '58dc7ddba14500538e5de842066bb3a1979687c6ae0c2472d8f1851b4f011e26', witnesses: [ { - path: str_to_path("1854'/1815'/0'/2/0"), + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '64f26fb866f0840f2ec299db16e6eff9d039ebacf673bdd8dba5110078344bf9647c4038588bfc826c73d7e0c03ea2ffb028de632d9462a129fd78f3a1bd7c0e', + 'b0a196ce81930fedb90551d395f7ba2ff8671f1528d1eec85e3d2398174a1bf6c9bc2afc6c14891cf11a24e16c4a6d39f73689f5947170d0f0d9a53418c76400', + }, + { + path: str_to_path("1852'/1815'/0'/2/0"), + witnessSignatureHex: + 'c9ee07d3ee9ed1be5576e1ed371393335a98270f2a316ebec6c702e519db1b68a8cfb67039355a46a3f9d96051c74ae4e13e41d1ad05c3a401a8365369ea8407', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with a stake registration script certificate', + testName: 'Sign tx with vote delegation certificates', tx: { ...shelleyBase, certificates: [ { - type: CertificateType.STAKE_REGISTRATION, + type: CertificateType.VOTE_DELEGATION, + params: { + stakeCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/2/0"), + }, + dRep: { + type: DRepParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/3/0"), + }, + }, + }, + { + type: CertificateType.VOTE_DELEGATION, + params: { + stakeCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/2/0"), + }, + dRep: { + type: DRepParamsType.KEY_HASH, + keyHashHex: + '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + }, + }, + { + type: CertificateType.VOTE_DELEGATION, params: { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/2/0"), + }, + dRep: { + type: DRepParamsType.SCRIPT_HASH, scriptHashHex: - '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + '1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + }, + }, + { + type: CertificateType.VOTE_DELEGATION, + params: { + stakeCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/2/0"), + }, + dRep: { + type: DRepParamsType.ABSTAIN, + }, + }, + }, + { + type: CertificateType.VOTE_DELEGATION, + params: { + stakeCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/2/0"), + }, + dRep: { + type: DRepParamsType.NO_CONFIDENCE, }, }, }, ], }, - signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, - additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048182008201581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048583098200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c8200581cba41c59ac6e1a0e4ac304af98db801097d0bf8d2a5b28a54752426a183098200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c8200581c7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c883098200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c8201581c1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c883098200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c810283098200581c1d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c8103', expectedResult: { txHashHex: - 'fba0908b41300d1b075ec6a7dafc2dcbe3376df17ef3feb2e4536b309f0034d1', + 'b65bfdff7d247058d60b55958111c5b45322fdb3806be0e86a09382bafce3457', witnesses: [ { - path: str_to_path("1854'/1815'/0'/2/0"), + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - 'bfb96452a106da86ff17c71692e25fac4826ae1c318c94d671fd7602229b411cf4422614cba241954a9bdb66bfd364bc9cfdf446639ff6e03273dc4073d66b0a', + '1a9dd087bce2b189a1d2a3ff6e57017bf6cef86d51ca944a8faf9c04cddafd4336e4bdebc29450c82b766f766b4a7982b5cee9731edb85f9025c7826880de106', + }, + { + path: str_to_path("1852'/1815'/0'/2/0"), + witnessSignatureHex: + '8100907b358d25330003ea0f9606c031256f2ca060322138e3e118676cdea4e949b1a2217e714f6c5686a31fe70e80bcb2d460f8b7f12a7f5926c1211502c70f', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with a stake delegation script certificate', + testName: 'Sign tx with AUTHORIZE_COMMITTEE_HOT certificates', tx: { ...shelleyBase, certificates: [ { - type: CertificateType.STAKE_DELEGATION, + type: CertificateType.AUTHORIZE_COMMITTEE_HOT, params: { - stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + coldCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/4/0"), + }, + hotCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/5/0"), + }, + }, + }, + { + type: CertificateType.AUTHORIZE_COMMITTEE_HOT, + params: { + coldCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/4/0"), + }, + hotCredential: { + type: CredentialParamsType.KEY_HASH, + keyHashHex: + '1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + }, + }, + { + type: CertificateType.AUTHORIZE_COMMITTEE_HOT, + params: { + coldCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/4/0"), + }, + hotCredential: { + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: - '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + '1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', }, - poolKeyHashHex: - 'f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', }, }, ], }, - signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, - additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048183028201581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277581cf61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a0483830e8200581ccf737588be6e9edeb737eb2e6d06e5cbd292bd8ee32e410c0bba1ba68200581cd098c6a0a621f3343abe55877ee88fd5a83363e3c7887b3c48839092830e8200581ccf737588be6e9edeb737eb2e6d06e5cbd292bd8ee32e410c0bba1ba68200581c1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8830e8200581ccf737588be6e9edeb737eb2e6d06e5cbd292bd8ee32e410c0bba1ba68201581c1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', expectedResult: { txHashHex: - '927d8924e77c879bcc2a1e5317d963028737d0764c6532a05474d8eda203911d', + 'f39823031913a09286755ec2383da73a7248e36f6fc92685928296ec81e43b76', witnesses: [ { - path: str_to_path("1854'/1815'/0'/2/0"), + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '78de23f120ff291913eee3d3981281d500e9476debb27bb640ff73eba53c1de452b5d9dba57d4353a37652f7a72a272e60a928fbf4181b70c031c9ba93888606', + '73e3c0105404e90f6cccebbd9a1e9bb119c4f0a3d5e489a52d15caa477db35802fefe83dbec748b2c388b9dc193821eac068f519edb89ed2c550bc28e51a7203', + }, + { + path: str_to_path("1852'/1815'/0'/4/0"), + witnessSignatureHex: + 'b8075d9666648e02f3e2ab6355fd786b3864cfc18a0070beb60813745a36c68e03b9face68231efc0d13da11069f2b3c7ca9a2c7fbf2119970071607e5c18d01', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with a stake deregistration script certificate', + testName: 'Sign tx with RESIGN_COMMITTEE_COLD certificates', tx: { ...shelleyBase, certificates: [ { - type: CertificateType.STAKE_DEREGISTRATION, + type: CertificateType.RESIGN_COMMITTEE_COLD, params: { - stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, - scriptHashHex: - '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + coldCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/4/0"), + }, + anchor: { + url: 'www.vacuumlabs.com', + hashHex: + '1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + }, + }, + }, + { + type: CertificateType.RESIGN_COMMITTEE_COLD, + params: { + coldCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/4/0"), }, }, }, ], }, - signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, - additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048182018201581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a0482830f8200581ccf737588be6e9edeb737eb2e6d06e5cbd292bd8ee32e410c0bba1ba682727777772e76616375756d6c6162732e636f6d58201afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef830f8200581ccf737588be6e9edeb737eb2e6d06e5cbd292bd8ee32e410c0bba1ba6f6', expectedResult: { txHashHex: - 'c4c8910810de8dc39aa0c33b65ee24f3f95216c7050f9ba85c00302a99f6d596', + '1817433dfe1082c43c67375977e08b6cf7654161b9f8227bdae79f962cd5d391', witnesses: [ { - path: str_to_path("1854'/1815'/0'/2/0"), + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '468e5dc048efa4985bb392248f6d8df3b4ed297a9cbe4b9670ac0cc0debc4e6dc00018a75079cf20c050f4bf9be1c9aecccae851d22fe940a72b25af802d910b', + '84ee1d069b3b851330a2c1bd4c2423500551400c53182a36792f1559148409bdda2ccaf0bdfc9a7885042092b9e316b12d21e3912cc47579f190df8a80b28c04', + }, + { + path: str_to_path("1852'/1815'/0'/4/0"), + witnessSignatureHex: + '6d2a387455c55590c3ea9f5432dbb55ecdded67db163d53ba5ac3ad4ad30a4a715990866440ba164ba790bf24c86192d4d68c86382a299cd5de56f8293fe540a', }, ], auxiliaryDataSupplement: null, }, }, -] - -export const testsAllegra: SignTxTestCase[] = [ { - testName: 'Sign tx with no ttl and no validity interval start', + testName: 'Sign tx with DREP_REGISTRATION certificates', tx: { - network: Networks.Mainnet, - inputs: [inputs.utxoShelley], - outputs: [outputs.externalShelleyBaseKeyhashKeyhash], - fee: 42, - ttl: null, - validityIntervalStart: null, + ...shelleyBase, + certificates: [ + { + type: CertificateType.DREP_REGISTRATION, + params: { + dRepCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/3/0"), + }, + deposit: '19', + anchor: { + url: 'www.vacuumlabs.com', + hashHex: + '1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + }, + }, + }, + { + type: CertificateType.DREP_REGISTRATION, + params: { + dRepCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/3/0"), + }, + deposit: '19', + anchor: null, + }, + }, + ], }, signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], txBody: - 'a300818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b090102182a', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048283108200581cba41c59ac6e1a0e4ac304af98db801097d0bf8d2a5b28a54752426a11382727777772e76616375756d6c6162732e636f6d58201afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef83108200581cba41c59ac6e1a0e4ac304af98db801097d0bf8d2a5b28a54752426a113f6', expectedResult: { txHashHex: - 'cbb6ee600297d0b5067b1e79cf1dc6361de4e5e731eacc57c42765944381ff18', + '8281bf86f63572b541b5ea27cc23285769d4b7cb6c881851cc5c4d5ab830d5d1', witnesses: [ { path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '4f6e3a61b48921fa0c3f67856fc955e754d16d210f0725ff31d959c53f830ddef354663040bc0bc4306127c3549f0c5339cc5a604512090a4fe26ebadc80550f', + '537adfd66b77ed7dbdc3a57e7577868809f583cbd086ef1905114f83fe4e8e7456bad4dfdfcf36f2e45f4760d4144d85235e8e7410d6b9e9e4337c692bc8790d', + }, + { + path: str_to_path("1852'/1815'/0'/3/0"), + witnessSignatureHex: + 'a7f2eda7c8890bc56258f5d0da6eeb74cb35f7511ef97400328d2ec3e970c029d73fe212c1226862390d4eccb865e7c793d728da017757c60652eca060d7e00c', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with no ttl, but with validity interval start', + testName: 'Sign tx with DREP_DEREGISTRATION certificate', tx: { - network: Networks.Mainnet, - inputs: [inputs.utxoShelley], - outputs: [outputs.externalShelleyBaseKeyhashKeyhash], - fee: 42, - ttl: null, - validityIntervalStart: 47, + ...shelleyBase, + certificates: [ + { + type: CertificateType.DREP_DEREGISTRATION, + params: { + dRepCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/3/0"), + }, + deposit: '19', + }, + }, + ], }, signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], txBody: - 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b090102182a08182f', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048183118200581cba41c59ac6e1a0e4ac304af98db801097d0bf8d2a5b28a54752426a113', expectedResult: { txHashHex: - '9fbc15167cfdf408998b0348ff6e69e63f404d1f0acf65763a057003f8a3a93b', + 'ddac3d3a8a4554f7dd1797a7bfdd4ec19ddf13d20f3b9ea79ed37d5663b51497', witnesses: [ { path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - 'e245b89938ad182361d696dafb0644b6b93bcfa3e631716afb5f73b6b6d6852c9313d7fd34a4a404e4b345b64d9b29ddef406197911106593000cd2fd18b900f', + '903e42d8f48c60d4bacc8aa953bff66c79ef8b48c2eece243f03d32146f9d213e6595809bc6c13e2ebb13f990ad0ef7bb937eab6a9d251c35aae7bafc2c51702', + }, + { + path: str_to_path("1852'/1815'/0'/3/0"), + witnessSignatureHex: + '56786aa0710832c8ef584ebe964473cd21eb15b4b60057a5d96973f6a4687176d1f7cbecde585f7b875fc75ad73a9404733219d61ee542363ef4baa8a1bb1504', }, ], auxiliaryDataSupplement: null, }, }, -] - -export const testsMary: SignTxTestCase[] = [ { - testName: 'Sign tx with a multiasset output', + testName: 'Sign tx with DREP_UPDATE certificates', tx: { - ...mainnetFeeTtl, - inputs: [inputs.utxoShelley], - outputs: [ - outputs.multiassetOneToken, - outputs.internalBaseWithStakingPath, - ], - validityIntervalStart: 7, - }, - signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, - txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1a007838628258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca79302182a030a0807', - expectedResult: { - txHashHex: - '9a9bce0cfe146a1327a94a6257e1013b12476d9c73c891d73faf74aaf131cde5', - witnesses: [ + ...shelleyBase, + certificates: [ + { + type: CertificateType.DREP_UPDATE, + params: { + dRepCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/3/0"), + }, + anchor: { + url: 'www.vacuumlabs.com', + hashHex: + '1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + }, + }, + }, + { + type: CertificateType.DREP_UPDATE, + params: { + dRepCredential: { + type: CredentialParamsType.KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/3/0"), + }, + }, + }, + ], + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048283128200581cba41c59ac6e1a0e4ac304af98db801097d0bf8d2a5b28a54752426a182727777772e76616375756d6c6162732e636f6d58201afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef83128200581cba41c59ac6e1a0e4ac304af98db801097d0bf8d2a5b28a54752426a1f6', + expectedResult: { + txHashHex: + '85b23eda26bd9f6f9f4ce80f7d1e9c0cf3afcb33a39c0102711a81a96715d2e6', + witnesses: [ { path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '6c4d490ea8f3973f9d030c36ff7221f012663af276bde346f8b90b54b06f49c22bcde3968cc281d548183e1506380028853948f7ef3c98a9e179540119688106', + 'e65f9e0d99db02f1a39b8af92b9f7e8f6509b24cbd6f4492e19d699f5f7e08d627a64def7408405ff0aadd7504bacfa279a2f1ba550a765f43d06fcac16f1009', + }, + { + path: str_to_path("1852'/1815'/0'/3/0"), + witnessSignatureHex: + '88b20b4bc43f6d45981c658689e6d80886b6aeb02b654363c421462f855654039d5ff3595be6778934b4eff2a24c3a082789f95559bd6e8afa2e8bab339e910d', }, ], auxiliaryDataSupplement: null, }, }, +] + +export const testsMultisig: SignTxTestCase[] = [ { - testName: 'Sign tx with a complex multiasset output', + testName: 'Sign tx without change address with Shelley scripthash output', tx: { - ...mainnetFeeTtl, + ...testnetFeeTtl, inputs: [inputs.utxoShelley], - outputs: [ - outputs.multiassetManyTokens, - outputs.internalBaseWithStakingPath, - ], - validityIntervalStart: 7, + outputs: [outputs.externalShelleyBaseScripthashKeyhash], }, - signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, + additionalWitnessPaths: [str_to_path("1854'/1815'/0'/0/0")], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a2581c7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373a34003581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209015820000000000000000000000000000000000000000000000000000000000000000002581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a248456c204e69c3b16f1904d24874652474436f696e1a007838628258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca79302182a030a0807', + 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839105e2f080eb93bad86d401545e0ce5f2221096d6477e11e6643922fa8d2ed495234dc0d667c1316ff84e572310e265edb31330448b36b7179e0102182a030a', expectedResult: { txHashHex: - 'b81c3a6f8506eeacb0512a54f12500151745fbb683f52dbc52f6c099437baca8', + '1e994755bafebf435f91e34655ba6a66ee92de64529dc811dce7001d92b0a44a', witnesses: [ { - path: str_to_path("1852'/1815'/0'/0/0"), + path: str_to_path("1854'/1815'/0'/0/0"), witnessSignatureHex: - 'e2c96040194d1baef4b9dfac945496f60d446597863a2049d12796df7fb6f9f9f31392555cfccfd7c745eef802d1904ba3a9ba4892569d0eed6f6e19a871630f', + '9c06b237c35be528a3f550e469e38c32c29a58417d489d8d4f1276a2111b2f6feca9b84d658f5e51ee7921512fe935e11defc7a1ff6152f76ea590baca04f307', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with big numbers', + testName: 'Sign tx with script based withdrawal', tx: { - ...mainnetFeeTtl, - inputs: [inputs.utxoShelley], - outputs: [outputs.multiassetBigNumber], - fee: '24103998870869519', - ttl: '24103998870869519', - validityIntervalStart: '24103998870869519', + ...shelleyBase, + withdrawals: [ + { + stakeCredential: { + type: CredentialParamsType.SCRIPT_HASH, + scriptHashHex: + '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + }, + amount: 111, + }, + ], }, - signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, + additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821b0055a275925d560fa1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1b0055a275925d560f021b0055a275925d560f031b0055a275925d560f081b0055a275925d560f', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a05a1581df1122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277186f', expectedResult: { txHashHex: - 'e60735a3cc71a8a3f89652797c3e650d6ed80059c0b59978c59858dcf6f8ca48', + '87de2c36e5a222f796b392a290717316d039dc42dc2150873e86ec9b0c870357', witnesses: [ { - path: str_to_path("1852'/1815'/0'/0/0"), + path: str_to_path("1854'/1815'/0'/2/0"), witnessSignatureHex: - '632cd935550a71c1e1869e6f5749ee4cb8c268cbe014138561fc2d1045b5b2be84526cfd5a6fea01de99bdf903fa17c79a58a832b5cdcb1c999bcbe995a56806', + '64f26fb866f0840f2ec299db16e6eff9d039ebacf673bdd8dba5110078344bf9647c4038588bfc826c73d7e0c03ea2ffb028de632d9462a129fd78f3a1bd7c0e', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with a multiasset change output', + testName: 'Sign tx with a stake registration script certificate', tx: { - ...mainnetFeeTtl, - inputs: [inputs.utxoShelley], - outputs: [ - outputs.externalShelleyBaseKeyhashKeyhash, - outputs.multiassetChange, + ...shelleyBase, + certificates: [ + { + type: CertificateType.STAKE_REGISTRATION, + params: { + stakeCredential: { + type: CredentialParamsType.SCRIPT_HASH, + scriptHashHex: + '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + }, + }, + }, ], }, - signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, + additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], txBody: - 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000182825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b09018258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1a0078386202182a030a', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048182008201581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', expectedResult: { txHashHex: - '005b324472b13e181f72a9c5eb1f05351a22b103ce35517768bab1d3bfe4a114', + 'fba0908b41300d1b075ec6a7dafc2dcbe3376df17ef3feb2e4536b309f0034d1', witnesses: [ { - path: str_to_path("1852'/1815'/0'/0/0"), + path: str_to_path("1854'/1815'/0'/2/0"), witnessSignatureHex: - '7d437d698a9a8f06f1e0ced7378c22b864b4a3dd8bba575e5cc497f55fcee984724549a34cb6e5ea11acf4749544ddabf2118c0545c668c5f75251a6be443905', + 'bfb96452a106da86ff17c71692e25fac4826ae1c318c94d671fd7602229b411cf4422614cba241954a9bdb66bfd364bc9cfdf446639ff6e03273dc4073d66b0a', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with zero fee, TTL and validity interval start', + testName: 'Sign tx with a stake delegation script certificate', tx: { - network: Networks.Mainnet, - fee: 0, - ttl: 0, - validityIntervalStart: 0, - inputs: [inputs.utxoShelley], - outputs: [outputs.internalBaseWithStakingPath], + ...shelleyBase, + certificates: [ + { + type: CertificateType.STAKE_DELEGATION, + params: { + stakeCredential: { + type: CredentialParamsType.SCRIPT_HASH, + scriptHashHex: + '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + }, + poolKeyHashHex: + 'f61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', + }, + }, + ], }, - signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, + additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b70001818258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca793020003000800', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048183028201581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277581cf61c42cbf7c8c53af3f520508212ad3e72f674f957fe23ff0acb4973', expectedResult: { txHashHex: - 'acc997f583c78f36529ee29134e2cfb7a4550493727f565a502ab40544827311', + '927d8924e77c879bcc2a1e5317d963028737d0764c6532a05474d8eda203911d', witnesses: [ { - path: str_to_path("1852'/1815'/0'/0/0"), + path: str_to_path("1854'/1815'/0'/2/0"), witnessSignatureHex: - 'e5ee59942fba139b5547e5e1dae1389ed9edd6e7bd7f057b988973c2451b5e3e41901c1d9a0fa74d34dae356a064ee783205d731fee01105c904702826b66b04', + '78de23f120ff291913eee3d3981281d500e9476debb27bb640ff73eba53c1de452b5d9dba57d4353a37652f7a72a272e60a928fbf4181b70c031c9ba93888606', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with output with decimal places', + testName: 'Sign tx with a stake deregistration script certificate', tx: { - network: Networks.Mainnet, - inputs: [inputs.utxoShelley], - outputs: [outputs.multiassetDecimalPlaces], - fee: 33, + ...shelleyBase, + certificates: [ + { + type: CertificateType.STAKE_DEREGISTRATION, + params: { + stakeCredential: { + type: CredentialParamsType.SCRIPT_HASH, + scriptHashHex: + '122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', + }, + }, + }, + ], }, - signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + signingMode: TransactionSigningMode.MULTISIG_TRANSACTION, + additionalWitnessPaths: [str_to_path("1854'/1815'/0'/2/0")], txBody: - 'a300818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a2581c6954264b15bc92d6d592febeac84f14645e1ed46ca5ebb9acdb5c15fa14553545249501a0034bf15581caf2e27f580f7f08e93190a81f72462f153026d06450924726645891ba244445249501904d24cffffffffffffffffffffffff1904d2021821', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a048182018201581c122a946b9ad3d2ddf029d3a828f0468aece76895f15c9efbd69b4277', expectedResult: { txHashHex: - 'a36c270c8ee52c8f5b9cc47ccad0869ad72f00dd1ac1510b682752e09738a27f', + 'c4c8910810de8dc39aa0c33b65ee24f3f95216c7050f9ba85c00302a99f6d596', witnesses: [ { - path: [2147485500, 2147485463, 2147483648, 0, 0], + path: str_to_path("1854'/1815'/0'/2/0"), witnessSignatureHex: - '30e8da0b9230bc1b1e2748ef51e9259f457d4e0bd0387eb186ade839f3bbac5a2face7eea72061b850c7d26a5b66bd0f90cff546c6c30e0987091a067c960d06', + '468e5dc048efa4985bb392248f6d8df3b4ed297a9cbe4b9670ac0cc0debc4e6dc00018a75079cf20c050f4bf9be1c9aecccae851d22fe940a72b25af802d910b', }, ], auxiliaryDataSupplement: null, }, }, +] + +export const testsAllegra: SignTxTestCase[] = [ { - testName: 'Sign tx with mint fields with various amounts', + testName: 'Sign tx with no ttl and no validity interval start', tx: { - ...mainnetFeeTtl, + network: Networks.Mainnet, inputs: [inputs.utxoShelley], - outputs: [], - mint: mints.mintAmountVariety, + outputs: [outputs.externalShelleyBaseKeyhashKeyhash], + fee: 42, + ttl: null, + validityIntervalStart: null, }, signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, txBody: - 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018002182a030a09a1581c7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373a44000581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20920581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20a1b7fffffffffffffff581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20b3b7fffffffffffffff', + 'a300818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b090102182a', expectedResult: { txHashHex: - 'd31008087e3a9a267661f802993f7604ac2dd53d4b458f27bfc3663bc7072de1', + 'cbb6ee600297d0b5067b1e79cf1dc6361de4e5e731eacc57c42765944381ff18', witnesses: [ { - path: [2147485500, 2147485463, 2147483648, 0, 0], + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '18fa055fb6d74b12170cdc227aaf4922c78405d4caf7bdbe5f959df2c3a912e20c5a18c4412d504685fe1179d32b5b588efe4a8d59f0274492de77f30f315409', + '4f6e3a61b48921fa0c3f67856fc955e754d16d210f0725ff31d959c53f830ddef354663040bc0bc4306127c3549f0c5339cc5a604512090a4fe26ebadc80550f', }, ], auxiliaryDataSupplement: null, }, }, { - testName: 'Sign tx with mint with decimal places', + testName: 'Sign tx with no ttl, but with validity interval start', tx: { network: Networks.Mainnet, inputs: [inputs.utxoShelley], outputs: [outputs.externalShelleyBaseKeyhashKeyhash], - fee: 33, - mint: mints.mintWithDecimalPlaces, + fee: 42, + ttl: null, + validityIntervalStart: 47, }, signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, txBody: - 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b090102182109a2581c6954264b15bc92d6d592febeac84f14645e1ed46ca5ebb9acdb5c15fa14553545249503a0034bf14581caf2e27f580f7f08e93190a81f72462f153026d06450924726645891ba244445249501904d24cffffffffffffffffffffffff1904d2', + 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b090102182a08182f', expectedResult: { txHashHex: - 'a96b68158758496044fbf91d7abaaa59e1cc426315c4fc2a1c4fa2c5db432807', + '9fbc15167cfdf408998b0348ff6e69e63f404d1f0acf65763a057003f8a3a93b', witnesses: [ { - path: [2147485500, 2147485463, 2147483648, 0, 0], + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '11b9ed90e2923c01869627ed5bc49ea66874fbef2418a2184437e19a30738a8bb52d7569113984617d73144e304be5cf84a30c21bd8b1c4cfe93cc434ed3db04', + 'e245b89938ad182361d696dafb0644b6b93bcfa3e631716afb5f73b6b6d6852c9313d7fd34a4a404e4b345b64d9b29ddef406197911106593000cd2fd18b900f', }, ], auxiliaryDataSupplement: null, }, }, +] + +export const testsMary: SignTxTestCase[] = [ { - testName: 'Sign tx with mint fields among other fields', + testName: 'Sign tx with a multiasset output', tx: { - network: Networks.Mainnet, + ...mainnetFeeTtl, inputs: [inputs.utxoShelley], outputs: [ outputs.multiassetOneToken, outputs.internalBaseWithStakingPath, ], - fee: 10, - validityIntervalStart: 100, - ttl: 1000, - mint: mints.mintAmountVariety, + validityIntervalStart: 7, }, signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, txBody: - 'a600818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1a007838628258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca793020a031903e808186409a1581c7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373a44000581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20920581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20a1b7fffffffffffffff581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20b3b7fffffffffffffff', + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1a007838628258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca79302182a030a0807', expectedResult: { txHashHex: - '49686d9089cba67506537574dd0514038f813a2b9e648097aa49c2b93d14d549', + '9a9bce0cfe146a1327a94a6257e1013b12476d9c73c891d73faf74aaf131cde5', witnesses: [ { - path: [2147485500, 2147485463, 2147483648, 0, 0], + path: str_to_path("1852'/1815'/0'/0/0"), witnessSignatureHex: - '2a4ec4e5eb03d24264d612923e62b01384d215a70c415b067cc109580cef1044fc9a5b17fe92f752b70702fd457e6ea455a4ef5f3afdd44548223e913bc43b08', + '6c4d490ea8f3973f9d030c36ff7221f012663af276bde346f8b90b54b06f49c22bcde3968cc281d548183e1506380028853948f7ef3c98a9e179540119688106', }, ], auxiliaryDataSupplement: null, }, }, -] - -export const testsAlonzoTrezorComparison: SignTxTestCase[] = [ { - testName: 'Full test for trezor feature parity', + testName: 'Sign tx with a complex multiasset output', tx: { - // "protocol_magic": 764824073, - // "network_id": 1, - // if Networks.Mainnet differs, the test should just explicitly give these - network: Networks.Mainnet, - inputs: [inputs.utxoMultisig], - outputs: [outputs.trezorParity1, outputs.trezorParityDatumHash1], - fee: 42, - ttl: 10, - validityIntervalStart: 47, - certificates: [ + ...mainnetFeeTtl, + inputs: [inputs.utxoShelley], + outputs: [ + outputs.multiassetManyTokens, + outputs.internalBaseWithStakingPath, + ], + validityIntervalStart: 7, + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a2581c7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373a34003581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df209015820000000000000000000000000000000000000000000000000000000000000000002581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a248456c204e69c3b16f1904d24874652474436f696e1a007838628258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca79302182a030a0807', + expectedResult: { + txHashHex: + 'b81c3a6f8506eeacb0512a54f12500151745fbb683f52dbc52f6c099437baca8', + witnesses: [ { - type: CertificateType.STAKE_REGISTRATION, + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + 'e2c96040194d1baef4b9dfac945496f60d446597863a2049d12796df7fb6f9f9f31392555cfccfd7c745eef802d1904ba3a9ba4892569d0eed6f6e19a871630f', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with big numbers', + tx: { + ...mainnetFeeTtl, + inputs: [inputs.utxoShelley], + outputs: [outputs.multiassetBigNumber], + fee: '24103998870869519', + ttl: '24103998870869519', + validityIntervalStart: '24103998870869519', + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821b0055a275925d560fa1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1b0055a275925d560f021b0055a275925d560f031b0055a275925d560f081b0055a275925d560f', + expectedResult: { + txHashHex: + 'e60735a3cc71a8a3f89652797c3e650d6ed80059c0b59978c59858dcf6f8ca48', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '632cd935550a71c1e1869e6f5749ee4cb8c268cbe014138561fc2d1045b5b2be84526cfd5a6fea01de99bdf903fa17c79a58a832b5cdcb1c999bcbe995a56806', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with a multiasset change output', + tx: { + ...mainnetFeeTtl, + inputs: [inputs.utxoShelley], + outputs: [ + outputs.externalShelleyBaseKeyhashKeyhash, + outputs.multiassetChange, + ], + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000182825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b09018258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1a0078386202182a030a', + expectedResult: { + txHashHex: + '005b324472b13e181f72a9c5eb1f05351a22b103ce35517768bab1d3bfe4a114', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '7d437d698a9a8f06f1e0ced7378c22b864b4a3dd8bba575e5cc497f55fcee984724549a34cb6e5ea11acf4749544ddabf2118c0545c668c5f75251a6be443905', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with zero fee, TTL and validity interval start', + tx: { + network: Networks.Mainnet, + fee: 0, + ttl: 0, + validityIntervalStart: 0, + inputs: [inputs.utxoShelley], + outputs: [outputs.internalBaseWithStakingPath], + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b70001818258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca793020003000800', + expectedResult: { + txHashHex: + 'acc997f583c78f36529ee29134e2cfb7a4550493727f565a502ab40544827311', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + 'e5ee59942fba139b5547e5e1dae1389ed9edd6e7bd7f057b988973c2451b5e3e41901c1d9a0fa74d34dae356a064ee783205d731fee01105c904702826b66b04', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with output with decimal places', + tx: { + network: Networks.Mainnet, + inputs: [inputs.utxoShelley], + outputs: [outputs.multiassetDecimalPlaces], + fee: 33, + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a300818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a2581c6954264b15bc92d6d592febeac84f14645e1ed46ca5ebb9acdb5c15fa14553545249501a0034bf15581caf2e27f580f7f08e93190a81f72462f153026d06450924726645891ba244445249501904d24cffffffffffffffffffffffff1904d2021821', + expectedResult: { + txHashHex: + 'a36c270c8ee52c8f5b9cc47ccad0869ad72f00dd1ac1510b682752e09738a27f', + witnesses: [ + { + path: [2147485500, 2147485463, 2147483648, 0, 0], + witnessSignatureHex: + '30e8da0b9230bc1b1e2748ef51e9259f457d4e0bd0387eb186ade839f3bbac5a2face7eea72061b850c7d26a5b66bd0f90cff546c6c30e0987091a067c960d06', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with mint fields with various amounts', + tx: { + ...mainnetFeeTtl, + inputs: [inputs.utxoShelley], + outputs: [], + mint: mints.mintAmountVariety, + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018002182a030a09a1581c7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373a44000581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20920581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20a1b7fffffffffffffff581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20b3b7fffffffffffffff', + expectedResult: { + txHashHex: + 'd31008087e3a9a267661f802993f7604ac2dd53d4b458f27bfc3663bc7072de1', + witnesses: [ + { + path: [2147485500, 2147485463, 2147483648, 0, 0], + witnessSignatureHex: + '18fa055fb6d74b12170cdc227aaf4922c78405d4caf7bdbe5f959df2c3a912e20c5a18c4412d504685fe1179d32b5b588efe4a8d59f0274492de77f30f315409', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with mint with decimal places', + tx: { + network: Networks.Mainnet, + inputs: [inputs.utxoShelley], + outputs: [outputs.externalShelleyBaseKeyhashKeyhash], + fee: 33, + mint: mints.mintWithDecimalPlaces, + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a400818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7000181825839017cb05fce110fb999f01abb4f62bc455e217d4a51fde909fa9aea545443ac53c046cf6a42095e3c60310fa802771d0672f8fe2d1861138b090102182109a2581c6954264b15bc92d6d592febeac84f14645e1ed46ca5ebb9acdb5c15fa14553545249503a0034bf14581caf2e27f580f7f08e93190a81f72462f153026d06450924726645891ba244445249501904d24cffffffffffffffffffffffff1904d2', + expectedResult: { + txHashHex: + 'a96b68158758496044fbf91d7abaaa59e1cc426315c4fc2a1c4fa2c5db432807', + witnesses: [ + { + path: [2147485500, 2147485463, 2147483648, 0, 0], + witnessSignatureHex: + '11b9ed90e2923c01869627ed5bc49ea66874fbef2418a2184437e19a30738a8bb52d7569113984617d73144e304be5cf84a30c21bd8b1c4cfe93cc434ed3db04', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with mint fields among other fields', + tx: { + network: Networks.Mainnet, + inputs: [inputs.utxoShelley], + outputs: [ + outputs.multiassetOneToken, + outputs.internalBaseWithStakingPath, + ], + fee: 10, + validityIntervalStart: 100, + ttl: 1000, + mint: mints.mintAmountVariety, + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + txBody: + 'a600818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018282583901eb0baa5e570cffbe2934db29df0b6a3d7c0430ee65d4c3a7ab2fefb91bc428e4720702ebd5dab4fb175324c192dc9bb76cc5da956e3c8dff821904d2a1581c95a292ffee938be03e9bae5657982a74e9014eb4960108c9e23a5b39a14874652474436f696e1a007838628258390114c16d7f43243bd81478e68b9db53a8528fd4fb1078d58d54a7f11241d227aefa4b773149170885aadba30aab3127cc611ddbc4999def61c1a006ca793020a031903e808186409a1581c7eae28af2208be856f7a119668ae52a49b73725e326dc16579dcc373a44000581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20920581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20a1b7fffffffffffffff581c1e349c9bdea19fd6c147626a5260bc44b71635f398b67c59881df20b3b7fffffffffffffff', + expectedResult: { + txHashHex: + '49686d9089cba67506537574dd0514038f813a2b9e648097aa49c2b93d14d549', + witnesses: [ + { + path: [2147485500, 2147485463, 2147483648, 0, 0], + witnessSignatureHex: + '2a4ec4e5eb03d24264d612923e62b01384d215a70c415b067cc109580cef1044fc9a5b17fe92f752b70702fd457e6ea455a4ef5f3afdd44548223e913bc43b08', + }, + ], + auxiliaryDataSupplement: null, + }, + }, +] + +export const testsAlonzoTrezorComparison: SignTxTestCase[] = [ + { + testName: 'Full test for trezor feature parity', + tx: { + // "protocol_magic": 764824073, + // "network_id": 1, + // if Networks.Mainnet differs, the test should just explicitly give these + network: Networks.Mainnet, + inputs: [inputs.utxoMultisig], + outputs: [outputs.trezorParity1, outputs.trezorParityDatumHash1], + fee: 42, + ttl: 10, + validityIntervalStart: 47, + certificates: [ + { + type: CertificateType.STAKE_REGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -1122,7 +1570,7 @@ export const testsAlonzoTrezorComparison: SignTxTestCase[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -1132,7 +1580,7 @@ export const testsAlonzoTrezorComparison: SignTxTestCase[] = [ type: CertificateType.STAKE_DELEGATION, params: { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -1144,7 +1592,7 @@ export const testsAlonzoTrezorComparison: SignTxTestCase[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -1289,7 +1737,7 @@ export const testsMultidelegation: SignTxTestCase[] = [ type: CertificateType.STAKE_REGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/2"), }, }, @@ -1298,7 +1746,7 @@ export const testsMultidelegation: SignTxTestCase[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/2"), }, }, @@ -1307,7 +1755,7 @@ export const testsMultidelegation: SignTxTestCase[] = [ type: CertificateType.STAKE_DELEGATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/2"), }, poolKeyHashHex: @@ -1318,7 +1766,7 @@ export const testsMultidelegation: SignTxTestCase[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/3"), }, amount: 1000, @@ -1380,3 +1828,385 @@ export const testsMultidelegation: SignTxTestCase[] = [ }, }, ] + +export const testsConwayWithoutCertificates: SignTxTestCase[] = [ + { + testName: 'Sign tx with treasury', + tx: { + ...shelleyBase, + treasury: 27, + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a15181b', + expectedResult: { + txHashHex: + 'c3fb3f4330d9f051b567db11d56ab8174cba081373936c9fde80d809b178326f', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + 'd709944dbc56080b194455a76474981e56c64715b8e5182a58f9f5bba20357f2e02945431145e6fe418b1953424ef1b88e3328f373da1d24cb164d6eb8e0a80f', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with donation', + tx: { + ...shelleyBase, + donation: 28, + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a16181c', + expectedResult: { + txHashHex: + '618718225c0c876fd429ca25957a23ad894eaebc1831365c5b41cba50993a1bf', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + 'eef7538ecd01708a3483900155c3c1545188b671f626a4622864cbfe41a51bfd4c47ccb9ee8accd7891bd0291bce3e44c8363a30ffbe80864af1a29a74239c00', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with treasury and donation', + tx: { + ...shelleyBase, + treasury: 27, + donation: 28, + }, + signingMode: TransactionSigningMode.PLUTUS_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a600818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a15181b16181c', + expectedResult: { + txHashHex: + '37e2cf72599186d1ec571af568ea0ab39f7f73ba2e8c5f4725bfd0d4fb8c58e7', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '90627003619a5512c5600542bfe5ece07909433948a601d599f51bc0b3d19b5c8084cf72d2b6ae6962918392c540d60105c32626804986e99364e6966f5e1504', + }, + ], + auxiliaryDataSupplement: null, + }, + }, +] + +const vote1 = { + govActionId: { + txHashHex: + '3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7', + govActionIndex: 3, + }, + votingProcedure: { + vote: VoteOption.ABSTAIN, + anchor: { + url: 'www.vacuumlabs.com', + hashHex: + '1afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + }, + }, +} +const vote2 = { + govActionId: { + txHashHex: + '3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7', + govActionIndex: 3, + }, + votingProcedure: { + vote: VoteOption.NO, + anchor: null, + }, +} +const vote3 = { + govActionId: { + txHashHex: + '3b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7', + govActionIndex: 3, + }, + votingProcedure: { + vote: VoteOption.YES, + anchor: null, + }, +} + +export const testsConwayVotingProcedures: SignTxTestCase[] = [ + { + testName: 'Sign tx with voting procedures, COMMITTEE_KEY_PATH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.COMMITTEE_KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/5/0"), + }, + votes: [vote1], + }, + ], + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18200581cd098c6a0a621f3343abe55877ee88fd5a83363e3c7887b3c48839092a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b703820282727777772e76616375756d6c6162732e636f6d58201afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + expectedResult: { + txHashHex: + '1878027bc8ffa79d279f5c739a18817598382f1f181c0722954642e28a552417', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '740d2c38e72b017566ee04cce0329795df75b9c5b5ab40045faabaafba16e80894169467a62db6e6a7110e9c3591819e9ba023c40598309c1db401ea6b84d107', + }, + { + path: str_to_path("1852'/1815'/0'/5/0"), + witnessSignatureHex: + '87045d01fed7fe418601fd529ada773e40e48973760a10bff18702b76ad50d689cc17f350faba86aeea587441d3bc0856c3d650644cdf67e00ebdf4be9768f0c', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with voting procedures, DREP_KEY_PATH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.DREP_KEY_PATH, + keyPath: str_to_path("1852'/1815'/0'/3/0"), + }, + votes: [vote2], + }, + ], + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18202581cba41c59ac6e1a0e4ac304af98db801097d0bf8d2a5b28a54752426a1a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7038200f6', + expectedResult: { + txHashHex: + 'c76996d3e2bce5d61c19e5c6f4e69dbda650f14b706b95c440e4f4dbe56f584c', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '8ed6756e5913a5cf965fda822a61c0f1691e795709104194483915d383b3ed4dbeae8c1258fd4fa2a915e0a573c3a8fe5ee2bf1c56652e02f2729cdea7f43a03', + }, + { + path: str_to_path("1852'/1815'/0'/3/0"), + witnessSignatureHex: + '901cb9f18ada4c07fb7b132fc7859d6e1a3beb42934f58d4d44fb8fbeef066a349482d4c159ecd54b61b4cb34e4db1fc5c57cc3b6bb4a040cf61d6dd88f73901', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with voting procedures, STAKE_POOL_KEY_PATH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.STAKE_POOL_KEY_PATH, + keyPath: str_to_path("1853'/1815'/0'/0'"), + }, + votes: [vote3], + }, + ], + }, + signingMode: TransactionSigningMode.ORDINARY_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18204581cdbfee4665e58c8f8e9b9ff02b17f32e08a42c855476a5d867c2737b7a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7038201f6', + expectedResult: { + txHashHex: + 'a883078593d6e64486f54bb975230f47d43e4a92f3a6bdef60a522197610c947', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '8fcacfc066da36cab795cc820433fc4cef8cc0b8f3b62fb95a32da1056aea878411e8f6b891d1f77881f1b95903fb6c4fd4c3922b44de7dc790909a1d1dcb800', + }, + { + path: str_to_path("1853'/1815'/0'/0'"), + witnessSignatureHex: + '745e2b96ae05133dba57695aff7a37e35a2c21f3c53174f280df5661974626839ed7cf6362a75db50349c30e935e2993a8493ef2a600e96fc67542cede5bbf02', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with voting procedures, COMMITTEE_KEY_HASH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.COMMITTEE_KEY_HASH, + keyHashHex: + '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + votes: [vote1], + }, + ], + }, + signingMode: TransactionSigningMode.PLUTUS_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18200581c7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b703820282727777772e76616375756d6c6162732e636f6d58201afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + expectedResult: { + txHashHex: + 'e19f0cdcd735f6ea53f5673e593008af68a182f66c1027aa31fd8da449b7cf5b', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '6d4d4be3cae6d5cac5721fe29b6bbc445bfce24b6ebc6be663043e240a575a96238e0beea8391a080fb060e290b7661413c275ef3ba0458af86df30ed62f6202', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with voting procedures, COMMITTEE_SCRIPT_HASH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.COMMITTEE_SCRIPT_HASH, + scriptHashHex: + '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + votes: [vote2], + }, + ], + }, + signingMode: TransactionSigningMode.PLUTUS_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18201581c7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7038200f6', + expectedResult: { + txHashHex: + '05af307259f8f07f34c536ce037b1a443c7a1be8e62f644c37364d3210b744d8', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '803bd1793c4afdf303d9ae5e7ec2eef7344663f0cfc77a5f8327fb51c693d6a13f07066cb01ab12d575a1fc45f2747ff3a2302edd5048a74b6e205bed0384e00', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with voting procedures, DREP_KEY_HASH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.DREP_KEY_HASH, + keyHashHex: + '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + votes: [vote3], + }, + ], + }, + signingMode: TransactionSigningMode.PLUTUS_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18202581c7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b7038201f6', + expectedResult: { + txHashHex: + '4cc800d11a4464c352841e393543981bfeb35dfef04037519c0170dce87c5198', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '7d8002af012f8ec0b67b3679f80f9119794062827834ded271be2e014970dd4206d6a53936d557daa74996d85812d6f541bad9578a05927d0c0778d63463f409', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with voting procedures, DREP_SCRIPT_HASH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.DREP_SCRIPT_HASH, + scriptHashHex: + '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + votes: [vote1], + }, + ], + }, + signingMode: TransactionSigningMode.PLUTUS_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18203581c7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b703820282727777772e76616375756d6c6162732e636f6d58201afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + expectedResult: { + txHashHex: + '00881f4f414a32bd7e3e06036935b8a37944dc3d348216df6a1470fb4e2f04ae', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + 'efd40f0cb90f93b3c664a1a8aba72941c570c07351db43054a399be4b0020d052397c8fdc28f2ed949d29b0d2040d5c296f447c0e104ed6ae58c553405e8c202', + }, + ], + auxiliaryDataSupplement: null, + }, + }, + { + testName: 'Sign tx with voting procedures, STAKE_POOL_KEY_HASH voter', + tx: { + ...shelleyBase, + votingProcedures: [ + { + voter: { + type: VoterType.STAKE_POOL_KEY_HASH, + keyHashHex: + '7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8', + }, + votes: [vote1], + }, + ], + }, + signingMode: TransactionSigningMode.PLUTUS_TRANSACTION, + additionalWitnessPaths: [], + txBody: + 'a500818258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b700018182582b82d818582183581c9e1c71de652ec8b85fec296f0685ca3988781c94a2e1a5d89d92f45fa0001a0d0c25611a002dd2e802182a030a13a18204581c7afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8a18258203b40265111d8bb3c3c608d95b3a0bf83461ace32d79336579a1939b3aad1c0b703820282727777772e76616375756d6c6162732e636f6d58201afd028b504c3668102b129b37a86c09a2872f76741dc7a68e2149c8deadbeef', + expectedResult: { + txHashHex: + '623dd691a60d25e379424eceae1052acff119013c56bd2b73e8e1e822d3292bd', + witnesses: [ + { + path: str_to_path("1852'/1815'/0'/0/0"), + witnessSignatureHex: + '5e9b164e24e0752c1c9987df83aa4ff9a54455c799231c191e8b150ad7af83db36cd5f91941f65b853f883b6721e4b9f724788fffa2371aaf5644ca53ccc1308', + }, + ], + auxiliaryDataSupplement: null, + }, + }, +] diff --git a/test/integration/__fixtures__/signTxPlutus.ts b/test/integration/__fixtures__/signTxPlutus.ts index c42afa47..351832b9 100644 --- a/test/integration/__fixtures__/signTxPlutus.ts +++ b/test/integration/__fixtures__/signTxPlutus.ts @@ -1,6 +1,6 @@ import {CertificateType, Networks, TxRequiredSignerType} from '../../../src/Ada' import { - StakeCredentialParamsType, + CredentialParamsType, TransactionSigningMode, } from '../../../src/types/public' import {str_to_path} from '../../../src/utils/address' @@ -283,7 +283,7 @@ export const testsAlonzo: SignTxTestCase[] = [ type: CertificateType.STAKE_DELEGATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_HASH, + type: CredentialParamsType.KEY_HASH, keyHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -295,7 +295,7 @@ export const testsAlonzo: SignTxTestCase[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.KEY_HASH, + type: CredentialParamsType.KEY_HASH, keyHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, diff --git a/test/integration/__fixtures__/signTxPoolRegistration.ts b/test/integration/__fixtures__/signTxPoolRegistration.ts index 2f13eeb5..54cb249d 100644 --- a/test/integration/__fixtures__/signTxPoolRegistration.ts +++ b/test/integration/__fixtures__/signTxPoolRegistration.ts @@ -10,7 +10,7 @@ import type { TxOutput, } from '../../../src/Ada' import { - StakeCredentialParamsType, + CredentialParamsType, PoolKeyType, PoolRewardAccountType, CertificateType, @@ -260,7 +260,7 @@ export const certificates: Record< type: CertificateType.STAKE_DELEGATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, poolKeyHashHex: @@ -271,7 +271,7 @@ export const certificates: Record< type: 0, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, }, diff --git a/test/integration/__fixtures__/signTxRejects.ts b/test/integration/__fixtures__/signTxRejects.ts index e20046ba..e4822f70 100644 --- a/test/integration/__fixtures__/signTxRejects.ts +++ b/test/integration/__fixtures__/signTxRejects.ts @@ -23,7 +23,7 @@ import { PoolKeyType, PoolOwnerType, PoolRewardAccountType, - StakeCredentialParamsType, + CredentialParamsType, TransactionSigningMode, } from '../../../src/types/public' import {str_to_path} from '../../../src/utils/address' @@ -114,28 +114,28 @@ const poolRetirementParam: PoolRetirementParams = { const stakeRegistrationPathParam: StakeRegistrationParams = { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, } const stakeRegistrationScriptHashParam: StakeRegistrationParams = { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, } const stakeDeregistrationParam: StakeDeregistrationParams = { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, } const stakeDelegationParam: StakeDelegationParams = { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, poolKeyHashHex: '', @@ -256,7 +256,7 @@ export const transactionInitRejectTestCases: TestCaseRejectShelley[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -285,7 +285,7 @@ export const transactionInitRejectTestCases: TestCaseRejectShelley[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -1058,7 +1058,7 @@ export const certificateStakingRejectTestCases: TestCaseRejectShelley[] = [ type: CertificateType.STAKE_REGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/0/0"), }, }, @@ -1085,7 +1085,7 @@ export const certificateStakingRejectTestCases: TestCaseRejectShelley[] = [ errCls: DeviceStatusError, errMsg: DeviceStatusMessages[DeviceStatusCodes.ERR_REJECTED_BY_POLICY], rejectReason: - InvalidDataReason.SIGN_MODE_MULTISIG__CERTIFICATE_STAKE_CREDENTIAL_ONLY_AS_SCRIPT, + InvalidDataReason.SIGN_MODE_MULTISIG__CERTIFICATE_CREDENTIAL_ONLY_AS_SCRIPT, }, ] @@ -1122,7 +1122,7 @@ export const withdrawalRejectTestCases: TestCaseRejectShelley[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.SCRIPT_HASH, + type: CredentialParamsType.SCRIPT_HASH, scriptHashHex: '29fb5fd4aa8cadd6705acc8263cee0fc62edca5ac38db593fec2f9fd', }, @@ -1142,7 +1142,7 @@ export const withdrawalRejectTestCases: TestCaseRejectShelley[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/0/0"), }, amount: 1000, @@ -1161,7 +1161,7 @@ export const withdrawalRejectTestCases: TestCaseRejectShelley[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, amount: 1000, @@ -1181,7 +1181,7 @@ export const withdrawalRejectTestCases: TestCaseRejectShelley[] = [ withdrawals: [ { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/0/0"), }, amount: 1000, @@ -1701,7 +1701,7 @@ export const singleAccountRejectTestCases: TestCaseRejectShelley[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/1'/2/0"), }, }, @@ -1737,7 +1737,7 @@ export const singleAccountRejectTestCases: TestCaseRejectShelley[] = [ { amount: 1000, stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/1'/2/0"), }, }, @@ -1774,7 +1774,7 @@ export const singleAccountRejectTestCases: TestCaseRejectShelley[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/1'/2/0"), }, }, @@ -1811,7 +1811,7 @@ export const singleAccountRejectTestCases: TestCaseRejectShelley[] = [ { amount: 1000, stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/1'/2/0"), }, }, @@ -1848,7 +1848,7 @@ export const singleAccountRejectTestCases: TestCaseRejectShelley[] = [ type: CertificateType.STAKE_DEREGISTRATION, params: { stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/0'/2/0"), }, }, @@ -1858,7 +1858,7 @@ export const singleAccountRejectTestCases: TestCaseRejectShelley[] = [ { amount: 1000, stakeCredential: { - type: StakeCredentialParamsType.KEY_PATH, + type: CredentialParamsType.KEY_PATH, keyPath: str_to_path("1852'/1815'/1'/2/0"), }, }, diff --git a/test/integration/getVersion.test.ts b/test/integration/getVersion.test.ts index 47952203..84443881 100644 --- a/test/integration/getVersion.test.ts +++ b/test/integration/getVersion.test.ts @@ -20,7 +20,7 @@ describe('getVersion', () => { const {version, compatibility} = await ada.getVersion() - expect(version.major).to.equal(6) + expect(version.major).to.equal(7) expect(version.minor).to.equal(0) expect(version.flags.isDebug).to.equal(true) @@ -43,6 +43,7 @@ describe('getVersion', () => { supportsReqSignersInOrdinaryTx: true, supportsBabbage: true, supportsCIP36Vote: true, + supportsConway: true, }) }) }) diff --git a/test/integration/signTx.test.ts b/test/integration/signTx.test.ts index 02d30342..29228ce0 100644 --- a/test/integration/signTx.test.ts +++ b/test/integration/signTx.test.ts @@ -4,6 +4,9 @@ import { testsAlonzoTrezorComparison, testsBabbageTrezorComparison, testsByron, + testsConwayVotingProcedures, + testsConwayWithCertificates, + testsConwayWithoutCertificates, testsMary, testsMultidelegation, testsMultisig, @@ -35,6 +38,18 @@ describeSignTxPositiveTest( 'signTxShelleyWithCertificates', testsShelleyWithCertificates, ) +describeSignTxPositiveTest( + 'signTxConwayWithoutCertificates', + testsConwayWithoutCertificates, +) +describeSignTxPositiveTest( + 'signTxConwayWithCertificates', + testsConwayWithCertificates, +) +describeSignTxPositiveTest( + 'signTxConwayVotingProcedures', + testsConwayVotingProcedures, +) describeSignTxPositiveTest('signTxMultisig', testsMultisig) describeSignTxPositiveTest('signTxAllegra', testsAllegra) describeSignTxPositiveTest('signTxMary', testsMary)