GetQuote
curl --request POST \
--url https://api.hular.dev/json/v1/quote \
--header 'Content-Type: application/json' \
--data '
{
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"amount": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"slippage_bps": 1,
"src_slippage_bps": 1,
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"gas_drop": "<string>",
"gasless": true,
"sponsor_fees": true,
"supported_params_version": 1
}
'import requests
url = "https://api.hular.dev/json/v1/quote"
payload = {
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"amount": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"slippage_bps": 1,
"src_slippage_bps": 1,
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"gas_drop": "<string>",
"gasless": True,
"sponsor_fees": True,
"supported_params_version": 1
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
src_chain: '<string>',
dst_chain: '<string>',
src_token: '<string>',
dst_token: '<string>',
amount: '<string>',
recipient: '<string>',
refund_address: '<string>',
slippage_bps: 1,
src_slippage_bps: 1,
referrers: [{address: '<string>', bps: 1}],
gas_drop: '<string>',
gasless: true,
sponsor_fees: true,
supported_params_version: 1
})
};
fetch('https://api.hular.dev/json/v1/quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hular.dev/json/v1/quote",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'src_chain' => '<string>',
'dst_chain' => '<string>',
'src_token' => '<string>',
'dst_token' => '<string>',
'amount' => '<string>',
'recipient' => '<string>',
'refund_address' => '<string>',
'slippage_bps' => 1,
'src_slippage_bps' => 1,
'referrers' => [
[
'address' => '<string>',
'bps' => 1
]
],
'gas_drop' => '<string>',
'gasless' => true,
'sponsor_fees' => true,
'supported_params_version' => 1
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hular.dev/json/v1/quote"
payload := strings.NewReader("{\n \"src_chain\": \"<string>\",\n \"dst_chain\": \"<string>\",\n \"src_token\": \"<string>\",\n \"dst_token\": \"<string>\",\n \"amount\": \"<string>\",\n \"recipient\": \"<string>\",\n \"refund_address\": \"<string>\",\n \"slippage_bps\": 1,\n \"src_slippage_bps\": 1,\n \"referrers\": [\n {\n \"address\": \"<string>\",\n \"bps\": 1\n }\n ],\n \"gas_drop\": \"<string>\",\n \"gasless\": true,\n \"sponsor_fees\": true,\n \"supported_params_version\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hular.dev/json/v1/quote")
.header("Content-Type", "application/json")
.body("{\n \"src_chain\": \"<string>\",\n \"dst_chain\": \"<string>\",\n \"src_token\": \"<string>\",\n \"dst_token\": \"<string>\",\n \"amount\": \"<string>\",\n \"recipient\": \"<string>\",\n \"refund_address\": \"<string>\",\n \"slippage_bps\": 1,\n \"src_slippage_bps\": 1,\n \"referrers\": [\n {\n \"address\": \"<string>\",\n \"bps\": 1\n }\n ],\n \"gas_drop\": \"<string>\",\n \"gasless\": true,\n \"sponsor_fees\": true,\n \"supported_params_version\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hular.dev/json/v1/quote")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"src_chain\": \"<string>\",\n \"dst_chain\": \"<string>\",\n \"src_token\": \"<string>\",\n \"dst_token\": \"<string>\",\n \"amount\": \"<string>\",\n \"recipient\": \"<string>\",\n \"refund_address\": \"<string>\",\n \"slippage_bps\": 1,\n \"src_slippage_bps\": 1,\n \"referrers\": [\n {\n \"address\": \"<string>\",\n \"bps\": 1\n }\n ],\n \"gas_drop\": \"<string>\",\n \"gasless\": true,\n \"sponsor_fees\": true,\n \"supported_params_version\": 1\n}"
response = http.request(request)
puts response.read_body{
"cross_chain": {
"quote_hash": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"min_amount_out": "<string>",
"amount_in_usd_micros": "<string>",
"amount_out_usd_micros": "<string>",
"slippage_bps": 1,
"fee_breakdown": {
"components": [
{
"name": "<string>",
"side": "<string>",
"usd_micros": "<string>",
"native": "<string>"
}
],
"dst_total_usd_micros": "<string>",
"src_total_usd_micros": "<string>",
"dst_gas_native": "<string>",
"src_gas_native": "<string>"
},
"router_address": "<string>",
"order_params": {
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"bridge_token_src": "<string>",
"bridge_token_dst": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"bridge_amount": "<string>",
"min_bridge_out": "<string>",
"min_amount_out": "<string>",
"gas_drop": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"refund_token": "<string>",
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"slippage_bps": 1,
"src_slippage_bps": 1,
"router_address": "<string>",
"refund_fee_bridge": "<string>",
"refund_fee_native": "<string>",
"nonce": "aSDinaTvuI8gbWludGxpZnk=",
"params_version": 1
},
"gasless": true,
"sponsor_fees": true,
"gasless_router_address": "<string>",
"sponsor_address": "<string>",
"fulfill_eta_secs": "<string>",
"direct_transfer": true,
"deposit_deadline": "<string>"
},
"same_chain_swap": {
"quote_hash": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"min_amount_out": "<string>",
"amount_in_usd_micros": "<string>",
"amount_out_usd_micros": "<string>",
"slippage_bps": 1,
"fee_breakdown": {
"components": [
{
"name": "<string>",
"side": "<string>",
"usd_micros": "<string>",
"native": "<string>"
}
],
"dst_total_usd_micros": "<string>",
"src_total_usd_micros": "<string>",
"dst_gas_native": "<string>",
"src_gas_native": "<string>"
},
"router_address": "<string>",
"order_params": {
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"bridge_token_src": "<string>",
"bridge_token_dst": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"bridge_amount": "<string>",
"min_bridge_out": "<string>",
"min_amount_out": "<string>",
"gas_drop": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"refund_token": "<string>",
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"slippage_bps": 1,
"src_slippage_bps": 1,
"router_address": "<string>",
"refund_fee_bridge": "<string>",
"refund_fee_native": "<string>",
"nonce": "aSDinaTvuI8gbWludGxpZnk=",
"params_version": 1
},
"fulfill_eta_secs": "<string>",
"deposit_deadline": "<string>"
}
}{
"code": 123,
"message": "<string>",
"details": [
{}
]
}Reference
GetQuote
Price a trade and persist it, returning the quote hash a deposit binds to.
POST
/
v1
/
quote
GetQuote
curl --request POST \
--url https://api.hular.dev/json/v1/quote \
--header 'Content-Type: application/json' \
--data '
{
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"amount": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"slippage_bps": 1,
"src_slippage_bps": 1,
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"gas_drop": "<string>",
"gasless": true,
"sponsor_fees": true,
"supported_params_version": 1
}
'import requests
url = "https://api.hular.dev/json/v1/quote"
payload = {
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"amount": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"slippage_bps": 1,
"src_slippage_bps": 1,
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"gas_drop": "<string>",
"gasless": True,
"sponsor_fees": True,
"supported_params_version": 1
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
src_chain: '<string>',
dst_chain: '<string>',
src_token: '<string>',
dst_token: '<string>',
amount: '<string>',
recipient: '<string>',
refund_address: '<string>',
slippage_bps: 1,
src_slippage_bps: 1,
referrers: [{address: '<string>', bps: 1}],
gas_drop: '<string>',
gasless: true,
sponsor_fees: true,
supported_params_version: 1
})
};
fetch('https://api.hular.dev/json/v1/quote', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hular.dev/json/v1/quote",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'src_chain' => '<string>',
'dst_chain' => '<string>',
'src_token' => '<string>',
'dst_token' => '<string>',
'amount' => '<string>',
'recipient' => '<string>',
'refund_address' => '<string>',
'slippage_bps' => 1,
'src_slippage_bps' => 1,
'referrers' => [
[
'address' => '<string>',
'bps' => 1
]
],
'gas_drop' => '<string>',
'gasless' => true,
'sponsor_fees' => true,
'supported_params_version' => 1
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hular.dev/json/v1/quote"
payload := strings.NewReader("{\n \"src_chain\": \"<string>\",\n \"dst_chain\": \"<string>\",\n \"src_token\": \"<string>\",\n \"dst_token\": \"<string>\",\n \"amount\": \"<string>\",\n \"recipient\": \"<string>\",\n \"refund_address\": \"<string>\",\n \"slippage_bps\": 1,\n \"src_slippage_bps\": 1,\n \"referrers\": [\n {\n \"address\": \"<string>\",\n \"bps\": 1\n }\n ],\n \"gas_drop\": \"<string>\",\n \"gasless\": true,\n \"sponsor_fees\": true,\n \"supported_params_version\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hular.dev/json/v1/quote")
.header("Content-Type", "application/json")
.body("{\n \"src_chain\": \"<string>\",\n \"dst_chain\": \"<string>\",\n \"src_token\": \"<string>\",\n \"dst_token\": \"<string>\",\n \"amount\": \"<string>\",\n \"recipient\": \"<string>\",\n \"refund_address\": \"<string>\",\n \"slippage_bps\": 1,\n \"src_slippage_bps\": 1,\n \"referrers\": [\n {\n \"address\": \"<string>\",\n \"bps\": 1\n }\n ],\n \"gas_drop\": \"<string>\",\n \"gasless\": true,\n \"sponsor_fees\": true,\n \"supported_params_version\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hular.dev/json/v1/quote")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"src_chain\": \"<string>\",\n \"dst_chain\": \"<string>\",\n \"src_token\": \"<string>\",\n \"dst_token\": \"<string>\",\n \"amount\": \"<string>\",\n \"recipient\": \"<string>\",\n \"refund_address\": \"<string>\",\n \"slippage_bps\": 1,\n \"src_slippage_bps\": 1,\n \"referrers\": [\n {\n \"address\": \"<string>\",\n \"bps\": 1\n }\n ],\n \"gas_drop\": \"<string>\",\n \"gasless\": true,\n \"sponsor_fees\": true,\n \"supported_params_version\": 1\n}"
response = http.request(request)
puts response.read_body{
"cross_chain": {
"quote_hash": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"min_amount_out": "<string>",
"amount_in_usd_micros": "<string>",
"amount_out_usd_micros": "<string>",
"slippage_bps": 1,
"fee_breakdown": {
"components": [
{
"name": "<string>",
"side": "<string>",
"usd_micros": "<string>",
"native": "<string>"
}
],
"dst_total_usd_micros": "<string>",
"src_total_usd_micros": "<string>",
"dst_gas_native": "<string>",
"src_gas_native": "<string>"
},
"router_address": "<string>",
"order_params": {
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"bridge_token_src": "<string>",
"bridge_token_dst": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"bridge_amount": "<string>",
"min_bridge_out": "<string>",
"min_amount_out": "<string>",
"gas_drop": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"refund_token": "<string>",
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"slippage_bps": 1,
"src_slippage_bps": 1,
"router_address": "<string>",
"refund_fee_bridge": "<string>",
"refund_fee_native": "<string>",
"nonce": "aSDinaTvuI8gbWludGxpZnk=",
"params_version": 1
},
"gasless": true,
"sponsor_fees": true,
"gasless_router_address": "<string>",
"sponsor_address": "<string>",
"fulfill_eta_secs": "<string>",
"direct_transfer": true,
"deposit_deadline": "<string>"
},
"same_chain_swap": {
"quote_hash": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"min_amount_out": "<string>",
"amount_in_usd_micros": "<string>",
"amount_out_usd_micros": "<string>",
"slippage_bps": 1,
"fee_breakdown": {
"components": [
{
"name": "<string>",
"side": "<string>",
"usd_micros": "<string>",
"native": "<string>"
}
],
"dst_total_usd_micros": "<string>",
"src_total_usd_micros": "<string>",
"dst_gas_native": "<string>",
"src_gas_native": "<string>"
},
"router_address": "<string>",
"order_params": {
"src_chain": "<string>",
"dst_chain": "<string>",
"src_token": "<string>",
"dst_token": "<string>",
"bridge_token_src": "<string>",
"bridge_token_dst": "<string>",
"amount_in": "<string>",
"amount_out": "<string>",
"bridge_amount": "<string>",
"min_bridge_out": "<string>",
"min_amount_out": "<string>",
"gas_drop": "<string>",
"recipient": "<string>",
"refund_address": "<string>",
"refund_token": "<string>",
"referrers": [
{
"address": "<string>",
"bps": 1
}
],
"slippage_bps": 1,
"src_slippage_bps": 1,
"router_address": "<string>",
"refund_fee_bridge": "<string>",
"refund_fee_native": "<string>",
"nonce": "aSDinaTvuI8gbWludGxpZnk=",
"params_version": 1
},
"fulfill_eta_secs": "<string>",
"deposit_deadline": "<string>"
}
}{
"code": 123,
"message": "<string>",
"details": [
{}
]
}rpc GetQuote(QuoteRequest) returns (QuoteResponse)
PreviewQuote for prices that update as they type.
Request
string
required
Source chain name, lowercase. Equal to
dst_chain for a same-chain swap.string
required
Destination chain name, lowercase.
string
required
Source token address. The zero address is the native asset on EVM chains.
string
required
Destination token address.
TradeType
required
Which side of the trade
amount fixes and whether the output is guaranteed: TRADE_TYPE_EXACT_INPUT, TRADE_TYPE_EXPECTED_OUTPUT, TRADE_TYPE_EXACT_INPUT_GUARANTEED_OUTPUT, or TRADE_TYPE_EXACT_OUTPUT. TRADE_TYPE_UNSPECIFIED is rejected. See Trade types.string
required
For exact input, the amount to deposit in the source token’s base units. For expected output, the desired output in the destination token’s base units.
string
required
Address receiving on the destination chain, in that chain’s address format.
string
required
Source-chain address a refund is paid to if the order cannot be fulfilled.
string
required
Native asset to deliver on the destination chain, in base units. Empty string for none. Capped by the chain’s
max_gas_drop.uint32
Floor for the destination swap leg, in basis points. Omitted means a tier is chosen for the pair.
uint32
Floor for the source swap leg, in basis points.
Referrer[]
Referrer addresses and their basis points. Priced into the quote as
referrer_fee.bool
Request a gasless quote: the deposit is signed off chain and relayed by the operator, whose gas cost is priced in as
sponsor_gas. Only for cross-chain quotes from a non-native source token on a chain where GetChains reports gasless: true. See SubmitGaslessOrder.bool
With
gasless, charge the relay gas to your partner funding balance instead of the user’s output. Requires an x-api-key belonging to a funded partner. See PartnerApi funding.Response
QuoteResponse is a oneof with two cases, cross_chain and same_chain_swap. Both carry the fields below; cross_chain additionally carries the gasless fields.
string
Keccak hash of the stored order parameters. The deposit carries it, and it identifies the order everywhere afterwards.
string
Deposit amount in the source token’s base units. Echoes the request for exact input; the solved input for expected output.
string
Expected output in the destination token’s base units, net of every fee. On an expected-output quote this can differ from the requested
amount by a few basis points.string
Guaranteed floor. A fulfillment delivering less does not land.
uint32
Slippage actually applied, which may differ from the request.
string
Contract the deposit must be sent to. Program id on Solana.
string
Notional input value in USD micros. Absent when a price is unavailable.
string
Notional output value in USD micros. Absent when a price is unavailable.
uint64
Estimated seconds from deposit to fulfillment, the median over recent orders on the same chain pair and route type. Absent when there is no history and no configured default for the destination chain.
string
RFC 3339 timestamp, 30 minutes after the quote was issued. Informational: the price is not adjusted afterwards, so clients should re-quote instead of depositing past it. A deposit that still lands is processed at the quoted terms while the quote is retained.
cross_chain only:
bool
The quote was priced for gasless submission. Deposit it through
SubmitGaslessOrder, not a wallet transaction.bool
The relay gas is charged to the partner’s funding balance rather than the user’s output.
string
EVM contract the relayed deposit executes against, and the spender the permit2 signature must authorize. Present on gasless quotes.
string
Solana account that pays the transaction fee. Set it as the fee payer of the transaction sent to
SubmitGaslessOrder. Present on gasless quotes from a Solana source.Example
grpcurl \
-H "x-api-key: $HULAR_API_KEY" \
-d '{
"src_chain": "arbitrum",
"dst_chain": "solana",
"src_token": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
"dst_token": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"trade_type": "TRADE_TYPE_EXACT_INPUT",
"amount": "25000000",
"recipient": "EPjF...",
"refund_address": "0x...",
"gas_drop": ""
}' \
$HULAR_HOST hular.v1.HularApi/GetQuote
Errors
| Code | When |
|---|---|
INVALID_ARGUMENT | Unsupported pair, missing or unknown trade type, malformed amount or address, size outside the accepted band, gas drop over the cap, slippage of 100% or more on an expected-output quote, unusable referrer list, gasless requested where it is not supported. |
UNAVAILABLE | Chain disabled for quoting, insufficient inventory, bridge pair suspended, price feed stale, aggregator failure. |
UNAUTHENTICATED | sponsor_fees without an API key. |
Headers
Optional. Without a key the request is rate limited per client IP and quotes carry extra spread.
Body
application/json
Required range:
x >= 0Required range:
x >= 0Show child attributes
Show child attributes
Available options:
TRADE_TYPE_UNSPECIFIED, TRADE_TYPE_EXACT_INPUT, TRADE_TYPE_EXPECTED_OUTPUT, TRADE_TYPE_EXACT_INPUT_GUARANTEED_OUTPUT, TRADE_TYPE_EXACT_OUTPUT Required range:
x >= 0