Passer au contenu principal
En bref
L’API de Signature Blockradar vous permet de signer cryptographiquement des messages texte et des données structurées (données typées) à l’aide des clés privées de votre portefeuille. Les signatures prouvent la propriété du portefeuille auprès de services tiers sans déplacer de fonds ni payer de frais de réseau (gas).

Prérequis

Avant d’utiliser l’API de Signature, assurez-vous d’avoir :
1

Clé API

Obtenez votre clé API depuis le Tableau de bord Blockradar. Accédez à Developers pour en générer une.
2

Portefeuille créé

Créez un portefeuille principal depuis le Tableau de bord Blockradar. Accédez à Wallets et créez-en un pour la blockchain souhaitée. Vous aurez besoin du walletId pour les opérations de signature.
3

Environnement

Choisissez entre Testnet (pour le développement) ou Mainnet (pour la production). Les portefeuilles sont isolés par environnement.

Comment ça fonctionne

L’API de Signature produit une signature cryptographique qui prouve que vous contrôlez une adresse de portefeuille spécifique. Le résultat signé peut être vérifié par n’importe quel tiers sans accéder à vos clés privées.

Signature de message

Signez des messages texte pour prouver la propriété du portefeuille. Fonctionne sur toutes les blockchains prises en charge : EVM, Tron et Solana.

Signature de données typées

Signez des données structurées selon le standard EIP-712. Utilisé pour les approbations sans gas (EIP-2612 Permit) et les transferts autorisés (EIP-3009). EVM uniquement.

Cas d’utilisation courants

  • Inscription auprès d’un fournisseur tiers — Prouvez que vous possédez une adresse lors de l’intégration avec des services comme Iron, Circle ou d’autres protocoles DeFi
  • Approbations de tokens sans gas — Signez des messages EIP-2612 Permit pour autoriser la dépense de tokens sans transaction on-chain
  • Transferts autorisés — Signez des messages EIP-3009 TransferWithAuthorization pour des transferts délégués
  • Attestations hors chaîne — Créez des preuves vérifiables d’intention ou d’accord liées à une adresse de portefeuille

Portefeuille principal vs Adresse enfant

L’API de Signature est disponible à deux niveaux :

Portefeuille principal

Signez avec les clés du portefeuille principal. Idéal pour les opérations de trésorerie et les intégrations avec des fournisseurs.

Adresse enfant

Signez avec les clés d’une adresse enfant spécifique. À utiliser lorsque le tiers exige une signature provenant d’une adresse de dépôt.

Points de terminaison

OpérationPortefeuille principalAdresse enfant
Signer un messagePOST /v1/wallets/{walletId}/signing/messagePOST /v1/wallets/{walletId}/addresses/{addressId}/signing/message
Signer des données typéesPOST /v1/wallets/{walletId}/signing/typed-dataPOST /v1/wallets/{walletId}/addresses/{addressId}/signing/typed-data

Signature de message

Signez un message texte avec la clé privée de votre portefeuille. L’API signe le message, vérifie que la signature correspond à l’adresse du portefeuille et renvoie à la fois la signature et un enregistrement de transaction.

Blockchains prises en charge

BlockchainStandard de signatureFormat de signature
EVM (Ethereum, Polygon, BSC, Base, Arbitrum, Optimism, Celo)EIP-191 (personal_sign)Encodé en hexadécimal avec les composants r, s, v
TronTronWeb signMessageV2Chaîne encodée en hexadécimal
SolanaEd25519Chaîne encodée en Base58

Paramètres de la requête

ParamètreTypeRequisDescription
messagestringOuiLe message texte à signer. Maximum 4 096 caractères.
referencestringNonVotre identifiant de suivi interne. Utilisez-le pour l’idempotence — les références en double sont rejetées.
metadataobjectNonPaires clé-valeur personnalisées stockées avec l’enregistrement de transaction.

Exemple de signature de message

curl --request POST \
  --url https://api.blockradar.co/v1/wallets/{walletId}/signing/message \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '{
    "message": "Please sign this message to verify your wallet ownership for Iron provider registration.",
    "reference": "iron-verification-001",
    "metadata": {
      "provider": "iron",
      "purpose": "wallet-verification"
    }
  }'

Réponse EVM

{
  "message": "Message signed successfully",
  "statusCode": 200,
  "data": {
    "id": "770f9100-7338-4823-b1ce-3658fc67db09",
    "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b",
    "status": "SUCCESS",
    "type": "SIGNED",
    "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "signedTransaction": {
      "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133",
      "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3",
      "v": 27,
      "signature": "0xdb095e6cbf...b31b"
    },
    "reference": "iron-verification-001",
    "metadata": {
      "provider": "iron",
      "purpose": "wallet-verification"
    },
    "confirmed": true,
    "createdAt": "2025-03-02T19:00:52.000Z"
  }
}

Réponse Tron / Solana

