Skip to main content
Allow your users to delegate a portion of their USDB rewards to another wallet. Useful for revenue-sharing arrangements, referral programs, or pooling rewards to a treasury.

How It Works

A wallet owner signs a message authorizing 1-100% of their BTC rewards to flow to a delegate pubkey. The delegation remains active until explicitly revoked. Constraints:
  • One active delegation per wallet
  • Cannot delegate to yourself
  • Percentage must be 1-100
  • Signed messages expire after 5 minutes

Message Formats

Delegation:
flashnet:delegate:v1:{delegatePubkey}:{percentage}:{nonce}
Revoke:
flashnet:revoke:v1:{nonce}
The nonce is a Unix timestamp in milliseconds (Date.now()). Messages are valid for 5 minutes from the nonce timestamp.

API Reference

Check if a wallet has an active delegation.Response (no delegation):
{ "active": false }
Response (active delegation):
{
  "active": true,
  "delegatePubkey": "03abc...",
  "percentage": 50,
  "createdAt": "2025-01-14T12:00:00.000Z"
}
Create or update a delegation. Replaces any existing delegation.Request body:
{
  "delegatorPubkey": "03abc...",
  "delegatePubkey": "02def...",
  "percentage": 50,
  "message": "flashnet:delegate:v1:02def...:50:1705233600000",
  "signature": "304402..."
}
Response:
{ "success": true, "delegationId": 123 }
Revoke an active delegation.Request body:
{
  "delegatorPubkey": "03abc...",
  "message": "flashnet:revoke:v1:1705233600000",
  "signature": "304402..."
}
Response:
{ "success": true, "delegationId": 123 }

Code Example

import { SparkWallet } from "@buildonspark/spark-sdk";

async function delegateRewards(
  wallet: SparkWallet,
  delegatePubkey: string,
  percentage: number
) {
  const delegatorPubkey = await wallet.getIdentityPublicKey();
  const nonce = Date.now();
  const message = `flashnet:delegate:v1:${delegatePubkey}:${percentage}:${nonce}`;

  const signature = await wallet.signMessageWithIdentityKey(message);

  const response = await fetch("https://rewards.flashnet.xyz/v1/delegation", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      delegatorPubkey,
      delegatePubkey,
      percentage,
      message,
      signature,
    }),
  });

  return response.json();
}

async function revokeDelegation(wallet: SparkWallet) {
  const delegatorPubkey = await wallet.getIdentityPublicKey();
  const nonce = Date.now();
  const message = `flashnet:revoke:v1:${nonce}`;

  const signature = await wallet.signMessageWithIdentityKey(message);

  const response = await fetch("https://rewards.flashnet.xyz/v1/delegation/revoke", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      delegatorPubkey,
      message,
      signature,
    }),
  });

  return response.json();
}

Error Responses

StatusErrorCause
400Invalid delegatorPubkey format invalid (must be 66-char hex)
400Invalid delegateDelegate pubkey format invalid
400Invalid message formatMessage doesn’t match expected format
400Delegate pubkey mismatchMessage delegate doesn’t match request body
400Percentage mismatchMessage percentage doesn’t match request body
400Nonce expired or invalidNonce older than 5 minutes or in the future
400Cannot delegate to selfDelegator and delegate are the same pubkey
401Invalid signatureSignature verification failed
404No active delegation foundRevoke called with no active delegation