Skip to main content
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:
  1. Created a Portal client
  2. 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:
FieldTypeRequiredDescription
sharestringYesThe JSON-serialized MPC share for the wallet.
expirationTsnumberNoUnix 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>"
}
FieldTypeDescription
idstringUnique identifier for the presignature.
expiresAtstringRFC 3339 expiration timestamp.
datastringOpaque 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>"
  }'
FieldTypeRequiredDescription
sharestringYesThe JSON-serialized MPC share.
paramsstringYesHex digest string to sign, without a 0x prefix.
presignaturestringYesThe data value from the presign response.
signingSchemestringNo"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"
  }'
FieldTypeRequiredDescription
sharestringYesThe JSON-serialized MPC share.
presignaturestringNoThe data value from the presign response. Omit for standard (non-presigned) signing.
methodstringYesRPC method (e.g., eth_sendTransaction, personal_sign).
paramsstring/object/arrayYesRPC parameters for the transaction.
rpcUrlstringYesRPC endpoint URL.
chainIdstringYesCAIP-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"
  }'
FieldTypeRequiredDescription
sharestringYesThe JSON-serialized MPC share.
presignaturestringNoThe data value from the presign response.
chainstringYesChain name or CAIP-2 ID (e.g., monad-testnet).
tostringYesRecipient address.
tokenstringYesToken identifier or "NATIVE" for native transfers.
amountstringYesAmount as a numeric string.
rpcUrlstringNoRPC 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