From c3afedb8b0b3ff28a62353bb9695b67b308e520a Mon Sep 17 00:00:00 2001 From: Callum Date: Tue, 16 Dec 2025 18:52:52 +0000 Subject: [PATCH] Remove BaseTransactionMessage from transaction-message durable nonce functions --- .../src/__tests__/durable-nonce-test.ts | 16 ++--- .../__typetests__/durable-nonce-typetest.ts | 22 +++---- .../transaction-messages/src/durable-nonce.ts | 60 ++++++++++--------- 3 files changed, 50 insertions(+), 48 deletions(-) diff --git a/packages/transaction-messages/src/__tests__/durable-nonce-test.ts b/packages/transaction-messages/src/__tests__/durable-nonce-test.ts index 8e21b32d7..ea788dbb1 100644 --- a/packages/transaction-messages/src/__tests__/durable-nonce-test.ts +++ b/packages/transaction-messages/src/__tests__/durable-nonce-test.ts @@ -11,7 +11,7 @@ import { setTransactionMessageLifetimeUsingDurableNonce, TransactionMessageWithDurableNonceLifetime, } from '../durable-nonce'; -import { BaseTransactionMessage } from '../transaction-message'; +import { TransactionMessage } from '../transaction-message'; function createMockAdvanceNonceAccountInstruction< TNonceAccountAddress extends string = string, @@ -42,7 +42,7 @@ function createMockAdvanceNonceAccountInstruction< } describe('assertIsDurableNonceTransactionMessage()', () => { - let durableNonceTx: BaseTransactionMessage & TransactionMessageWithDurableNonceLifetime; + let durableNonceTx: TransactionMessage & TransactionMessageWithDurableNonceLifetime; const NONCE_CONSTRAINT = { nonce: '123' as Nonce, nonceAccountAddress: '123' as Address, @@ -129,7 +129,7 @@ describe('assertIsDurableNonceTransactionMessage()', () => { blockhash: '123' as Blockhash, lastValidBlockHeight: 123n, } as TransactionMessageWithBlockhashLifetime['lifetimeConstraint'], - } as BaseTransactionMessage); + } as unknown as TransactionMessage); }).toThrow(); }); it('does not throw when supplied a durable nonce transaction', () => { @@ -165,7 +165,7 @@ describe('assertIsDurableNonceTransactionMessage()', () => { }); describe('setTransactionMessageLifetimeUsingDurableNonce', () => { - let baseTx: BaseTransactionMessage; + let baseTx: TransactionMessage; const NONCE_CONSTRAINT_A = { nonce: '123' as Nonce, nonceAccountAddress: '123' as Address, @@ -210,7 +210,7 @@ describe('setTransactionMessageLifetimeUsingDurableNonce', () => { it('does not modify an `AdvanceNonceAccount` instruction if the existing one matches the constraint added', () => { const instruction = createMockAdvanceNonceAccountInstruction(NONCE_CONSTRAINT_A); instruction.accounts[2].role = AccountRole.WRITABLE_SIGNER; - const transaction: BaseTransactionMessage = { + const transaction: TransactionMessage = { ...baseTx, instructions: [instruction, baseTx.instructions[0]], }; @@ -222,7 +222,7 @@ describe('setTransactionMessageLifetimeUsingDurableNonce', () => { }); describe('when the existing `AdvanceNonceAccount` instruction does not match the constraint added', () => { it('replaces the existing instruction', () => { - const transaction: BaseTransactionMessage = { + const transaction: TransactionMessage = { ...baseTx, instructions: [ createMockAdvanceNonceAccountInstruction(NONCE_CONSTRAINT_B), @@ -240,7 +240,7 @@ describe('setTransactionMessageLifetimeUsingDurableNonce', () => { }); it('freezes the replacement instruction', () => { - const transaction: BaseTransactionMessage = { + const transaction: TransactionMessage = { ...baseTx, instructions: [ createMockAdvanceNonceAccountInstruction(NONCE_CONSTRAINT_B), @@ -256,7 +256,7 @@ describe('setTransactionMessageLifetimeUsingDurableNonce', () => { }); }); describe('given a durable nonce transaction', () => { - let durableNonceTxWithConstraintA: BaseTransactionMessage & TransactionMessageWithDurableNonceLifetime; + let durableNonceTxWithConstraintA: TransactionMessage & TransactionMessageWithDurableNonceLifetime; beforeEach(() => { durableNonceTxWithConstraintA = { ...baseTx, diff --git a/packages/transaction-messages/src/__typetests__/durable-nonce-typetest.ts b/packages/transaction-messages/src/__typetests__/durable-nonce-typetest.ts index d4e28acce..a546df6e4 100644 --- a/packages/transaction-messages/src/__typetests__/durable-nonce-typetest.ts +++ b/packages/transaction-messages/src/__typetests__/durable-nonce-typetest.ts @@ -14,7 +14,7 @@ import { import { AdvanceNonceAccountInstruction } from '../durable-nonce-instruction'; import { setTransactionMessageFeePayer, TransactionMessageWithFeePayer } from '../fee-payer'; import { appendTransactionMessageInstruction } from '../instructions'; -import { BaseTransactionMessage, TransactionMessage } from '../transaction-message'; +import { TransactionMessage } from '../transaction-message'; import { TransactionMessageWithinSizeLimit } from '../transaction-message-size'; const mockNonceConfig = { @@ -37,11 +37,11 @@ type V0TransactionMessage = Extract; { // It narrows the transaction message type to one with a nonce-based lifetime. { - const message = null as unknown as BaseTransactionMessage & { some: 1 }; + const message = null as unknown as TransactionMessage & { some: 1 }; if (isTransactionMessageWithDurableNonceLifetime(message)) { - message satisfies BaseTransactionMessage & TransactionMessageWithDurableNonceLifetime & { some: 1 }; + message satisfies TransactionMessage & TransactionMessageWithDurableNonceLifetime & { some: 1 }; } else { - message satisfies BaseTransactionMessage & { some: 1 }; + message satisfies TransactionMessage & { some: 1 }; // @ts-expect-error It does not have a nonce-based lifetime. message satisfies TransactionMessageWithDurableNonceLifetime; } @@ -52,7 +52,7 @@ type V0TransactionMessage = Extract; { // It narrows the transaction message type to one with a nonce-based lifetime. { - const message = null as unknown as BaseTransactionMessage & { some: 1 }; + const message = null as unknown as TransactionMessage & { some: 1 }; // @ts-expect-error Should not be durable nonce lifetime message satisfies TransactionMessageWithDurableNonceLifetime; // @ts-expect-error Should not have a nonce-based lifetime @@ -60,7 +60,7 @@ type V0TransactionMessage = Extract; // @ts-expect-error Should not start with a nonce instruction. message.instructions[0] satisfies AdvanceNonceAccountInstruction; assertIsTransactionMessageWithDurableNonceLifetime(message); - message satisfies BaseTransactionMessage & TransactionMessageWithDurableNonceLifetime & { some: 1 }; + message satisfies TransactionMessage & TransactionMessageWithDurableNonceLifetime & { some: 1 }; message satisfies TransactionMessageWithDurableNonceLifetime; message satisfies { lifetimeConstraint: { nonce: Nonce } }; message.instructions[0] satisfies AdvanceNonceAccountInstruction; @@ -97,7 +97,7 @@ type V0TransactionMessage = Extract; m => setTransactionMessageLifetimeUsingDurableNonce(mockNonceConfig, m), ); - message satisfies BaseTransactionMessage & TransactionMessageWithFeePayer; + message satisfies TransactionMessage & TransactionMessageWithFeePayer; message satisfies TransactionMessageWithDurableNonceLifetime<'nonce', 'nonceAuthority', 'nonce'>; message.instructions satisfies readonly [ AdvanceNonceAccountInstruction<'nonce', 'nonceAuthority'>, @@ -116,7 +116,7 @@ type V0TransactionMessage = Extract; m => setTransactionMessageLifetimeUsingDurableNonce(newMockNonceConfig, m), ); - message satisfies BaseTransactionMessage & TransactionMessageWithFeePayer; + message satisfies TransactionMessage & TransactionMessageWithFeePayer; message satisfies TransactionMessageWithDurableNonceLifetime<'newNonce', 'newNonceAuthority', 'newNonce'>; message.instructions satisfies readonly [ AdvanceNonceAccountInstruction<'newNonce', 'newNonceAuthority'>, @@ -126,7 +126,7 @@ type V0TransactionMessage = Extract; // It keeps the size limit type safety if we are only updating the durable nonce lifetime. { - const message = null as unknown as BaseTransactionMessage & + const message = null as unknown as TransactionMessage & TransactionMessageWithDurableNonceLifetime & TransactionMessageWithinSizeLimit; const newMessage = setTransactionMessageLifetimeUsingDurableNonce(mockNonceConfig, message); @@ -135,7 +135,7 @@ type V0TransactionMessage = Extract; // It removes the size limit type safety if we previously has a blockhash lifetime. { - const message = null as unknown as BaseTransactionMessage & + const message = null as unknown as TransactionMessage & TransactionMessageWithBlockhashLifetime & TransactionMessageWithinSizeLimit; const newMessage = setTransactionMessageLifetimeUsingDurableNonce(mockNonceConfig, message); @@ -145,7 +145,7 @@ type V0TransactionMessage = Extract; // It removes the size limit type safety if we previously had no lifetime set. { - const message = null as unknown as BaseTransactionMessage & TransactionMessageWithinSizeLimit; + const message = null as unknown as TransactionMessage & TransactionMessageWithinSizeLimit; const newMessage = setTransactionMessageLifetimeUsingDurableNonce(mockNonceConfig, message); // @ts-expect-error The message may no longer be within size limit. newMessage satisfies TransactionMessageWithinSizeLimit; diff --git a/packages/transaction-messages/src/durable-nonce.ts b/packages/transaction-messages/src/durable-nonce.ts index 905f3edd0..4c8c9a560 100644 --- a/packages/transaction-messages/src/durable-nonce.ts +++ b/packages/transaction-messages/src/durable-nonce.ts @@ -9,7 +9,7 @@ import { isAdvanceNonceAccountInstruction, } from './durable-nonce-instruction'; import { ExcludeTransactionMessageLifetime } from './lifetime'; -import { BaseTransactionMessage } from './transaction-message'; +import { TransactionMessage } from './transaction-message'; import { ExcludeTransactionMessageWithinSizeLimit } from './transaction-message-size'; type DurableNonceConfig< @@ -65,7 +65,7 @@ export interface TransactionMessageWithDurableNonceLifetime< /** * A helper type to exclude the durable nonce lifetime constraint from a transaction message. */ -export type ExcludeTransactionMessageDurableNonceLifetime = +export type ExcludeTransactionMessageDurableNonceLifetime = TTransactionMessage extends TransactionMessageWithDurableNonceLifetime ? ExcludeTransactionMessageLifetime : TTransactionMessage; @@ -94,8 +94,8 @@ export type ExcludeTransactionMessageDurableNonceLifetime = Omit< - // 1. The transaction message only grows in size if it currently has a different (or no) lifetime. - TTransactionMessage extends TransactionMessageWithDurableNonceLifetime - ? TTransactionMessage - : ExcludeTransactionMessageWithinSizeLimit, - // 2. Remove the instructions array as we are going to replace it with a new one. - 'instructions' -> & { - // 3. Replace or prepend the first instruction with the advance nonce account instruction. - readonly instructions: TTransactionMessage['instructions'] extends readonly [ - AdvanceNonceAccountInstruction, - ...infer TTail extends readonly Instruction[], - ] - ? readonly [AdvanceNonceAccountInstruction, ...TTail] - : readonly [ - AdvanceNonceAccountInstruction, - ...TTransactionMessage['instructions'], - ]; - // 4. Set the lifetime constraint to the nonce value. - readonly lifetimeConstraint: NonceLifetimeConstraint; -}; +> = TTransactionMessage extends unknown + ? Omit< + // 1. The transaction message only grows in size if it currently has a different (or no) lifetime. + TTransactionMessage extends TransactionMessageWithDurableNonceLifetime + ? TTransactionMessage + : ExcludeTransactionMessageWithinSizeLimit, + // 2. Remove the instructions array as we are going to replace it with a new one. + 'instructions' + > & { + // 3. Replace or prepend the first instruction with the advance nonce account instruction. + readonly instructions: TTransactionMessage['instructions'] extends readonly [ + AdvanceNonceAccountInstruction, + ...infer TTail extends readonly Instruction[], + ] + ? readonly [AdvanceNonceAccountInstruction, ...TTail] + : readonly [ + AdvanceNonceAccountInstruction, + ...TTransactionMessage['instructions'], + ]; + // 4. Set the lifetime constraint to the nonce value. + readonly lifetimeConstraint: NonceLifetimeConstraint; + } + : never;