diff --git a/.changeset/sour-beans-hear.md b/.changeset/sour-beans-hear.md new file mode 100644 index 000000000..c1b0c5469 --- /dev/null +++ b/.changeset/sour-beans-hear.md @@ -0,0 +1,7 @@ +--- +'@solana/transactions': major +'@solana/signers': major +'@solana/kit': major +--- + +BREAKING CHANGE: The `FullySignedTransaction` no longer extends the `Transaction` type so it can be composed with other flags that also narrow transaction types. This means, whenever `FullySignedTransaction` is used on its own, it will need to be replaced with `FullySignedTransaction & Transaction`. diff --git a/docs/content/docs/getting-started/send-transaction.mdx b/docs/content/docs/getting-started/send-transaction.mdx index b3b2cb912..071878ab0 100644 --- a/docs/content/docs/getting-started/send-transaction.mdx +++ b/docs/content/docs/getting-started/send-transaction.mdx @@ -12,8 +12,8 @@ The most common way to send transactions is via the `sendTransaction` RPC method One way to tackle this would be to encode the transaction ourselves using `getBase64EncodedWireTransaction` and pass it to the `sendTransaction` RPC method like so. ```ts twoslash -import { FullySignedTransaction, TransactionWithBlockhashLifetime, Rpc, SolanaRpcApi } from "@solana/kit"; -const signedTransaction = null as unknown as FullySignedTransaction & TransactionWithBlockhashLifetime; +import { Transaction, FullySignedTransaction, TransactionWithBlockhashLifetime, Rpc, SolanaRpcApi } from "@solana/kit"; +const signedTransaction = null as unknown as Transaction & FullySignedTransaction & TransactionWithBlockhashLifetime; const rpc = null as unknown as Rpc; // ---cut-before--- import { getBase64EncodedWireTransaction } from "@solana/kit"; @@ -25,8 +25,8 @@ await rpc.sendTransaction(encodedTransaction, { preflightCommitment: "confirmed" However, Kit offers a helper function that does that for us whilst providing some sensible default values. This function is called `sendTransactionWithoutConfirmingFactory` and, given an RPC object, it returns a function that sends transactions without waiting for confirmation. ```ts twoslash -import { FullySignedTransaction, TransactionWithBlockhashLifetime, Rpc, SolanaRpcApi } from "@solana/kit"; -const signedTransaction = null as unknown as FullySignedTransaction & TransactionWithBlockhashLifetime; +import { Transaction, FullySignedTransaction, TransactionWithBlockhashLifetime, Rpc, SolanaRpcApi } from "@solana/kit"; +const signedTransaction = null as unknown as Transaction & FullySignedTransaction & TransactionWithBlockhashLifetime; const rpc = null as unknown as Rpc; // ---cut-before--- import { sendTransactionWithoutConfirmingFactory } from "@solana/kit"; @@ -50,6 +50,7 @@ Both accept RPC and RPC Subscriptions objects and return a function that sends a ```ts twoslash import { + Transaction, FullySignedTransaction, TransactionWithBlockhashLifetime, Rpc, @@ -57,7 +58,7 @@ import { RpcSubscriptions, SolanaRpcSubscriptionsApi, } from "@solana/kit"; -const signedTransaction = null as unknown as FullySignedTransaction & TransactionWithBlockhashLifetime; +const signedTransaction = null as unknown as Transaction & FullySignedTransaction & TransactionWithBlockhashLifetime; const rpc = null as unknown as Rpc; const rpcSubscriptions = null as unknown as RpcSubscriptions; // ---cut-before--- @@ -77,6 +78,7 @@ As such, Kit decouples these two distinct concepts by offering a `getSignatureFr ```ts twoslash import { + Transaction, FullySignedTransaction, TransactionWithBlockhashLifetime, Rpc, @@ -84,7 +86,7 @@ import { RpcSubscriptions, SolanaRpcSubscriptionsApi, } from "@solana/kit"; -const signedTransaction = null as unknown as FullySignedTransaction & TransactionWithBlockhashLifetime; +const signedTransaction = null as unknown as Transaction & FullySignedTransaction & TransactionWithBlockhashLifetime; const rpc = null as unknown as Rpc; const rpcSubscriptions = null as unknown as RpcSubscriptions; // ---cut-before--- diff --git a/docs/content/docs/upgrade-guide.mdx b/docs/content/docs/upgrade-guide.mdx index c70e8da57..57151673f 100644 --- a/docs/content/docs/upgrade-guide.mdx +++ b/docs/content/docs/upgrade-guide.mdx @@ -473,10 +473,11 @@ import { createSolanaRpcSubscriptions, FullySignedTransaction, TransactionWithBlockhashLifetime, + Transaction, } from "@solana/kit"; const rpc = createSolanaRpc("https://api.devnet.solana.com"); const rpcSubscriptions = createSolanaRpcSubscriptions("wss://api.devnet.solana.com"); -const signedTransaction = null as unknown as FullySignedTransaction & TransactionWithBlockhashLifetime; +const signedTransaction = null as unknown as Transaction & FullySignedTransaction & TransactionWithBlockhashLifetime; // ---cut-end--- // Create a send and confirm function from your RPC and RPC Subscriptions objects. diff --git a/packages/kit/src/__tests__/send-transaction-internal-test.ts b/packages/kit/src/__tests__/send-transaction-internal-test.ts index 15de7ac81..2e0253bfe 100644 --- a/packages/kit/src/__tests__/send-transaction-internal-test.ts +++ b/packages/kit/src/__tests__/send-transaction-internal-test.ts @@ -5,6 +5,7 @@ import { Base64EncodedWireTransaction, FullySignedTransaction, getBase64EncodedWireTransaction, + Transaction, TransactionWithBlockhashLifetime, TransactionWithDurableNonceLifetime, } from '@solana/transactions'; @@ -21,7 +22,7 @@ const FOREVER_PROMISE = new Promise(() => { }); describe('sendAndConfirmTransaction', () => { - const MOCK_TRANSACTION = {} as FullySignedTransaction & TransactionWithBlockhashLifetime; + const MOCK_TRANSACTION = {} as FullySignedTransaction & Transaction & TransactionWithBlockhashLifetime; let confirmRecentTransaction: jest.Mock; let createPendingRequest: jest.Mock; let rpc: Rpc; @@ -176,6 +177,7 @@ describe('sendAndConfirmTransaction', () => { describe('sendAndConfirmDurableNonceTransaction', () => { const MOCK_DURABLE_NONCE_TRANSACTION = {} as unknown as FullySignedTransaction & + Transaction & TransactionWithDurableNonceLifetime; let confirmDurableNonceTransaction: jest.Mock; let createPendingRequest: jest.Mock; diff --git a/packages/kit/src/send-and-confirm-durable-nonce-transaction.ts b/packages/kit/src/send-and-confirm-durable-nonce-transaction.ts index c141852a9..3321b5f9d 100644 --- a/packages/kit/src/send-and-confirm-durable-nonce-transaction.ts +++ b/packages/kit/src/send-and-confirm-durable-nonce-transaction.ts @@ -5,12 +5,12 @@ import { createRecentSignatureConfirmationPromiseFactory, waitForDurableNonceTransactionConfirmation, } from '@solana/transaction-confirmation'; -import { FullySignedTransaction, TransactionWithDurableNonceLifetime } from '@solana/transactions'; +import { FullySignedTransaction, Transaction, TransactionWithDurableNonceLifetime } from '@solana/transactions'; import { sendAndConfirmDurableNonceTransaction_INTERNAL_ONLY_DO_NOT_EXPORT } from './send-transaction-internal'; type SendAndConfirmDurableNonceTransactionFunction = ( - transaction: FullySignedTransaction & TransactionWithDurableNonceLifetime, + transaction: FullySignedTransaction & Transaction & TransactionWithDurableNonceLifetime, config: Omit< Parameters[0], 'confirmDurableNonceTransaction' | 'rpc' | 'transaction' diff --git a/packages/kit/src/send-and-confirm-transaction.ts b/packages/kit/src/send-and-confirm-transaction.ts index d07545db4..bb39f468c 100644 --- a/packages/kit/src/send-and-confirm-transaction.ts +++ b/packages/kit/src/send-and-confirm-transaction.ts @@ -6,12 +6,12 @@ import { TransactionWithLastValidBlockHeight, waitForRecentTransactionConfirmation, } from '@solana/transaction-confirmation'; -import { FullySignedTransaction } from '@solana/transactions'; +import { FullySignedTransaction, Transaction } from '@solana/transactions'; import { sendAndConfirmTransactionWithBlockhashLifetime_INTERNAL_ONLY_DO_NOT_EXPORT } from './send-transaction-internal'; type SendAndConfirmTransactionWithBlockhashLifetimeFunction = ( - transaction: FullySignedTransaction & TransactionWithLastValidBlockHeight, + transaction: FullySignedTransaction & Transaction & TransactionWithLastValidBlockHeight, config: Omit< Parameters[0], 'confirmRecentTransaction' | 'rpc' | 'transaction' diff --git a/packages/kit/src/send-transaction-internal.ts b/packages/kit/src/send-transaction-internal.ts index 2af3792de..26786593c 100644 --- a/packages/kit/src/send-transaction-internal.ts +++ b/packages/kit/src/send-transaction-internal.ts @@ -9,6 +9,7 @@ import { import { FullySignedTransaction, getBase64EncodedWireTransaction, + Transaction, TransactionWithDurableNonceLifetime, } from '@solana/transactions'; @@ -21,7 +22,7 @@ interface SendAndConfirmDurableNonceTransactionConfig 'getNonceInvalidationPromise' | 'getRecentSignatureConfirmationPromise' >, ) => Promise; - transaction: FullySignedTransaction & TransactionWithDurableNonceLifetime; + transaction: FullySignedTransaction & Transaction & TransactionWithDurableNonceLifetime; } interface SendAndConfirmTransactionWithBlockhashLifetimeConfig @@ -33,14 +34,14 @@ interface SendAndConfirmTransactionWithBlockhashLifetimeConfig 'getBlockHeightExceedencePromise' | 'getRecentSignatureConfirmationPromise' >, ) => Promise; - transaction: FullySignedTransaction & TransactionWithLastValidBlockHeight; + transaction: FullySignedTransaction & Transaction & TransactionWithLastValidBlockHeight; } interface SendTransactionBaseConfig extends SendTransactionConfigWithoutEncoding { abortSignal?: AbortSignal; commitment: Commitment; rpc: Rpc; - transaction: FullySignedTransaction; + transaction: FullySignedTransaction & Transaction; } type SendTransactionConfigWithoutEncoding = Omit< diff --git a/packages/kit/src/send-transaction-without-confirming.ts b/packages/kit/src/send-transaction-without-confirming.ts index 3accab340..d0c449ef2 100644 --- a/packages/kit/src/send-transaction-without-confirming.ts +++ b/packages/kit/src/send-transaction-without-confirming.ts @@ -1,10 +1,10 @@ import type { Rpc, SendTransactionApi } from '@solana/rpc'; -import { FullySignedTransaction } from '@solana/transactions'; +import { FullySignedTransaction, Transaction } from '@solana/transactions'; import { sendTransaction_INTERNAL_ONLY_DO_NOT_EXPORT } from './send-transaction-internal'; type SendTransactionWithoutConfirmingFunction = ( - transaction: FullySignedTransaction, + transaction: FullySignedTransaction & Transaction, config: Omit[0], 'rpc' | 'transaction'>, ) => Promise; diff --git a/packages/signers/src/__tests__/sign-transaction-test.ts b/packages/signers/src/__tests__/sign-transaction-test.ts index d9d2c3691..1d400d228 100644 --- a/packages/signers/src/__tests__/sign-transaction-test.ts +++ b/packages/signers/src/__tests__/sign-transaction-test.ts @@ -441,7 +441,7 @@ describe('signTransactionMessageWithSigners', () => { }); // And the transaction is fully signed. - signedTransaction satisfies FullySignedTransaction; + signedTransaction satisfies FullySignedTransaction & Transaction; // And the signers were called with the expected parameters. expect(signerA.modifyAndSignTransactions).toHaveBeenCalledWith([unsignedTransaction], mockOptions); diff --git a/packages/signers/src/__typetests__/sign-transaction-typetest.ts b/packages/signers/src/__typetests__/sign-transaction-typetest.ts index 8d53434f4..5457eca9b 100644 --- a/packages/signers/src/__typetests__/sign-transaction-typetest.ts +++ b/packages/signers/src/__typetests__/sign-transaction-typetest.ts @@ -65,7 +65,7 @@ type CompilableTransactionMessageWithSigners = CompilableTransactionMessage & Tr const transactionMessage = null as unknown as CompilableTransactionMessageWithSigners & TransactionMessageWithBlockhashLifetime; signTransactionMessageWithSigners(transactionMessage) satisfies Promise< - Readonly + Readonly >; } @@ -74,7 +74,7 @@ type CompilableTransactionMessageWithSigners = CompilableTransactionMessage & Tr const transactionMessage = null as unknown as CompilableTransactionMessageWithSigners & TransactionMessageWithDurableNonceLifetime; signTransactionMessageWithSigners(transactionMessage) satisfies Promise< - Readonly + Readonly >; } @@ -82,7 +82,7 @@ type CompilableTransactionMessageWithSigners = CompilableTransactionMessage & Tr // [signTransactionMessageWithSigners]: returns a fully signed transaction with an unknown lifetime const transactionMessage = null as unknown as CompilableTransactionMessageWithSigners; signTransactionMessageWithSigners(transactionMessage) satisfies Promise< - Readonly + Readonly >; } diff --git a/packages/signers/src/sign-transaction.ts b/packages/signers/src/sign-transaction.ts index 80f6baf65..e844e05be 100644 --- a/packages/signers/src/sign-transaction.ts +++ b/packages/signers/src/sign-transaction.ts @@ -173,7 +173,7 @@ export async function signTransactionMessageWithSigners< * */ export async function signAndSendTransactionMessageWithSigners< - TTransactionMessage extends CompilableTransactionMessageWithSigners = CompilableTransactionMessageWithSigners, + TTransactionMessage extends CompilableTransactionMessageWithSigners, >(transaction: TTransactionMessage, config?: TransactionSendingSignerConfig): Promise { assertIsTransactionMessageWithSingleSendingSigner(transaction); diff --git a/packages/transactions/src/__typetests__/signatures-typetest.ts b/packages/transactions/src/__typetests__/signatures-typetest.ts index 12960d5a2..a299942dc 100644 --- a/packages/transactions/src/__typetests__/signatures-typetest.ts +++ b/packages/transactions/src/__typetests__/signatures-typetest.ts @@ -26,7 +26,7 @@ import { Transaction } from '../transaction'; // signTransaction { const transaction = null as unknown as Transaction & { some: 1 }; - signTransaction([], transaction) satisfies Promise; + signTransaction([], transaction) satisfies Promise; } // isFullySignedTransaction diff --git a/packages/transactions/src/signatures.ts b/packages/transactions/src/signatures.ts index 0f711d900..8f2414856 100644 --- a/packages/transactions/src/signatures.ts +++ b/packages/transactions/src/signatures.ts @@ -16,7 +16,7 @@ import { Transaction } from './transaction'; * Represents a transaction that is signed by all of its required signers. Being fully signed is a * prerequisite of functions designed to land transactions on the network. */ -export type FullySignedTransaction = NominalType<'transactionSignedness', 'fullySigned'> & Transaction; +export type FullySignedTransaction = NominalType<'transactionSignedness', 'fullySigned'>; let base58Decoder: Decoder | undefined; @@ -70,10 +70,10 @@ function uint8ArraysEqual(arr1: Uint8Array, arr2: Uint8Array) { * @see {@link signTransaction} if you want to assert that the transaction has all of its required * signatures after signing. */ -export async function partiallySignTransaction( +export async function partiallySignTransaction( keyPairs: CryptoKeyPair[], - transaction: T, -): Promise { + transaction: TTransaction, +): Promise { let newSignatures: Record | undefined; let unexpectedSigners: Set
| undefined; @@ -146,10 +146,10 @@ export async function partiallySignTransaction( * @see {@link partiallySignTransaction} if you want to sign the transaction without asserting that * the resulting transaction is fully signed. */ -export async function signTransaction( +export async function signTransaction( keyPairs: CryptoKeyPair[], - transaction: T, -): Promise { + transaction: TTransaction, +): Promise { const out = await partiallySignTransaction(keyPairs, transaction); assertIsFullySignedTransaction(out); Object.freeze(out);