Skip to content

About Swap API

The Definitive Swap API provides a simple interface to swap tokens. This guide demonstrates how to set up and execute a token swap using the API.

Swap Tokens in Five Steps

  1. Get an API Key
  2. Prepare the Pre Hash
  3. Sign the Request
  4. Generate A Quote
  5. Submit Request

Step 1: Get an API Key

Before you begin, obtain your API credentials from Definitive. Follow these steps:

  • Visit the Getting Started page for instructions.
  • Generate your API key and secret.
  • Store them securely, for example, in a .env file:
API_KEY=your_api_key_here
API_SECRET=your_api_secret_here

Additionally, you could use AuthHelpers to streamline this process.

Step 2: Prepare the Pre Hash

To secure your request, you must create a "prehash" string that incorporates the HTTP method, path, query parameters, timestamp, and headers. The prehash format is:

${method}:${path}?${queryParamsString}:${timestamp}:${sortedHeaders}${bodyString};

Below is an example function to generate this prehash in JavaScript:

// if you're using typescript we recommend copying this method directly
function preparePrehash({
  method,
  timestamp,
  path,
  queryParams,
  headers,
  body,
}: PrehashParams) {
  const filtered = Object.entries(headers).filter(([key]) =>
    key.toLowerCase().startsWith("x-definitive-")
  );
 
  // ensure that the headers are sorted for consistency
  const sortedHeaders = filtered
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([key, value]) => `${key}:${JSON.stringify(value)}`)
    .join(",");
 
  // only pass x-definitive-api-key and x-definitive-timestamp
  if (filtered.length > 2) {
    throw new Error("Headers are too long - are you adding a new header?");
  }
 
  // stringify the query params eg. 'key=value&key2=value2'
  const queryParamsString = new URLSearchParams(queryParams).toString();
 
  // Use an empty string if no body is provided
  const bodyString = body ?? "";
 
  return `${method}:${path}?${queryParamsString}:${timestamp}:${sortedHeaders}${bodyString}`;
}
 
const timestamp = Date.now().toString();
 
// generate the message to be signed
const message = preparePrehash({
  method: "POST",
  path: "/v2/portfolio/trade",
  timestamp,
  headers: {
    "x-definitive-api-key": apiKey,
    "x-definitive-timestamp": timestamp,
  },
  queryParams: {},
});

Step 3: Sign the Request

After generating the prehash message, sign it using your API secret. Remove the dpks_ prefix from your API secret (if present) and create an HMAC using SHA-256.

/**
* Signs a message using HMAC SHA256.
*/
function signMessage(message) {
  const signingSecret = apiSecret.replace("dpks_", "");
  return crypto.createHmac("sha256", signingSecret)
    .update(message)
    .digest("hex");
}

Step 4: Generate the Quote

These orders will be scoped to the portfolio for which you created the keys. It is necessary to generate the quote in order to submit a valid request.

async function generateQuote() {
  const method = "POST";
  const path = "/v2/portfolio/trade/quote";
  const timestamp = Date.now().toString();
 
  const headers = {
    "x-definitive-api-key": apiKey,
    "x-definitive-timestamp": timestamp,
    "Content-Type": "application/json"
  };
 
  // Replace these addresses with valid tokens for your trade.
  const quoteRequest = {
    type: "market",     // "market", "limit", "twap", or "stop"
    chain: "base",      // example chain; change if needed
    targetAsset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // e.g., USDC on base
    contraAsset: "0x4200000000000000000000000000000000000006",  // e.g., WETH on base
    qty: "10.00",       // trade quantity
    orderSide: "sell",  // "buy" or "sell"
    slippageTolerance: "0.01", // 1% slippage tolerance
    maxPriceImpact: "0.05"     // 5% maximum price impact
  };
 
  const bodyString = JSON.stringify(quoteRequest);
 
  // Prepare a prehash message using the current parameters.
  const prehashMessage = preparePrehash({
    method,
    path,
    timestamp,
    headers,
    queryParams: {},
    body: bodyString
  });
 
  const signature = signMessage(prehashMessage);
 
  try {
    const response = await fetch(`https://ddp.definitive.fi${path}`, {
      method,
      headers: {
        ...headers,
        "x-definitive-signature": signature
      },
      body: bodyString
    });
 
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
    }
 
    const json = await response.json();
    console.log("Quote Response:", json);
    return json;
  } catch (error) {
    console.error("Error generating quote:", error);
    throw error;
  }
}

Step 5: Submit the Request

Now that we have the ability to generate a prehash, sign the message, and generate a quote: we are ready to submit a request.

async function submitTradeFromQuote() {
  try {
    const quoteResponse = await generateQuote();
    if (!quoteResponse || !quoteResponse.quote) {
      throw new Error("Invalid quote response.");
    }
 
    const method = "POST";
    const path = "/v2/portfolio/trade";
    const timestamp = Date.now().toString();
 
    const headers = {
      "x-definitive-api-key": apiKey,
      "x-definitive-timestamp": timestamp,
      "Content-Type": "application/json"
    };
 
    // Use the quote object directly for the trade
    const bodyString = JSON.stringify(quoteResponse.quote);
 
    const prehashMessage = preparePrehash({
      method,
      path,
      timestamp,
      headers,
      queryParams: {},
      body: bodyString
    });
 
    const signature = signMessage(prehashMessage);
 
    const response = await fetch(`https://ddp.definitive.fi${path}`, {
      method,
      headers: {
        ...headers,
        "x-definitive-signature": signature
      },
      body: bodyString
    });
 
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
    }
 
    const orderResponse = await response.json();
    console.log("Order Response:", orderResponse);
    return orderResponse;
  } catch (error) {
    console.error("Error in submitting trade from quote:", error);
    throw error;
  }
}

Now, if you call submitTradeFromQuote() it will generate a quote and submit it. Please make sure you are using the correct parameters to prevent any accidental swaps.

Key Takeaways

  • Generating The Prehash
  • Signing the Message
  • Generating a Quote with the new v2 format
  • Submitting the Request to v2 endpoints