Skip to main content
1Click signs quote payloads so partners can verify the payload origin and detect tampering before using fields like depositAddress in 1click quote response payloads. This can help to
  • Prevent man-in-the-middle tampering on transport or proxy layers.
  • Ensure a quote/status payload was produced by the 1Click API.
  • Detect unexpected field mutation before showing the quote or executing swaps.

What is signed

The signed message is a Base58-encoded SHA-256 hash of a deterministic JSON object from the 1click quote payload response. The JSON is serialized with stable key ordering (json-stable-stringify), then hashed with SHA-256 and Base58-encoded.

TypeScript interface example used for signing

quoteRequest fields included in signature derivation. The signing payload shape matches the SDK types below:
type OneClickSignedQuoteRequest = {
  dry: boolean;
  swapType: string;
  slippageTolerance: number;
  originAsset: string;
  depositType: string;
  destinationAsset: string;
  amount: string;
  refundTo: string;
  refundType: string;
  recipient: string;
  recipientType: string;
  deadline: string;
  quoteWaitingTimeMs?: number;
  referral?: string;
  virtualChainRecipient?: string;
  virtualChainRefundRecipient?: string;
  customRecipientMsg?: string;
};

type OneClickDrySignedQuote = {
  amountIn: string;
  amountInFormatted: string;
  amountInUsd: string;
  minAmountIn: string;
  amountOut: string;
  amountOutFormatted: string;
  amountOutUsd: string;
  minAmountOut: string;
};

type OneClickFullSignedQuote = OneClickDrySignedQuote & {
  depositAddress?: string;
  depositMemo?: string;
  chainDepositAddresses?: Array<{
    blockchain: string;
    address: string;
    memo?: string;
  }>;
  deadline?: string;
  timeWhenInactive?: string;
  timeEstimate?: number;
  virtualChainRecipient?: string;
  virtualChainRefundRecipient?: string;
  customRecipientMsg?: string;
  refundFee?: string;
  withdrawFee?: string;
};
Both dry and non-dry quotes can be verified to have come from 1Click. The difference is that non-dry quotes include extra execution fields (for example depositAddress) in the signed payload.
The signed message input is:
stringify({ ...quoteRequest, ...quoteResponse, timestamp });
If you integrate with our TypeScript SDK, use verifyQuoteSignature() directly:
import { verifyQuoteSignature } from "@defuse-protocol/one-click-sdk-typescript";

const quoteResponse = await fetch("https://1click.chaindefuser.com/v0/quote", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(quoteRequest),
}).then((r) => r.json());

const isValid = verifyQuoteSignature(quoteResponse);
if (!isValid) {
  throw new Error("Invalid quote signature");
}
The verifyQuoteSignature() function requires @defuse-protocol/one-click-sdk-typescript version 0.1.24 or later.
Both include signature and timestamp, and both should be verified before consuming the quote payload.