> ## Documentation Index
> Fetch the complete documentation index at: https://build.onswig.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Client Signing

The client does not prepare wallet operations. It only signs prepared
transactions.

## What to look for

If a prepared transaction has a non-empty `signatureRequests` /
`signature_requests` collection, the client still needs to sign it before
submission.

## Ed25519 signing

For normal Solana-key signing, use `signPreparedTransaction(...)`:

<CodeGroup dropdown>
  ```typescript TypeScript theme={null}
  import {
    signPreparedTransaction,
    type PreparedTransaction,
  } from '@swig-wallet/developer-sdk/client';
  import { VersionedTransaction } from '@solana/web3.js';

  declare const prepared: PreparedTransaction;

  const signed = await signPreparedTransaction(prepared, {
    signTransaction: async (transaction) => {
      const versioned = VersionedTransaction.deserialize(
        Buffer.from(transaction, 'base64'),
      );
      versioned.sign([userKeypair]);
      return Buffer.from(versioned.serialize()).toString('base64');
    },
  });
  ```

  ```python Python theme={null}
  from swig_developer_sdk import sign_prepared_transaction

  signed = await sign_prepared_transaction(
      prepared,
      sign_transaction=application_ed25519_signer,
  )
  ```
</CodeGroup>

## Secp256r1 and passkeys

For passkey-backed prepared transactions, use the Swig signing helpers:

<CodeGroup dropdown>
  ```typescript TypeScript theme={null}
  import {
    createSecp256r1PasskeySigningFn,
    signPreparedSwigTransaction,
  } from '@swig-wallet/developer-sdk/client';

  const passkeySigningFn = createSecp256r1PasskeySigningFn({
    allowCredentials: [{ id: credentialId, type: 'public-key' }],
    userVerification: 'preferred',
  });

  const signed = await signPreparedSwigTransaction(prepared, {
    secp256r1: passkeySigningFn,
  });
  ```

  ```python Python theme={null}
  from swig_developer_sdk import (
      create_secp256r1_passkey_signing_fn,
      sign_prepared_swig_transaction,
  )

  passkey_signing_fn = create_secp256r1_passkey_signing_fn(get_assertion)

  signed = await sign_prepared_swig_transaction(
      prepared,
      secp256r1=passkey_signing_fn,
  )
  ```
</CodeGroup>

## Secp256k1 and EVM wallets

For EVM-backed prepared transactions, use the EVM helper. It wraps an EIP-1193
provider with `personal_sign` and adds the Ethereum message prefix expected by
Swig's `secp256k1` authority payload.

<CodeGroup dropdown>
  ```typescript TypeScript theme={null}
  import {
    createSecp256k1EvmSigningFn,
    signPreparedSwigTransaction,
    type PreparedTransaction,
  } from '@swig-wallet/developer-sdk/client';

  declare const prepared: PreparedTransaction;
  declare const evmAddress: string;

  const evmSigningFn = createSecp256k1EvmSigningFn({
    provider: window.ethereum,
    address: evmAddress,
  });

  const signed = await signPreparedSwigTransaction(prepared, {
    secp256k1: evmSigningFn,
  });
  ```

  ```python Python theme={null}
  from swig_developer_sdk import (
      create_secp256k1_evm_signing_fn,
      sign_prepared_swig_transaction,
  )

  evm_signing_fn = create_secp256k1_evm_signing_fn(
      provider=evm_provider,
      address=evm_address,
  )

  signed = await sign_prepared_swig_transaction(
      prepared,
      secp256k1=evm_signing_fn,
  )
  ```
</CodeGroup>

## After signing

Once the client has signed the required transactions, your app can send them
directly or hand them to [Sponsor & Submit](/developer-sdk/sponsor-and-submit).
