Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/metal-rice-make.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solana/transaction-messages': patch
---

Refactor transaction-messages package to stop using BaseTransactionMessage
8 changes: 4 additions & 4 deletions packages/transaction-messages/src/__tests__/fee-payer-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import '@solana/test-matchers/toBeFrozenObject';
import { Address } from '@solana/addresses';

import { setTransactionMessageFeePayer, TransactionMessageWithFeePayer } from '../fee-payer';
import { BaseTransactionMessage } from '../transaction-message';
import { TransactionMessage } from '../transaction-message';

const EXAMPLE_FEE_PAYER_A =
'7mvYAxeCui21xYkAyQSjh6iBVZPpgVyt7PYv9km8V5mE' as Address<'7mvYAxeCui21xYkAyQSjh6iBVZPpgVyt7PYv9km8V5mE'>;
const EXAMPLE_FEE_PAYER_B =
'5LHng8dLBxCYyR3jdDbobLiRQ6pR74pYtxKohY93RbZN' as Address<'5LHng8dLBxCYyR3jdDbobLiRQ6pR74pYtxKohY93RbZN'>;

describe('setTransactionMessageFeePayer', () => {
let baseTx: BaseTransactionMessage;
let baseTx: TransactionMessage;
beforeEach(() => {
baseTx = {
instructions: [],
Expand All @@ -23,7 +23,7 @@ describe('setTransactionMessageFeePayer', () => {
expect(txWithFeePayerA).toHaveProperty('feePayer', { address: EXAMPLE_FEE_PAYER_A });
});
describe('given a transaction with a fee payer already set', () => {
let txWithFeePayerA: BaseTransactionMessage & TransactionMessageWithFeePayer;
let txWithFeePayerA: TransactionMessage & TransactionMessageWithFeePayer;
beforeEach(() => {
txWithFeePayerA = {
...baseTx,
Expand All @@ -40,7 +40,7 @@ describe('setTransactionMessageFeePayer', () => {
});
});
describe('given a transaction with a fee payer with extra properties set', () => {
let txWithFeePayerA: BaseTransactionMessage & {
let txWithFeePayerA: TransactionMessage & {
readonly feePayer: Readonly<{ address: Address; extra: 'extra' }>;
};
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
prependTransactionMessageInstruction,
prependTransactionMessageInstructions,
} from '../instructions';
import { BaseTransactionMessage } from '../transaction-message';
import { TransactionMessage } from '../transaction-message';

const PROGRAM_A =
'AALQD2dt1k43Acrkp4SvdhZaN4S115Ff2Bi7rHPti3sL' as Address<'AALQD2dt1k43Acrkp4SvdhZaN4S115Ff2Bi7rHPti3sL'>;
Expand All @@ -19,7 +19,7 @@ const PROGRAM_C =
'6Bkt4j67rxzFF6s9DaMRyfitftRrGxe4oYHPRHuFChzi' as Address<'6Bkt4j67rxzFF6s9DaMRyfitftRrGxe4oYHPRHuFChzi'>;

describe('Transaction instruction helpers', () => {
let baseTx: BaseTransactionMessage;
let baseTx: TransactionMessage;
let exampleInstruction: Instruction<string>;
let secondExampleInstruction: Instruction<string>;
beforeEach(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Address } from '@solana/addresses';
import { TransactionMessageWithBlockhashLifetime } from '../blockhash';
import { TransactionMessageWithDurableNonceLifetime } from '../durable-nonce';
import { setTransactionMessageFeePayer, TransactionMessageWithFeePayer } from '../fee-payer';
import { BaseTransactionMessage, TransactionMessage } from '../transaction-message';
import { TransactionMessage } from '../transaction-message';

const mockFeePayer = 'mock' as Address<'mockFeePayer'>;
const aliceAddress = 'alice' as Address<'alice'>;
Expand All @@ -16,17 +16,17 @@ type V0TransactionMessage = Extract<TransactionMessage, { version: 0 }>;
{
// It adds the fee payer to the new message
{
const message = null as unknown as BaseTransactionMessage & { some: 1 };
const message = null as unknown as TransactionMessage & { some: 1 };
const messageWithFeePayer = setTransactionMessageFeePayer(aliceAddress, message);
messageWithFeePayer satisfies BaseTransactionMessage & TransactionMessageWithFeePayer<'alice'> & { some: 1 };
messageWithFeePayer satisfies TransactionMessage & TransactionMessageWithFeePayer<'alice'> & { some: 1 };
}

// It *replaces* an existing fee payer with the new one
{
const messageWithAliceFeePayer = null as unknown as BaseTransactionMessage &
const messageWithAliceFeePayer = null as unknown as TransactionMessage &
TransactionMessageWithFeePayer<'alice'> & { some: 1 };
const messageWithBobFeePayer = setTransactionMessageFeePayer(bobAddress, messageWithAliceFeePayer);
messageWithBobFeePayer satisfies BaseTransactionMessage & TransactionMessageWithFeePayer<'bob'> & { some: 1 };
messageWithBobFeePayer satisfies TransactionMessage & TransactionMessageWithFeePayer<'bob'> & { some: 1 };
// @ts-expect-error Alice should no longer be a payer.
messageWithBobFeePayer satisfies TransactionMessageWithFeePayer<'alice'>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
prependTransactionMessageInstruction,
prependTransactionMessageInstructions,
} from '../instructions';
import { BaseTransactionMessage, TransactionMessage } from '../transaction-message';
import { TransactionMessage } from '../transaction-message';
import { TransactionMessageWithinSizeLimit } from '../transaction-message-size';

type Instruction = BaseTransactionMessage['instructions'][number];
type Instruction = TransactionMessage['instructions'][number];
type InstructionA = Instruction & { identifier: 'A' };
type InstructionB = Instruction & { identifier: 'B' };
type InstructionC = Instruction & { identifier: 'C' };
Expand All @@ -29,9 +29,9 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
{
// It returns the same TransactionMessage type
{
const message = null as unknown as BaseTransactionMessage & { some: 1 };
const message = null as unknown as TransactionMessage & { some: 1 };
const newMessage = appendTransactionMessageInstruction(null as unknown as Instruction, message);
newMessage satisfies BaseTransactionMessage & { some: 1 };
newMessage satisfies TransactionMessage & { some: 1 };
}

// It concatenates the instruction types
Expand All @@ -47,7 +47,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac

// It adds instruction types to base transaction messages
{
const message = null as unknown as BaseTransactionMessage;
const message = null as unknown as TransactionMessage;
const newMessage = appendTransactionMessageInstruction(null as unknown as InstructionA, message);
newMessage.instructions satisfies readonly [...Instruction[], InstructionA];
}
Expand All @@ -63,9 +63,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
m => appendTransactionMessageInstruction(null as unknown as InstructionA, m),
);

message satisfies BaseTransactionMessage &
TransactionMessageWithBlockhashLifetime &
TransactionMessageWithFeePayer;
message satisfies TransactionMessage & TransactionMessageWithBlockhashLifetime & TransactionMessageWithFeePayer;
message.instructions satisfies readonly [InstructionA];
}

Expand All @@ -80,15 +78,15 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
m => appendTransactionMessageInstruction(null as unknown as InstructionA, m),
);

message satisfies BaseTransactionMessage &
message satisfies TransactionMessage &
TransactionMessageWithDurableNonceLifetime &
TransactionMessageWithFeePayer;
message.instructions satisfies readonly [AdvanceNonceAccountInstruction, InstructionA];
}

// It removes the size limit type safety.
{
const message = null as unknown as BaseTransactionMessage & TransactionMessageWithinSizeLimit;
const message = null as unknown as TransactionMessage & TransactionMessageWithinSizeLimit;
const newMessage = appendTransactionMessageInstruction(null as unknown as Instruction, message);
// @ts-expect-error Potentially no longer within size limit.
newMessage satisfies TransactionMessageWithinSizeLimit;
Expand All @@ -110,9 +108,9 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
{
// It returns the same TransactionMessage type
{
const message = null as unknown as BaseTransactionMessage & { some: 1 };
const message = null as unknown as TransactionMessage & { some: 1 };
const newMessage = appendTransactionMessageInstructions(null as unknown as Instruction[], message);
newMessage satisfies BaseTransactionMessage & { some: 1 };
newMessage satisfies TransactionMessage & { some: 1 };
}

// It concatenates the instruction types
Expand All @@ -131,7 +129,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac

// It adds instruction types to base transaction messages
{
const message = null as unknown as BaseTransactionMessage;
const message = null as unknown as TransactionMessage;
const newMessage = appendTransactionMessageInstructions(
[null as unknown as InstructionA, null as unknown as InstructionB],
message,
Expand All @@ -141,7 +139,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac

// It removes the size limit type safety.
{
const message = null as unknown as BaseTransactionMessage & TransactionMessageWithinSizeLimit;
const message = null as unknown as TransactionMessage & TransactionMessageWithinSizeLimit;
const newMessage = appendTransactionMessageInstructions([null as unknown as Instruction], message);
// @ts-expect-error Potentially no longer within size limit.
newMessage satisfies TransactionMessageWithinSizeLimit;
Expand All @@ -163,27 +161,26 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
{
// It returns the same TransactionMessage type
{
const message = null as unknown as BaseTransactionMessage & { some: 1 };
const message = null as unknown as TransactionMessage & { some: 1 };
const newMessage = prependTransactionMessageInstruction(null as unknown as Instruction, message);
newMessage satisfies BaseTransactionMessage & { some: 1 };
newMessage satisfies TransactionMessage & { some: 1 };
}

// It strips the durable nonce transaction message type
{
const message = null as unknown as BaseTransactionMessage &
const message = null as unknown as TransactionMessage &
TransactionMessageWithDurableNonceLifetime & { some: 1 };
const newMessage = prependTransactionMessageInstruction(null as unknown as Instruction, message);
newMessage satisfies BaseTransactionMessage & { some: 1 };
newMessage satisfies TransactionMessage & { some: 1 };
// @ts-expect-error The durable nonce transaction message type should be stripped.
newMessage satisfies TransactionMessageWithDurableNonceLifetime;
}

// It does not remove blockhash lifetimes.
{
const message = null as unknown as BaseTransactionMessage &
TransactionMessageWithBlockhashLifetime & { some: 1 };
const message = null as unknown as TransactionMessage & TransactionMessageWithBlockhashLifetime & { some: 1 };
const newMessage = prependTransactionMessageInstruction(null as unknown as Instruction, message);
newMessage satisfies BaseTransactionMessage & TransactionMessageWithBlockhashLifetime & { some: 1 };
newMessage satisfies TransactionMessage & TransactionMessageWithBlockhashLifetime & { some: 1 };
}

// It concatenates the instruction types
Expand All @@ -199,7 +196,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac

// It adds instruction types to base transaction messages
{
const message = null as unknown as BaseTransactionMessage;
const message = null as unknown as TransactionMessage;
const newMessage = prependTransactionMessageInstruction(null as unknown as InstructionA, message);
newMessage.instructions satisfies readonly [InstructionA, ...Instruction[]];
}
Expand All @@ -215,9 +212,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
m => prependTransactionMessageInstruction(null as unknown as InstructionA, m),
);

message satisfies BaseTransactionMessage &
TransactionMessageWithBlockhashLifetime &
TransactionMessageWithFeePayer;
message satisfies TransactionMessage & TransactionMessageWithBlockhashLifetime & TransactionMessageWithFeePayer;
message.instructions satisfies readonly [InstructionA];
}

Expand All @@ -233,14 +228,14 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
);

message.instructions satisfies readonly [InstructionA, AdvanceNonceAccountInstruction];
message satisfies BaseTransactionMessage & TransactionMessageWithFeePayer;
message satisfies TransactionMessage & TransactionMessageWithFeePayer;
// @ts-expect-error No longer a durable nonce lifetime.
message satisfies TransactionMessageWithDurableNonceLifetime;
}

// It removes the size limit type safety.
{
const message = null as unknown as BaseTransactionMessage & TransactionMessageWithinSizeLimit;
const message = null as unknown as TransactionMessage & TransactionMessageWithinSizeLimit;
const newMessage = prependTransactionMessageInstruction(null as unknown as Instruction, message);
// @ts-expect-error Potentially no longer within size limit.
newMessage satisfies TransactionMessageWithinSizeLimit;
Expand All @@ -262,17 +257,17 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac
{
// It returns the same TransactionMessage type
{
const message = null as unknown as BaseTransactionMessage & { some: 1 };
const message = null as unknown as TransactionMessage & { some: 1 };
const newMessage = prependTransactionMessageInstructions(null as unknown as Instruction[], message);
newMessage satisfies BaseTransactionMessage & { some: 1 };
newMessage satisfies TransactionMessage & { some: 1 };
}

// It strips the durable nonce transaction message type
{
const message = null as unknown as BaseTransactionMessage &
const message = null as unknown as TransactionMessage &
TransactionMessageWithDurableNonceLifetime & { some: 1 };
const newMessage = prependTransactionMessageInstructions(null as unknown as Instruction[], message);
newMessage satisfies BaseTransactionMessage & { some: 1 };
newMessage satisfies TransactionMessage & { some: 1 };
// @ts-expect-error The durable nonce transaction message type should be stripped.
newMessage satisfies TransactionMessageWithDurableNonceLifetime;
}
Expand All @@ -293,7 +288,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac

// It adds instruction types to base transaction messages
{
const message = null as unknown as BaseTransactionMessage;
const message = null as unknown as TransactionMessage;
const newMessage = prependTransactionMessageInstructions(
[null as unknown as InstructionA, null as unknown as InstructionB],
message,
Expand All @@ -303,7 +298,7 @@ type TransactionMessageNotLegacy = Exclude<TransactionMessage, { version: 'legac

// It removes the size limit type safety.
{
const message = null as unknown as BaseTransactionMessage & TransactionMessageWithinSizeLimit;
const message = null as unknown as TransactionMessage & TransactionMessageWithinSizeLimit;
const newMessage = prependTransactionMessageInstructions([null as unknown as Instruction], message);
// @ts-expect-error Potentially no longer within size limit.
newMessage satisfies TransactionMessageWithinSizeLimit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Address } from '@solana/addresses';
import { TransactionMessageWithBlockhashLifetime } from '../../blockhash';
import { TransactionMessageWithFeePayer } from '../../fee-payer';
import { TransactionMessageWithLifetime } from '../../lifetime';
import { BaseTransactionMessage } from '../../transaction-message';
import { TransactionMessage } from '../../transaction-message';
import { getCompiledAddressTableLookups } from '../address-table-lookups';
import { getCompiledMessageHeader } from '../header';
import { getCompiledInstructions } from '../instructions';
Expand All @@ -21,7 +21,7 @@ const MOCK_LIFETIME_CONSTRAINT =
'SOME_CONSTRAINT' as unknown as TransactionMessageWithBlockhashLifetime['lifetimeConstraint'];

describe('compileTransactionMessage', () => {
let baseTx: BaseTransactionMessage & TransactionMessageWithFeePayer & TransactionMessageWithLifetime;
let baseTx: TransactionMessage & TransactionMessageWithFeePayer & TransactionMessageWithLifetime;
beforeEach(() => {
baseTx = {
feePayer: { address: 'abc' as Address<'abc'> },
Expand Down Expand Up @@ -50,7 +50,7 @@ describe('compileTransactionMessage', () => {
});
});
it('sets `addressTableLookups` to the return value of `getCompiledAddressTableLookups`', () => {
const message = compileTransactionMessage(baseTx);
const message = compileTransactionMessage(baseTx as typeof baseTx & { version: 0 });
expect(getCompiledAddressTableLookups).toHaveBeenCalled();
expect(message.addressTableLookups).toBe(expectedAddressTableLookups);
});
Expand Down
10 changes: 5 additions & 5 deletions packages/transaction-messages/src/compile/message.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TransactionMessageWithFeePayer } from '../fee-payer';
import { TransactionMessageWithLifetime } from '../lifetime';
import { BaseTransactionMessage } from '../transaction-message';
import { TransactionMessage } from '../transaction-message';
import { getAddressMapFromInstructions, getOrderedAccountsFromAddressMap } from './accounts';
import { getCompiledAddressTableLookups } from './address-table-lookups';
import { getCompiledMessageHeader } from './header';
Expand Down Expand Up @@ -63,7 +63,7 @@ type VersionedCompiledTransactionMessage = BaseCompiledTransactionMessage &
* @see {@link decompileTransactionMessage}
*/
export function compileTransactionMessage<
TTransactionMessage extends BaseTransactionMessage & TransactionMessageWithFeePayer,
TTransactionMessage extends TransactionMessage & TransactionMessageWithFeePayer,
>(transactionMessage: TTransactionMessage): CompiledTransactionMessageFromTransactionMessage<TTransactionMessage> {
type ReturnType = CompiledTransactionMessageFromTransactionMessage<TTransactionMessage>;

Expand All @@ -86,17 +86,17 @@ export function compileTransactionMessage<
} as ReturnType;
}

type CompiledTransactionMessageFromTransactionMessage<TTransactionMessage extends BaseTransactionMessage> =
type CompiledTransactionMessageFromTransactionMessage<TTransactionMessage extends TransactionMessage> =
ForwardTransactionMessageLifetime<ForwardTransactionMessageVersion<TTransactionMessage>, TTransactionMessage>;

type ForwardTransactionMessageVersion<TTransactionMessage extends BaseTransactionMessage> =
type ForwardTransactionMessageVersion<TTransactionMessage extends TransactionMessage> =
TTransactionMessage extends Readonly<{ version: 'legacy' }>
? LegacyCompiledTransactionMessage
: VersionedCompiledTransactionMessage;

type ForwardTransactionMessageLifetime<
TCompiledTransactionMessage extends CompiledTransactionMessage,
TTransactionMessage extends BaseTransactionMessage,
TTransactionMessage extends TransactionMessage,
> = TTransactionMessage extends TransactionMessageWithLifetime
? CompiledTransactionMessageWithLifetime & TCompiledTransactionMessage
: TCompiledTransactionMessage;
Loading