Polygon
DFlow supports token swaps and indicative quotes on Polygon.
To access best-execution market maker liquidity, you must create order flow auctions (OFAs) for each token pair you want to support. Additionally, your OFAs 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.
If you choose to use an alternative liquidity source (e.g. AMM or aggregator) for certain token pairs or order sizes, you may set up a backup liquidity provider (LP) without creating an auction. Refer to Backup Liquidity Provider (LP).
Token Swaps
Step 1: Request an Endorsement
First, request an endorsement from your endorsement server.
- TypeScript
// Use your endorsement server's URL
const endorsementServerURL = "https://endorsements.dflow.net";
const walletAddress = "0x838A9B9992052AB55b5239c74d41671d03A5c31A";
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 Polygon transaction that contains the instructions needed to perform the token swap.
- TypeScript SDK
- TypeScript
import {
FirmQuoteResponseCode,
getFirmQuote,
} from "@dflow-protocol/signatory-client-lib/evm";
const signatoryServerURL = "https://signatory-1.dflow.net";
const walletAddress = "0x838A9B9992052AB55b5239c74d41671d03A5c31A";
const firmQuote = await getFirmQuote(signatoryServerURL, {
chainId: 137,
sendToken: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
receiveToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
sendQty: "5",
orderFlowSource: "dflow1ejsafz9xy3ymkp6fmw8t299ag0wfl7drydj68n",
endorsement: endorsement,
retailTrader: walletAddress,
});
if (firmQuote.code !== FirmQuoteResponseCode.Ok) {
// Quote request failed.
}
const signatoryServerURL = "https://signatory-1.dflow.net";
const firmQuoteEndpoint = signatoryServerURL + "/api/evm/firmQuote";
const walletAddress = "0x838A9B9992052AB55b5239c74d41671d03A5c31A";
const requestBody = JSON.stringify({
chainId: 137,
sendToken: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
receiveToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
sendQty: "5",
orderFlowSource: "dflow1ejsafz9xy3ymkp6fmw8t299ag0wfl7drydj68n",
endorsement: endorsement,
retailTrader: walletAddress,
});
const response = await fetch(firmQuoteEndpoint, {
method: "POST",
headers: {
"content-type": "application/json",
"content-length": Buffer.byteLength(requestBody).toString(),
},
body: requestBody,
});
const firmQuote = await response.json();
if (firmQuote.code !== 0) {
// Quote request failed.
}
This is the response:
{
"code": 0, // A successful firm quote fetched from the market maker
"tx": {
"chainId": 137,
"from": "0x838A9B9992052AB55b5239c74d41671d03A5c31A",
"to": "0x...",
"data": "0x...",
"value": "...",
},
"minGasLimit": "500000",
"allowanceTarget": "0x...",
"lastValidBlockTimestamp": 1682214813,
"lastAllowedBlockTimestamp": 1682214803,
"receiveQty": "4923819115647293875", // 4.923819115647293875 MATIC
"requestId": {...},
}
Firm Quote Request Fields
Field | Type | Description |
---|---|---|
chainId | number | The chain ID of the EVM chain. |
sendToken | string | The address of the ERC-20 token sent by the retail trader. For native MATIC, this is 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee. |
receiveToken | string | The address of the ERC-20 token received by the retail trader. For native MATIC, this is 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee. |
sendQty | string | The quantity of sendToken that the retail trader will send. |
orderFlowSource | string | The order flow source's DFlow address. This is the address on the DFlow Chain of the wallet that you use to create your auctions. |
endorsement | object | (Optional) The endorsement received from the endorsement server. Only required if the request is routed via an auction. |
retailTrader | string | Address of the retail trader's Polygon wallet. |
Firm Quote Response Fields
The response for a successful request contains the following fields:
Field | Type | Description |
---|---|---|
code | number | The status code for the quote request. The available response codes are 0 , 1 , and 2 . 0 indicates a successful request for market maker quote. 1 indicates a successful request for backup liquidity quote when the quote request is routed via an auction. For both 0 and 1 , you must send the transaction using the DFlow sendTransaction endpoint. 2 indicates a successful request for backup liquidity when the quote request is not routed via an auction. In this case, the transaction must be sent directly to Polygon. |
tx | object | The transaction. The client is responsible for populating the transaction's nonce and gas parameters. The client must not modify the specified transaction parameters. |
minGasLimit | string | Minimum allowed gas limit for the transaction. If the client specifies a lower gas limit, the transaction will be rejected. |
allowanceTarget | string | The contract address for which the retail trader needs to have an allowance for the send token for the transaction to be processed. |
lastValidBlockTimestamp | number | The last Polygon block timestamp at which the transaction can be processed. |
lastAllowedBlockTimestamp | string | The last Polygon block timestamp at which the swap transaction may be sent to the DFlow node. If the transaction is sent to the DFlow node after this Polygon block timestamp, the DFlow node rejects the transaction, and you must request another quote. |
receiveQty | string | The quantity of receiveToken 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 receiveToken is USDC, which has 6 decimals, and the receiveQty is 1500000, then the retail trader will receive 1.5 USDC. |
requestId | object | Request 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. Firm quote requests with a response code of 0
or 1
must do this step. If you fetched a firm quote from a backup LP without routing via an auction (response code 3
), you can send the transaction directly to Polygon.
- TypeScript SDK
- TypeScript
import {
sendTransaction,
SendTransactionResponseCode,
} from "@dflow-protocol/signatory-client-lib/evm";
import { ethers } from "ethers";
const signatoryServerURL = "https://signatory-1.dflow.net";
const [nonce, feeData] = await Promise.all([
ethers.provider.getTransactionCount(walletAddress),
ethers.provider.getFeeData(),
]);
const signedTx = await wallet.signTransaction({
...firmQuote.tx,
nonce,
gasLimit: firmQuote.minGasLimit,
maxFeePerGas: feeData.maxFeePerGas,
});
const result = await sendTransaction(signatoryServerURL, {
tx: signedTx,
lastAllowedBlockTimestamp: firmQuote.lastAllowedBlockTimestamp,
endorsement: endorsement,
requestId: firmQuote.requestId,
});
if (result.code !== SendTransactionResponseCode.Sent) {
// Transaction wasn't sent. Request another quote and retry.
}
import { ethers } from "ethers";
const signatoryServerURL = "https://signatory-1.dflow.net";
const sendTransactionEndpoint = signatoryServerURL + "/api/evm/sendTransaction";
const [nonce, feeData] = await Promise.all([
ethers.Provider.getTransactionCount(walletAddress),
ethers.Provider.getFeeData(),
]);
const signedTx = await wallet.signTransaction({
...firmQuote.tx,
nonce,
gasLimit: firmQuote.minGasLimit,
maxFeePerGas: feeData.maxFeePerGas,
});
const requestBody = JSON.stringify({
tx: signedTx,
lastAllowedBlockTimestamp: firmQuote.lastAllowedBlockTimestamp,
endorsement: endorsement,
requestId: firmQuote.requestId,
});
const response = await fetch(sendTransactionEndpoint, {
method: "POST",
headers: {
"content-type": "application/json",
"content-length": Buffer.byteLength(requestBody).toString(),
},
body: requestBody,
});
const result = await response.json();
if (result.code !== 0) {
// Transaction wasn't sent. Request another quote and retry.
}
This is the response:
{
"code": 0,
"txHash": "0x..."
}
Send Transaction Request Fields
Field | Type | Description |
---|---|---|
tx | string | The hex-encoded transaction, signed by the retail trader. |
lastAllowedBlockTimestamp | number | (Optional) Taken from the firmQuote response. Only specified if the firm quote response included a lastAllowedBlockTimestamp . |
endorsement | object | The endorsement received from the endorsement server. |
requestId | object | Taken from the firmQuote response. |
Send Transaction Response Fields
If the transaction was sent to Polygon, the response will contain the following fields:
Field | Type | Description |
---|---|---|
code | number | 0 if transaction was sent to the network and 1 if transaction was not sent to the network. |
txHash | string | Polygon transaction hash. You can use this to check for transaction confirmation using the Polygon 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
.
- TypeScript
// Use your endorsement server's URL
const endorsementServerURL = "https://endorsements.dflow.net";
const walletAddress = "0x838A9B9992052AB55b5239c74d41671d03A5c31A";
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.
- TypeScript SDK
- TypeScript
import { getIndicativeQuote } from "@dflow-protocol/signatory-client-lib/evm";
const signatoryServerURL = "https://signatory-1.dflow.net";
const walletAddress = "0x838A9B9992052AB55b5239c74d41671d03A5c31A";
const indicativeQuote = await getIndicativeQuote(signatoryServerURL, {
chainId: 137,
sendToken: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
receiveToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
sendQty: "5",
orderFlowSource: "dflow1ejsafz9xy3ymkp6fmw8t299ag0wfl7drydj68n",
endorsement: endorsement, // Required when routing via auction
retailTrader: walletAddress, // Required when routing via auction
});
const signatoryServerURL = "https://signatory-1.dflow.net";
const indicativeQuoteEndpoint = signatoryServerURL + "/api/evm/indicativeQuote";
const walletAddress = "0x838A9B9992052AB55b5239c74d41671d03A5c31A";
const requestBody = JSON.stringify({
chainId: 137,
sendToken: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
receiveToken: "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
sendQty: "5",
orderFlowSource: "dflow1ejsafz9xy3ymkp6fmw8t299ag0wfl7drydj68n",
endorsement: endorsement, // Required when routing via auction
retailTrader: walletAddress, // Required when routing via auction
});
const response = await fetch(indicativeQuoteEndpoint, {
method: "POST",
headers: {
"content-type": "application/json",
"content-length": Buffer.byteLength(requestBody).toString(),
},
body: requestBody,
});
const indicativeQuote = await response.json();
This is the response:
{
"fillPrice": "984763823125212342" // 0.984763823125212342 MATIC per USDC
}
Indicative Quote Request Fields
Field | Type | Description |
---|---|---|
chainId | number | The chain ID of the EVM chain. |
sendToken | string | The address of the ERC-20 token sent by the retail trader. For native MATIC, this is 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee. |
receiveToken | string | The address of the ERC-20 token received by the retail trader. For native MATIC, this is 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee. |
sendQty | string | The quantity of sendToken that the retail trader will send. |
orderFlowSource | string | The order flow source's DFlow address. This is the address on the DFlow Chain of the wallet that you use to create your auctions. |
endorsement | object | (Optional) The endorsement received from the endorsement server. Only required if the request is routed via an auction. |
retailTrader | string | (Optional) Address of the retail trader's Polygon wallet. Only required if the request is routed via an auction. |
Indicative Quote Response Fields
The response for a successful request contains the following fields:
Field | Type | Description |
---|---|---|
fillPrice | string | The 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 token. For example, if the receiveToken is USDC, which has 6 decimals, and the fillPrice is 1500000, then the retail trader would receive 1.5 USDC per sendToken token. |