Skip to main content

Solana

DFlow supports token swaps and indicative quotes on Solana. Backup liquidity is available from Jupiter Aggregator.

Supported token pairs and order sizes

You must create auctions for each token pair you want to support. Additionally, your auctions for a token pair must cover all order sizes that you want to support for that token pair. See Create Auction to learn how to create an auction.

Token Swaps

Step 1: Request an Endorsement

First, request an endorsement from your endorsement server.

// Use your endorsement server's URL
const endorsementServerURL = "https://endorsements.dflow.net";
const walletAddress = "rtFMmRrBUKnz6hXm2KfEQBK7GLMq8ziHCt9yZrEMmF7";
const endorsementURL = endorsementServerURL + "?retailTrader=" + walletAddress;
const endorsement = await (await fetch(endorsementURL)).json();

Step 2: Request a Firm Quote

Once your request is endorsed, you can request a firm quote. A firm quote includes a Solana transaction that contains the instructions needed to perform the token swap.

import { FirmQuoteResponseCode, getFirmQuote } from "@dflow-protocol/signatory-client-lib/solana";

const signatoryServerURL = "https://signatory.dflow.net";
const walletAddress = "rtFMmRrBUKnz6hXm2KfEQBK7GLMq8ziHCt9yZrEMmF7";
const firmQuote = await getFirmQuote(SIGNATORY_SERVER_URL, {
sendMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
receiveMint: "So11111111111111111111111111111111111111112",
sendQty: "5",
useNativeSOL: true,
orderFlowSource: "dflow1ejsafz9xy3ymkp6fmw8t299ag0wfl7drydj68n",
endorsement: endorsement,
retailTrader: walletAddress,
});
if (firmQuote.code !== FirmQuoteResponseCode.Ok) {
// Quote request failed.
}

This is the response:

{
"code": 0,
"tx": "AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACql2AsCC3sGxwonmDS+MiTggf0o9TAKt3l1Nmg6TrMEvXBQHEKjJErsbRvhQQGn+KtUYpNS+bbHlW1UXih2XoIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMABAoLd1EiR7xIwXGcMLfFgMqwV59vInB9tFI5Qd+4gTdzFNnUY5fiBgcuPOZhS+hFYyxUxq9CJuYqhGH6yVnMCivXDMdnyrUb5RQt+Y/aWhp3zirvTcT08a/bHrQr1WR1w/KFtsmZm5tVD330elTNoVK+tCz586Ulkg5JwgORt3s0rpJhKUqQTo8Zxi70fvC/bVrZzD+J1z0E2ZEu1PtfaSw2ta/ELj1MYBPRSkaHAoIuDExEQSy11AXVdbUoloxagD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAabiFf+q4GE+2h/Y0YYwDXaxDncGus7VZig8AAAAAABBqfVFxksXFEhjMlMPUrxf1ja7gibof1E49vZigAAAAAG3fbh12Whk9nL4UbO63msHLSF7V9bN5E6jPWFfv8AqbmVE5/Jadms/F1fK99HET/4gMnV4tGlDHxokNB/dSq/BQYCAgE0AAAAAPAdHwAAAAAApQAAAAAAAAAG3fbh12Whk9nL4UbO63msHLSF7V9bN5E6jPWFfv8AqQkEAQcCCAEBCQMFAwIJA0BLTAAAAAAACQMEAQAJAwQfORUAAAAACQMBAgIBCQ==",
"txRequiredLamports": 2039280,
"lastValidBlockHeight": 7842,
"lastAllowedBlockHeight": 7817,
"receiveQty": "356065028", // 0.356065028 SOL
"quoteId": ...
"requestId": ...
}

Firm Quote Request Fields

FieldTypeDescription
sendMintstringThe Base58-encoded SPL mint that the retail trader will send.
receiveMintstringThe Base58-encoded SPL mint that the retail trader will receive.
sendQtystringThe quantity of sendMint that the retail trader will send.
useNativeSOLbooleanUse native SOL instead of wrapped SOL when buying or selling SOL. Default is true.
orderFlowSourcestringThe order flow source's DFlow address. This is the address on the DFlow chain of the wallet that you use to create your auctions.
endorsementobjectThe endorsement received from the endorsement server.
retailTraderstringBase58-encoded address of the retail trader's Solana wallet.

Firm Quote Response Fields

The response for a successful request contains the following fields:

FieldTypeDescription
codeintegerThe status code for the quote request. 0 indicates a successful request.
receiveQtystringThe quantity of receiveMint that the retail trader will receive. Note that the receiveQty is specified with the fixed number of decimals used for the receive mint. For example, if the receiveMint is USDC, which has 6 decimals, and the receiveQty is 1500000, then the retail trader will receive 1.5 USDC.
txstringThe Base64-encoded swap transaction. If needed, the transaction will include an instructions to create the retail trader's associated token account for the receiveMint.
txRequiredLamportsintegerThe number of lamports required from the retail trader to execute the transaction. This number accounts for the rent required to create the retail trader's associated token account for the receiveMint, the rent required to create an ephemeral token account used to wrap or unwrap native SOL, and the Solana network fee. Note that rent for an ephemeral token account used to wrap or unwrap native SOL is returned to the retail trader at the end of the transaction.
lastValidBlockHeightintegerThe last valid Solana block height at which the swap transaction may be processed on Solana. You can use this when checking for transaction confirmation using the Solana JSON RPC API.
lastAllowedBlockHeightintegerThe last Solana block height at which the swap transaction may be sent to the DFlow node. If the transaction is sent to the DFlow node after this Solana block height, the DFlow node rejects the transaction, and you must request another quote.
blockHeightQueryCommitmentstringThe commitment level that the DFlow node will use when querying the Solana block height to determine whether the lastAllowedBlockHeight has passed. You should use this commitment level when querying and comparing the current Solana block height to the lastAllowedBlockHeight.
quoteIdstringAn identifier used by the market maker to identify its quotes. Must be included in the sendTransaction request.
requestIdobjectRequest information used by the DFlow node when processing a sendTransaction request.

