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

# Sign a transaction

> Easily use our EIP-1193 provider or custom built functions to make sending and signing transactions easier!

## Signing

### Improving signing performance

You can reduce signing latency for EVM transactions by enabling **presignatures**. The SDK will then pre-compute part of the MPC signing flow in the background and use that data when the user signs, without any change to your code. Enable it via the `usePresignatures` feature flag when creating your `Portal` instance. See [Feature flags](/sdks/web/guide/feature-flags#usepresignatures) for details.

The `Portal` instance includes a number of helper functions to allow you to execute `Provider` requests without having to worry about encoding, request format, or what method to pass in your request. These helper functions allows you to easily sign and submit transactions, sign messages, and even sign typed data.

```typescript theme={null}
const chainId = 'eip155:1' // Ethereum Mainnet
const myAddress = await portal.getEip155Address() // Your Ethereum address
const messageToSign = "0x48656c6c6f20576f726c64" // Message must be a hex string

const signature = await portal.request({
    chainId,
    method: 'eth_sign',
    params: [myAddress, messageToSign],
    signatureApprovalMemo: 'Optional memo shown during approval', // optional
})
```

### Signature approval memo

Clients can pass an optional **`signatureApprovalMemo`** so the user sees a short description during the approval flow. It is supported in:

* **`portal.request()`** — add `signatureApprovalMemo` to any signing method (`eth_sendTransaction`, `personal_sign`, `sol_signAndSendTransaction`, etc.).
* **`portal.sendAsset(chain, params)`** — include `signatureApprovalMemo` in the `params` object. See [Send tokens](./send-tokens#advanced-controlling-gas-sponsorship).
* **`portal.rawSign(curve, param, options)`** — pass an optional third argument with the memo.

**Example: request with memo**

```typescript theme={null}
const txHash = await portal.request({
  chainId: 'eip155:1',
  method: 'eth_sendTransaction',
  params: [transaction],
  signatureApprovalMemo: 'Send transaction',
})
```

**Example: rawSign with memo**

```typescript theme={null}
const signature = await portal.rawSign(
  PortalCurve.SECP256K1,
  messageHex,
  { signatureApprovalMemo: 'Sign login challenge' }
)
```

### Signing a User Operation

If your client uses [Account Abstraction](../../../resources/account-abstraction), you can sign an [ERC-4337 User Operation](https://eips.ethereum.org/EIPS/eip-4337) using the `eth_signUserOperation` method. This signs the User Operation without submitting it on-chain, returning the signature directly.

```typescript theme={null}
const chainId = 'eip155:11155111' // Ethereum Sepolia

try {
  const address = await portal.getEip155Address()
  if (!address) {
    throw new Error('Wallet address not found')
  }

  const userOp = {
    sender: address,
    nonce: '0x0',
    callData: '0x',
    callGasLimit: '0x5208',
    verificationGasLimit: '0x5208',
    preVerificationGas: '0x5208',
    maxFeePerGas: '0x1',
    maxPriorityFeePerGas: '0x1',
  }
  const signature = await portal.request({
    chainId,
    method: 'eth_signUserOperation',
    params: [userOp],
  })

  console.log('✅ Signature:', signature)
} catch (error) {
  console.error('❌ Failed to sign UserOperation:', error)
}
```

**User Operation Parameters:**

| Name                   | Type     | Description                                                                   |
| ---------------------- | -------- | ----------------------------------------------------------------------------- |
| `sender`               | `String` | The address of the smart contract account                                     |
| `nonce`                | `String` | Anti-replay parameter (hex-encoded)                                           |
| `callData`             | `String` | The data to pass to the `sender` during the main execution call (hex-encoded) |
| `callGasLimit`         | `String` | Gas limit for the main execution call (hex-encoded)                           |
| `verificationGasLimit` | `String` | Gas limit for the verification step (hex-encoded)                             |
| `preVerificationGas`   | `String` | Gas paid for pre-verification (hex-encoded)                                   |
| `maxFeePerGas`         | `String` | Maximum fee per unit of gas (hex-encoded)                                     |
| `maxPriorityFeePerGas` | `String` | Maximum priority fee per unit of gas (hex-encoded)                            |

You can also pass a signature approval memo and control gas sponsorship:

```typescript theme={null}
const signature = await portal.request({
  chainId: 'eip155:11155111',
  method: 'eth_signUserOperation',
  params: [userOp],
  signatureApprovalMemo: 'Approve UserOp',
  sponsorGas: true,
})
```

## Raw Requests with the Provider

## Estimating Gas

By default, Portal will estimate and populate the `gas` property in a `transaction` object if the property is undefined.

To estimate the `gas` value manually use the `eth_estimateGas` RPC call and pass in your transaction as the parameter.

```javascript theme={null}
const gas = await portal.request({
    chainId: 'eip155:1',
    method: 'eth_estimateGas',
    params: [
        // partial transaction to estimate gas for
        {
            from:"0xFROMADDRESS",
            to:"0xTOADDRESS",
            value:"0xVALUE",
            input:"HASH_OF_CONTRACT_CALL_DATA", // only needed if calling a smart contract
        }
    ]
})

console.log(gas)
// "0x5208"
```

And now you are signing transactions with Portal! 🙌 🚀 Next, we'll explore how to simulate a transaction so that you can create smoother experiences for your users.
