Presignatures let you front-load part of the MPC computation so that subsequent signing completes faster. For a general overview, see the Presignatures resource.
This guide walks through creating a presignature and using it with the sign, raw sign, and send asset endpoints.
Prerequisites
Before starting, make sure you have:
- Created a Portal client
- Created a wallet and have access to the
share data
Step 1: Create a Presignature
Call the presign endpoint with your share to generate a presignature.
Presignatures currently only support the SECP256K1 curve (EVM, Bitcoin). ED25519 (Solana) support is coming soon.
curl --request POST \
--url https://mpc-client.portalhq.io/v1/presign/SECP256K1 \
--header 'Authorization: Bearer <clientApiKey>' \
--header 'Content-Type: application/json' \
--data '{
"share": "<SECP256K1_SHARE>"
}'
Request body:
| Field | Type | Required | Description |
|---|
share | string | Yes | The JSON-serialized MPC share for the wallet. |
expirationTs | number | No | Unix timestamp for when the presignature expires. Defaults to 7 days. Max 365 days. |
Response:
{
"id": "presig-uuid-123",
"expiresAt": "2025-03-18T10:00:00Z",
"data": "<PRESIGNATURE_DATA>"
}
| Field | Type | Description |
|---|
id | string | Unique identifier for the presignature. |
expiresAt | string | RFC 3339 expiration timestamp. |
data | string | Opaque presignature payload. Pass this as the presignature field in signing requests. |
Store the data value from the response — you will pass it as the presignature field in the next step. It is also recommended to store the id and expiresAt values for bookkeeping purposes. The id may be needed when communicating with Portal support.
Step 2: Use the Presignature
Pass the presignature data value in the presignature field of any compatible signing endpoint.
Raw Sign
Sign an arbitrary hex digest string with a presignature.
curl --request POST \
--url https://mpc-client.portalhq.io/v1/raw/sign/SECP256K1 \
--header 'Authorization: Bearer <clientApiKey>' \
--header 'Content-Type: application/json' \
--data '{
"params": "<HEX_DIGEST_STRING>",
"presignature": "<PRESIGNATURE_DATA>",
"share": "<SECP256K1_SHARE>"
}'
| Field | Type | Required | Description |
|---|
share | string | Yes | The JSON-serialized MPC share. |
params | string | Yes | Hex digest string to sign, without a 0x prefix. |
presignature | string | Yes | The data value from the presign response. |
signingScheme | string | No | "cggmp" (default) or "frost". |
The curve in the URL path (e.g., /SECP256K1) must match the curve used when creating the presignature.
Sign (RPC-based)
Use a presignature with the RPC-based sign endpoint for blockchain transactions.
curl --request POST \
--url https://mpc-client.portalhq.io/v1/sign \
--header 'Authorization: Bearer <clientApiKey>' \
--header 'Content-Type: application/json' \
--data '{
"share": "<SECP256K1_SHARE>",
"presignature": "<PRESIGNATURE_DATA>",
"method": "eth_sendTransaction",
"params": {"value": "0x01", "from": "YOUR_ETH_ADDRESS", "to": "RECIPIENT_ADDRESS", "data": ""},
"rpcUrl": "YOUR_RPC_URL",
"chainId": "eip155:10143"
}'
| Field | Type | Required | Description |
|---|
share | string | Yes | The JSON-serialized MPC share. |
presignature | string | No | The data value from the presign response. Omit for standard (non-presigned) signing. |
method | string | Yes | RPC method (e.g., eth_sendTransaction, personal_sign). |
params | string/object/array | Yes | RPC parameters for the transaction. |
rpcUrl | string | Yes | RPC endpoint URL. |
chainId | string | Yes | CAIP-2 chain ID (e.g., eip155:10143). |
Send Assets
Use a presignature with the high-level send assets endpoint.
curl --request POST \
--url https://mpc-client.portalhq.io/v1/assets/send \
--header 'Authorization: Bearer <clientApiKey>' \
--header 'Content-Type: application/json' \
--data '{
"share": "<SECP256K1_SHARE>",
"presignature": "<PRESIGNATURE_DATA>",
"rpcUrl": "https://api.portalhq.io/rpc/v1/eip155/10143",
"chain": "monad-testnet",
"to": "0xDestinationAddress",
"token": "NATIVE",
"amount": "0.0001"
}'
| Field | Type | Required | Description |
|---|
share | string | Yes | The JSON-serialized MPC share. |
presignature | string | No | The data value from the presign response. |
chain | string | Yes | Chain name or CAIP-2 ID (e.g., monad-testnet). |
to | string | Yes | Recipient address. |
token | string | Yes | Token identifier or "NATIVE" for native transfers. |
amount | string | Yes | Amount as a numeric string. |
rpcUrl | string | No | RPC endpoint URL. |
Important Notes
- Single-use: Each presignature can only be used once. After signing, you must create a new one.
- Active limit: You can have up to 100 active presignatures per client. Set up a regular process to discard expired presignatures.
- Curve matching: For raw sign, the presignature’s curve must match the URL path curve.
- Expiration: Presignatures expire after their
expiresAt timestamp. The default is 7 days; the maximum is 365 days.
Additional Resources