> **Can't find what you're looking for?** Use `search_docs` on the docs MCP server at `https://www.openfort.io/api/mcp` to find what you need.
>
> **Have feedback?** Use `submit_feedback` on the same MCP server.

# Sign message

Call the connected Solana provider with a UTF-8 string. The provider returns a base58-encoded Ed25519 signature. Signing happens off-chain — it costs no SOL and broadcasts nothing to the cluster.

## Parameters

| Parameter | Type | Description |
| :--- | :--- | :--- |
| `message` | `string` | The message to sign. Ed25519 signs the raw bytes, so there is no hashing option to configure. |

## Return value

`Promise<string>` — the signature, base58 encoded. The key that produced it is `solana.provider.publicKey`, which is the active wallet's address.

## Usage

`provider` is only defined while `status` is `'connected'`, so gate on the status before signing.

```tsx
import { useSolanaEmbeddedWallet } from '@openfort/react/solana'

function SignSolanaMessage() {
  const solana = useSolanaEmbeddedWallet()

  const handleSignMessage = async () => {
    if (solana.status !== 'connected') return

    const signature = await solana.provider.signMessage('Hello from Openfort!')
    console.log('Signature:', signature)   // base58 string
    console.log('Signed by:', solana.provider.publicKey)
  }

  return (
    <button
      onClick={() => void handleSignMessage()}
      disabled={solana.status !== 'connected'}
    >
      Sign message
    </button>
  )
}
```

The provider also exposes an EIP-1193-style `request` method for the same operation, which resolves to an object instead of a bare string:

```tsx
const { signature } = await solana.provider.request({
  method: 'signMessage',
  params: { message: 'Hello from Openfort!' },
})
```

## Errors

Provider methods reject on failure — they don't resolve to `{ error }` the way the hook's `create` and `setActive` actions do. Catch the rejection and read `shortMessage` for text you can show a user.

```tsx
import { OpenfortError, WalletNotConnectedError } from '@openfort/react'

try {
  const signature = await solana.provider.signMessage('Hello from Openfort!')
} catch (error) {
  if (error instanceof WalletNotConnectedError) {
    // The active wallet changed, or the wallet session ended, before the signature ran.
  }
  if (error instanceof OpenfortError) console.error(error.shortMessage)
}
```

Signer work runs on a serial queue per client, so a signature waits behind any send or recovery already in flight. An operation that never settles is cut off after five minutes with a `WalletNotConnectedError`, which is safe to retry.

## Related

* [Send transaction (Solana)](https://www.openfort.io/docs/products/embedded-wallet/react/wallet/actions/send-transaction/solana) — for transaction message bytes, use `provider.signTransaction({ messageBytes })` instead of `signMessage`.
* [useSolanaEmbeddedWallet](https://www.openfort.io/docs/products/embedded-wallet/react/hooks/useSolanaEmbeddedWallet) — the hook that exposes `status`, `activeWallet`, and `provider`.
* [Sign message (Ethereum)](https://www.openfort.io/docs/products/embedded-wallet/react/wallet/actions/sign-message) — `personal_sign` and EIP-712 typed data through the confirmation modal.
