## TransactionMessage Requirements

In order to be signable, a `TransactionMessage` must:

- have a version and a list of zero or more instructions (ie. conform to `BaseTransactionMessage`)
- have a fee payer set (ie. conform to `TransactionMessageWithFeePayer`)
- have a lifetime specified (ie. conform to `TransactionMessageWithBlockhashLifetime | TransactionMessageWithDurableNonceLifetime`)

On the client, signers abstract the interface to sign transactions.

A signer is an interface that hides the implementation details of a specific signer (like a wallet in the browser).

```typescript
await mySigner.signTransactions([myTransaction]);
```

Usually we construct the transaction by building up a bunch of instructions:

```typescript
import { pipe } from "@solana/functional";
import { createTransactionMessage } from "@solana/transaction-messages";
import { compileTransaction } from "@solana/transactions";

const myTransactionMessage = pipe(
    createTransactionMessage({ version: 0 }),
    // Add instructions, fee payer, lifetime, etc.
);
const myTransaction = compileTransaction(myTransactionMessage);
const [transactionSignatures] = await mySigner.signTransactions([myTransaction]);
```

### Categories of Signers
There are 3 categories of signers:

- **Partial signers**: Given a message or transaction, provide one or more signatures for it. These signers are not able to modify the given data which allows us to run many of them in parallel.
- **Modifying signers**: Can choose to modify a message or transaction before signing it with zero or more private keys. Because modifying a message or transaction invalidates any pre-existing signatures over it, modifying signers must do their work before any other signer.
- **Sending signers**: Given a transaction, signs it and sends it immediately to the blockchain. When applicable, the signer may also decide to modify the provided transaction before signing it. This interface accommodates wallets that simply cannot sign a transaction without sending it at the same time. This category of signers does not apply to regular messages.

### Signer Types Table
Here is a table of the various signer types for both messages and transactions.

|  | Partial signers | Modifying signers | Sending signers |
| --- | --- | --- | --- |
| `TransactionSigner` | `TransactionPartialSigner` | `TransactionModifyingSigner` | `TransactionSendingSigner` |
| `MessageSigner` | `MessagePartialSigner` | `MessageModifyingSigner` | N/A |

Signers can be stored inside of the account meta of an instruction. This helps avoid passing them around as plain old addresses.

### Creating Signable Messages
To sign something we need at least a signable message:

```typescript
import { createSignableMessage } from "@solana/kit"

const myMessage = createSignableMessage(new Uint8Array([1, 2, 3]));
const myMessageFromText = createSignableMessage('Hello world!');
const myMessageWithSignatures = createSignableMessage('Hello world!', {
    '1234..5678': new Uint8Array([1, 2, 3]),
});
```

A message is just a recent blockhash, a list of accounts and a corresponding list of instructions.

Usually though you would be signing an actual `Transaction` which is a message and a list of signers.

### Union Types for Signers
Most of the time you will be working with the union types:

```typescript
type MessageSigner<TAddress extends string = string> =
    | MessagePartialSigner<TAddress>
    | MessageModifyingSigner<TAddress>;

type TransactionSigner<TAddress extends string = string> =
    | TransactionPartialSigner<TAddress>
    | TransactionModifyingSigner<TAddress>
    | TransactionSendingSigner<TAddress>;
```

Most of the time in our tests we are using a `KeyPairSigner`

```typescript
import { generateKeyPair } from "@solana/keys";
import { createSignerFromKeyPair, KeyPairSigner } from "@solana/signers";

const myKeyPair: CryptoKeyPair = await generateKeyPair();
const myKeyPairSigner: KeyPairSigner = await createSignerFromKeyPair(myKeyPair);
```

And even more likely we would use the helper:

```typescript
import { generateKeyPairSigner } from "@solana/signers";

const myKeyPairSigner = await generateKeyPairSigner();
```
