NERO
Wallets

Signing Messages

Sign personal messages (EIP-191) and EIP-712 typed data using threshold ECDSA

Signing Messages

The Nero MPC SDK signs messages using threshold cryptography where the full private key is never reconstructed on the client device during normal operation. Both DKLS (2-party threshold ECDSA) and Pedersen (DKG with ERC-4337) protocols are supported.

Dual-Protocol Signing Architecture

ProtocolImplementationAccount Type
dklsDKLSClientEOA (Externally Owned Account)
pedersenSmartWallet via SigningClientSmart Account (ERC-4337)

The protocol selection in your SDK configuration determines which signing path is taken for all operations.

Personal Messages (EIP-191)

Message signing implements the Ethereum personal_sign standard, which prefixes messages with "\x19Ethereum Signed Message:\n" + len(message) before hashing. Both protocols support raw string and Uint8Array message inputs.

const message = "Hello, NERO!";
const signature = await sdk.signMessage(message);

DKLS path: Converts the message to a string if it's a Uint8Array, then delegates to DKLSClient.signMessage().

Pedersen path: Uses SmartWallet.signMessage(), which internally coordinates with the backend using a SigningClient.

Typed Data (EIP-712)

Sign structured data with domain separation:

const typedData = {
  types: {
    EIP712Domain: [
      { name: "name", type: "string" },
      { name: "version", type: "string" },
      { name: "chainId", type: "uint256" },
    ],
    Transfer: [
      { name: "to", type: "address" },
      { name: "amount", type: "uint256" },
    ],
  },
  primaryType: "Transfer",
  domain: {
    name: "MyApp",
    version: "1",
    chainId: 689,
  },
  message: {
    to: "0x1234...",
    amount: "1000000000000000000",
  },
};

const signature = await sdk.signTypedData(typedData);

DKLS path: Delegates to DKLSClient.signTypedData(), which performs EIP-712 encoding before generating the signature.

Pedersen path: Uses SmartWallet.signTypedData(), following the same MPC coordination pattern as message signing but with EIP-712 encoding.

Signature Format

All signing methods return signatures as hex-encoded strings in the format 0x<r><s><v>.

Signatures conform to the Signature interface:

FieldDescription
rFirst 32 bytes of the signature
sSecond 32 bytes of the signature
vRecovery identifier
fullSignatureComplete hex-encoded signature string

EIP-1193 Provider Integration

The SDK exposes an EIP-1193 compatible provider for signing through standard Web3 libraries:

const provider = sdk.getProvider();

// personal_sign: converts hex or UTF-8 messages to bytes
await provider.request({
  method: "personal_sign",
  params: [message, address],
});

// eth_signTypedData_v4: parses JSON typed data
await provider.request({
  method: "eth_signTypedData_v4",
  params: [address, JSON.stringify(typedData)],
});

With ethers.js

import { BrowserProvider } from "ethers";

const ethersProvider = new BrowserProvider(sdk.getProvider());
const signer = await ethersProvider.getSigner();
const signature = await signer.signMessage("Hello, NERO!");

With viem

import { createWalletClient, custom } from "viem";

const client = createWalletClient({
  transport: custom(sdk.getProvider()),
});

Error Handling

Error CodeScenarioThrown By
NO_WALLETSigning attempted before wallet creationSDK signing method guards
INVALID_NONCE_COMMITMENTBackend provided malformed nonceSigningClient validation
INVALID_PARTIAL_SIGNATUREBackend partial signature verification failedSigningClient verification logic

Security Model

  1. No Full Key Reconstruction: During signing operations, the full private key is never reconstructed on the client. Only partial signatures are computed locally.
  2. Share Protection: Client shares are stored encrypted in IndexedDBStorage or MemoryStorage using a device-specific key.

The threshold signature protocol ensures that neither party alone can forge signatures without the other's participation, maintaining non-custodial security while enabling responsive UX through client-side partial signature generation.

On this page