Step 3: Send the Swap Transaction

Now that you have a swap transaction, you can sign it and then execute it by sending it via the DFlow network.

import { sendTransaction, SendTransactionResponseCode } from "@dflow-protocol/signatory-client-lib/solana";
import { Transaction } from "@solana/web3.js";

const signatoryServerURL = "https://signatory.dflow.net";
const txBuffer = Buffer.from(firmQuote.tx, "base64");
const tx = Transaction.from(txBuffer);
const signedTx = await wallet.signTransaction(tx);
const serializedTx = signedTx.serialize({ requireAllSignatures: false }).toString("base64");
const result = await sendTransaction(SIGNATORY_SERVER_URL, {
tx: serializedTx,
lastValidBlockHeight: firmQuote.lastValidBlockHeight,
lastAllowedBlockHeight: firmQuote.lastAllowedBlockHeight,
endorsement: endorsement,
quoteId: firmQuote.quoteId,
requestId: firmQuote.requestId,
});
if (result.code !== SendTransactionResponseCode.Sent) {
// Transaction wasn't sent. Request another quote and retry.
}

This is the response:

{
"signature": "3dqTxisZH5fdKz9g5jQnCvVr7R6oMFCoR9ZUkhrWkE9DGbzLZ8ZkQk8kqd4ztdQRNDmyXjNbgi1h22BtXbvnja73"
}

Send Transaction Request Fields

FieldTypeDescription
txstringThe Base64-encoded swap transaction, signed by the retail trader.
lastValidBlockHeightintegerTaken from the firmQuote response.
lastAllowedBlockHeightintegerTaken from the firmQuote response.
endorsementobjectThe endorsement received from the endorsement server.
quoteIdstringTaken from the firmQuote response.
requestIdobjectTaken from the firmQuote response.

Send Transaction Response Fields

If the transaction was sent to Solana, the response will contain the following fields:

FieldTypeDescription
signaturestringThe transaction signature. You can use this to check for transaction confirmation using the Solana JSON RPC API.

Indicative Quotes

An indicative quote contains pricing information from the market maker, but unlike a firm quote, it cannot be used to swap tokens at a set price. You should use indicative quotes to show pricing information when you don't have a wallet connected or don't intend to send an order.

Step 1: Request an Endorsement

First, request an endorsement from your endorsement server. Note that if your application allows your users to see indicative prices before connecting their wallets, your endorsements for indicative quotes can be generic and omit the retailTrader.

// Use your endorsement server's URL
const endorsementServerURL = "https://endorsements.dflow.net";
const walletAddress = "rtFMmRrBUKnz6hXm2KfEQBK7GLMq8ziHCt9yZrEMmF7";
const endorsementURL = endorsementServerURL + "?retailTrader=" + walletAddress;
const endorsement = await (await fetch(endorsementURL)).json();

Step 2: Request an Indicative Quote

Once your request is endorsed, you can request an indicative quote.

import { getIndicativeQuote } from "@dflow-protocol/signatory-client-lib/solana";

const signatoryServerURL = "https://signatory.dflow.net";
const walletAddress = "rtFMmRrBUKnz6hXm2KfEQBK7GLMq8ziHCt9yZrEMmF7";
const indicativeQuote = await getIndicativeQuote(SIGNATORY_SERVER_URL, {
sendMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
receiveMint: "So11111111111111111111111111111111111111112",
sendQty: "5",
orderFlowSource: "dflow1ejsafz9xy3ymkp6fmw8t299ag0wfl7drydj68n",
endorsement: endorsement,
retailTrader: walletAddress,
});

This is the response:

{
"fillPrice": "76640000" // 0.076640000 SOL per USDC
}

Indicative Quote Request Fields

FieldTypeDescription
sendMintstringThe Base58-encoded SPL mint that the retail trader would send.
receiveMintstringThe Base58-encoded SPL mint that the retail trader would receive.
sendQtystringThe quantity of sendMint that the retail trader would send.
orderFlowSourcestringThe order flow source's DFlow address. This is the address on the DFlow chain of the wallet that you use to create your auctions.
endorsementobjectThe endorsement received from the endorsement server.
retailTraderstring (optional)Base58-encoded address of the retail trader's Solana wallet. Include this field if and only if the endorsement is specific to the retail trader.

Indicative Quote Response Fields

The response for a successful request contains the following fields:

FieldTypeDescription
fillPricestringThe number of token units that the retail trader would receive per token sent. Note that the fillPrice is specified with the fixed number of decimals used for the receive mint. For example, if the receiveMint is USDC, which has 6 decimals, and the fillPrice is 1500000, then the retail trader would receive 1.5 USDC per sendMint token.