Pour Tron et Solana, l’objet signedTransaction contient uniquement le champ signature (pas de composants r, s, v) :
{
  "message": "Message signed successfully",
  "statusCode": 200,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "hash": "3xYkZ9...",
    "status": "SUCCESS",
    "type": "SIGNED",
    "senderAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y",
    "recipientAddress": "TJRabPrwbZy45sbavfcjinPJC18kjpRT9Y",
    "signedTransaction": {
      "signature": "3xYkZ9..."
    },
    "reference": "tron-verification-001",
    "confirmed": true,
    "createdAt": "2025-03-02T19:00:52.000Z"
  }
}

Champs de la réponse

ChampDescription
idIdentifiant unique de la transaction pour l’enregistrement de signature
hashLa signature cryptographique. Pour EVM : chaîne hexadécimale. Pour Tron : chaîne hexadécimale. Pour Solana : chaîne base58.
statusToujours SUCCESS pour les signatures complétées
typeToujours SIGNED pour les transactions de signature
senderAddressL’adresse du portefeuille qui a produit la signature
signedTransactionComposants de la signature. EVM inclut r, s, v et la signature complète. Tron et Solana incluent uniquement signature.
referenceVotre chaîne de référence fournie (le cas échéant)
metadataVotre objet de métadonnées fourni (le cas échéant)

Signature de données typées (EVM uniquement)

Signez des données structurées selon le standard EIP-712. Ceci est utilisé pour les approbations sans gas, les transferts délégués et d’autres flux d’autorisation on-chain nécessitant une signature structurée.
La signature de données typées est uniquement disponible pour les blockchains compatibles EVM (Ethereum, Polygon, BSC, Base, Arbitrum, Optimism, Celo). Tron et Solana ne prennent pas en charge EIP-712.

Standards pris en charge

StandardCas d’utilisation
EIP-712Signature générique de données structurées
EIP-2612 (Permit)Approbations de tokens sans gas — approuver la dépense sans transaction on-chain
EIP-3009 (TransferWithAuthorization)Transferts délégués — autoriser un transfert qu’un tiers soumet

Paramètres de la requête

ParamètreTypeRequisDescription
domainobjectOuiSéparateur de domaine EIP-712. Inclut name, version, chainId et verifyingContract.
typesobjectOuiDéfinitions de types pour les données structurées.
messageobjectOuiLes données à signer, conformes aux définitions de types.

Exemple EIP-2612 Permit

curl --request POST \
  --url https://api.blockradar.co/v1/wallets/{walletId}/signing/typed-data \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '{
    "domain": {
      "name": "USD Coin",
      "version": "2",
      "chainId": 11155111,
      "verifyingContract": "0xa0b86a33e6441b8c4c8c0c077bcdd28571685701"
    },
    "types": {
      "Permit": [
        { "name": "owner", "type": "address" },
        { "name": "spender", "type": "address" },
        { "name": "value", "type": "uint256" },
        { "name": "nonce", "type": "uint256" },
        { "name": "deadline", "type": "uint256" }
      ]
    },
    "message": {
      "owner": "0x742d35cc6634c0532925a3b8d4c9db96c4b4d8b6",
      "spender": "0x8ba1f109551bd432803012645aac136c4c8c8c0c",
      "value": "1000000000",
      "nonce": "0",
      "deadline": "1641081600"
    }
  }'

Réponse des données typées

{
  "message": "Typed data signed successfully",
  "statusCode": 200,
  "data": {
    "id": "770f9100-7338-4823-b1ce-3658fc67db09",
    "hash": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e21335aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b31b",
    "status": "SUCCESS",
    "type": "SIGNED",
    "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "signedTransaction": {
      "r": "0xdb095e6cbf235d630cee43e0953e60c351e46897bc4e65abfce3e975810e2133",
      "s": "0x5aa3918399dac1e01badb2dc8c59c171e65d0c328c92737de702da9d76b889b3",
      "v": 27,
      "signature": "0xdb095e6cbf...b31b"
    },
    "confirmed": true,
    "createdAt": "2025-03-02T19:00:52.000Z"
  }
}

Champs de l’objet domaine

ChampTypeRequisDescription
namestringOuiLe nom du domaine de signature (par ex., le nom du token ou de la dApp)
versionstringOuiLa version du domaine
chainIdnumberOuiL’identifiant de la chaîne. Doit correspondre au réseau blockchain du portefeuille.
verifyingContractstringOuiL’adresse du contrat qui vérifiera la signature
saltstringNonSel de domaine optionnel pour EIP-712 v4
Validation du Chain ID
Le chainId dans votre objet domaine doit correspondre à l’identifiant de chaîne du réseau blockchain du portefeuille. S’ils ne correspondent pas, l’API renvoie une erreur 400 Chain ID mismatch.

Signature avec une adresse enfant

Signez des messages ou des données typées en utilisant une adresse enfant spécifique au lieu du portefeuille principal :
curl --request POST \
  --url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/signing/message \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <api-key>' \
  --data '{
    "message": "Verify ownership of deposit address for provider onboarding.",
    "reference": "address-verify-001"
  }'
