Skip to content

Commit

Permalink
refactor(experimental): assert single sending signer inside signAndSe…
Browse files Browse the repository at this point in the history
…nd function (#2852)

Fixes #2818

This PR calls the `assertIsTransactionMessageWithSingleSendingSigner` inside the `signAndSendTransactionMessageWithSigners` so the end-user doesn't need to do it explicitly.

This is partly to improve the developer experience and partly because TS doesn't fail properly when the transaction message hasn't been asserted on prior to calling the sign and send function.

Note that I did not remove the `assertIsTransactionMessageWithSingleSendingSigner` and the `isTransactionMessageWithSingleSendingSigner` from the package's exports since they may still be useful for custom use-cases such as the one described in the documentation:

```ts
let transactionSignature: SignatureBytes;
if (isTransactionMessageWithSingleSendingSigner(transaction)) {
    transactionSignature = await signAndSendTransactionMessageWithSigners(transaction);
} else {
    const signedTransaction = await signTransactionMessageWithSigners(transaction);
    const encodedTransaction = getBase64EncodedWireTransaction(signedTransaction);
    transactionSignature = await rpc.sendTransaction(encodedTransaction).send();
}
```
  • Loading branch information
lorisleiva authored Jun 26, 2024
1 parent 53b60c9 commit cec9048
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 6 deletions.
5 changes: 5 additions & 0 deletions .changeset/short-jokes-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solana/signers': patch
---

The `signAndSendTransactionMessageWithSigners` function now automatically asserts that the provided transaction message contains a single sending signer and fails otherwise.
4 changes: 2 additions & 2 deletions packages/signers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -549,9 +549,9 @@ Here as well, composite transaction signers are treated such that at least one s
- `TransactionModifyingSigner`, if no other `TransactionModifyingSigner` exists.
- `TransactionPartialSigner`, otherwise.

The provided transaction must be of type `ITransactionWithSingleSendingSigner` meaning that it must contain exactly one `TransactionSendingSigner` inside its account metas. If more than one composite signers implement the `TransactionSendingSigner` interface, one of them will be selected as the sending signer.
The provided transaction must contain exactly one `TransactionSendingSigner` inside its account metas. If more than one composite signers implement the `TransactionSendingSigner` interface, one of them will be selected as the sending signer. Otherwise, if multiple `TransactionSendingSigners` must be selected, the function will throw an error.

Therefore, you may use the `assertIsTransactionWithSingleSendingSigner()` function to ensure the transaction is of the expected type.
If you'd like to assert that a transaction makes use of exactly one `TransactionSendingSigner` _before_ calling this function, you may use the `assertIsTransactionWithSingleSendingSigner` function.

```ts
assertIsTransactionWithSingleSendingSigner(myTransaction);
Expand Down
8 changes: 4 additions & 4 deletions packages/signers/src/sign-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { isTransactionModifyingSigner, TransactionModifyingSigner } from './tran
import { isTransactionPartialSigner, TransactionPartialSigner } from './transaction-partial-signer';
import { isTransactionSendingSigner, TransactionSendingSigner } from './transaction-sending-signer';
import { isTransactionSigner, TransactionSigner } from './transaction-signer';
import { ITransactionMessageWithSingleSendingSigner } from './transaction-with-single-sending-signer';
import { assertIsTransactionMessageWithSingleSendingSigner } from './transaction-with-single-sending-signer';

type CompilableTransactionMessageWithSigners = CompilableTransactionMessage & ITransactionMessageWithSigners;

Expand Down Expand Up @@ -123,10 +123,10 @@ export async function signTransactionMessageWithSigners<
* Otherwise, it will send the transaction using the provided fallbackSender.
*/
export async function signAndSendTransactionMessageWithSigners<
TTransactionMessage extends CompilableTransactionMessageWithSigners &
ITransactionMessageWithSingleSendingSigner = CompilableTransactionMessageWithSigners &
ITransactionMessageWithSingleSendingSigner,
TTransactionMessage extends CompilableTransactionMessageWithSigners = CompilableTransactionMessageWithSigners,
>(transaction: TTransactionMessage, config: { abortSignal?: AbortSignal } = {}): Promise<SignatureBytes> {
assertIsTransactionMessageWithSingleSendingSigner(transaction);

const abortSignal = config.abortSignal;
const { partialSigners, modifyingSigners, sendingSigner } = categorizeTransactionSigners(
deduplicateSigners(getSignersFromTransactionMessage(transaction).filter(isTransactionSigner)),
Expand Down

0 comments on commit cec9048

Please sign in to comment.