La signature avec une adresse enfant suit le même format de requête et de réponse que la signature avec le portefeuille principal. La seule différence est l’URL du point de terminaison, qui inclut le addressId.

Événements webhook

Les opérations de signature déclenchent un webhook avec l’enregistrement de transaction :
ÉvénementDescription
signed.successMessage ou données typées signés et vérifiés

Contenu du webhook

{
  "event": "signed.success",
  "data": {
    "id": "770f9100-7338-4823-b1ce-3658fc67db09",
    "hash": "0xdb095e6cbf...b31b",
    "status": "SUCCESS",
    "type": "SIGNED",
    "senderAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "recipientAddress": "0x947514e4B803e312C312da0F1B41fEDdbe15ae7a",
    "signedTransaction": {
      "r": "0xdb095e6cbf...2133",
      "s": "0x5aa3918399...89b3",
      "v": 27,
      "signature": "0xdb095e6cbf...b31b"
    },
    "reference": "iron-verification-001",
    "metadata": {
      "provider": "iron",
      "purpose": "wallet-verification"
    },
    "wallet": {
      "id": "d236a191-c1d4-423c-a439-54ce6542ca41",
      "name": "Ethereum Master Wallet"
    },
    "blockchain": {
      "name": "ethereum",
      "network": "testnet"
    },
    "confirmed": true,
    "createdAt": "2025-03-02T19:00:52.000Z"
  }
}

Exemple de flux complet

Voici une implémentation complète pour signer un message et soumettre la signature à un fournisseur tiers :
async function signAndVerifyWithProvider(walletId, providerMessage) {
  const apiKey = process.env.BLOCKRADAR_API_KEY;
  const baseUrl = 'https://api.blockradar.co/v1';

  // Step 1: Sign the message
  const signResponse = await fetch(
    `${baseUrl}/wallets/${walletId}/signing/message`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({
        message: providerMessage,
        reference: `provider-verify-${Date.now()}`
      })
    }
  ).then(r => r.json());

  if (signResponse.statusCode !== 200) {
    throw new Error(`Signing failed: ${signResponse.message}`);
  }

  const { hash, senderAddress } = signResponse.data;

  // Step 2: Submit the signature to the third-party provider
  // The provider can verify the signature matches the wallet address
  // without accessing your private keys
  return {
    address: senderAddress,
    signature: hash,
    message: providerMessage
  };
}

// Usage
signAndVerifyWithProvider(
  'wallet-uuid',
  'I authorize Iron to manage assets on my behalf.'
);

Réponses d’erreur

{
  "message": "Wallet not found",
  "statusCode": 404
}
Le walletId n’existe pas ou n’appartient pas à votre entreprise.
{
  "message": "Address not found",
  "statusCode": 404
}
Le addressId n’existe pas ou n’est pas associé au portefeuille spécifié.
{
  "message": "Typed data signing is only supported for EVM blockchains",
  "statusCode": 400
}
La signature de données typées (EIP-712) est uniquement disponible sur les chaînes compatibles EVM. Utilisez la signature de message pour Tron et Solana.
{
  "message": "Chain ID mismatch",
  "statusCode": 400
}
Le chainId dans votre objet domaine de données typées ne correspond pas au réseau blockchain du portefeuille.
{
  "message": "Signature verification failed",
  "statusCode": 400
}
La vérification aller-retour interne a échoué. Cela indique une erreur système — contactez le support.

Bonnes Pratiques

Sécurité

  • Utilisez des références — Suivez les opérations de signature avec des identifiants de référence uniques pour les pistes d’audit et l’idempotence
  • Vérifiez le message — Avant de signer, confirmez que le contenu du message correspond à ce que le service tiers attend
  • Limitez la longueur du message — Les messages sont limités à 4 096 caractères. Gardez les messages concis et spécifiques

Intégration

  • Pas de frais de gas — Les opérations de signature sont hors chaîne et ne nécessitent pas de solde en tokens natifs
  • Réponse immédiate — Les signatures sont générées de manière synchrone. Aucun polling ou attente de webhook n’est nécessaire pour la signature elle-même
  • Écoutez les webhooks — Utilisez les webhooks pour maintenir une piste d’audit de tous les événements de signature

Données typées

  • Faites correspondre les Chain IDs — Le chainId dans votre domaine doit correspondre au réseau du portefeuille. Utilisez les Chain IDs sandbox (testnet) pour les tests et les Chain IDs de production (mainnet) pour les opérations en direct
  • Vérifiez le contrat — Le verifyingContract doit être le contrat qui vérifiera la signature on-chain

Référence API

Points de terminaison du portefeuille principal

Point de terminaisonDescription
Signer un messageSigner un message texte
Signer des données typéesSigner des données structurées EIP-712

Points de terminaison de l’adresse enfant

Point de terminaisonDescription
Signer un messageSigner un message texte depuis une adresse enfant
Signer des données typéesSigner des données structurées EIP-712 depuis une adresse enfant