Skip to content

Conversation

@dimxy
Copy link
Collaborator

@dimxy dimxy commented Jul 23, 2025

Next phase of liquidity routing (LR) development (WIP).
Fixes and new features to the find_best_quote RPC:

  • adds 'buy' action support,
  • adds bid orders support,
  • adds LR_1 step (after atomic swap).
    Improved code, RPC params, fixed total price calculations.

Details for the find_best_quote RPC are here:

/// The "find_best_quote" RPC implementation to find the best swap with liquidity routing (LR), also known as 'aggregated taker swap with LR'.

This code requires setting up 1inch API service as an LR provider.

Setting Up 1inch Provider in KDF

The MM2.json should contain "1inch_api" param pointing to a url to the 1inch API server ("https://api.1inch.dev") or KDF proxy.
The KDF proxy must re-route requests to the 1inch API server and add an "Authorization" HTTP header set to "Bearer <1inch-API-KEY>" value.
@smk762

@dimxy dimxy self-assigned this Jul 23, 2025
@dimxy dimxy added status: in progress priority: medium Moderately important tasks that should be completed but are not urgent. feature: swap improvement: swap labels Jul 23, 2025
@smk762
Copy link

smk762 commented Aug 1, 2025

@dimxy can you please supply request examples of find_best_quote (and any other upcoming RPC not subject to significantly change) so I can draft the docs?

@shamardy
Copy link
Collaborator

shamardy commented Aug 1, 2025

can you please supply request examples of find_best_quote (and any other upcoming RPC not subject to significantly change) so I can draft the docs?

find_best_quote is for finding the most price-effective way to execute a trade, even if it requires intermediate token conversions. This is what we call Liquidity Routing (LR). It's for scenarios where a user wants to trade Token A for Token D, but the best available P2P / atomic swap orders are for trading Token B for Token C.

The full path for this method is experimental::liquidity_routing::find_best_quote

How It Works

The method analyzes a list of available P2P orders and determines the most economical path, which could be:

  1. Direct Atomic Swap: A direct trade if a suitable order exists (e.g., the user has Token B and wants Token C).
  2. LR Before Atomic Swap: An LR swap first (e.g., swapping Token A for Token B via a provider like 1inch), followed by the P2P atomic swap (Token B for Token C).
  3. LR After Atomic Swap: The P2P atomic swap first (Token B for Token C), followed by an LR swap on the received funds (Token C for Token D).
  4. LR Before and After: A combination of LR swaps both before and after the atomic swap (A → B, then B → C, then C → D).

It calculates the total_price for each valid path and returns the details of the most optimal one, allowing a user to execute a complex multi-step trade as a single operation.

User Scenario: Trading Across Different Liquidity Pools

Scenario

A user, Alex, wants to buy 1 BTC. He holds WETH on the Ethereum network. He checks the Komodo DeFi Framework orderbook and finds two promising orders from sellers:

  • Order 1: A seller is offering 1 BTC in exchange for 35,000 DAI.
  • Order 2: A seller is offering 1 BTC in exchange for 35,100 USDC.

Alex has WETH, not DAI or USDC. Manually, he would have to go to an external exchange, sell his WETH for DAI or USDC (paying fees), withdraw the tokens, and then place the P2P order. This is slow, complex, and error-prone.

Solution using the API

Alex's application can use the find_best_quote as the first step to automate this process.

  1. Get Orders: The application first calls an orderbook RPC (e.g., best_orders_rpc_v2) to get the list of available orders for BTC.

  2. Find the Best Quote: The application then calls find_best_quote with the following parameters:

    • method: "buy"
    • user_base: "BTC" (the asset Alex ultimately wants to receive)
    • user_rel: "WETH-ERC20" (the asset Alex has and wants to spend)
    • volume: "1" (the amount of BTC Alex wants to buy)
    • asks: The list of orders received in step 1 (the BTC-DAI and BTC-USDC orders).

What find_best_quote Does

  1. It sees that Alex has WETH, but the orders require DAI or USDC.
  2. It contacts the 1inch API to get quotes for swapping WETH → DAI and WETH → USDC.
  3. It calculates the total effective price for both paths.
    • Path 1: (Amount of WETH needed to get 35,000 DAI) / 1 BTC
    • Path 2: (Amount of WETH needed to get 35,100 USDC) / 1 BTC
  4. It compares these two total prices and selects the cheaper one.

The Response

The RPC returns a single, optimal path. For instance, if the WETH → DAI route is cheaper, the response will detail the two required steps:

  • lr_data_0: Details for the 1inch swap from WETH to DAI.
  • atomic_swap: Details for the P2P atomic swap of DAI for BTC.

Alex's application can then present this unified quote to him. If he accepts, the application would use the response data to call execute_routed_trade to start the multi-step swap.

Use Cases and Examples

Here are examples for different scenarios that find_best_quote can handle.

Use Case 1: Direct Atomic Swap (No LR Needed)

This is the simplest case where the user already holds the required asset.

Request: The user wants to buy 1 BTC and already has DAI. The provided order is a BTC-DAI ask order.

NOTE: find_best_quote RPC accepts orders received from the best_orders RPC. The best_orders RPC returns ask orders, if called with the "buy" parameter, and returns bid orders, if called with "sell". Those ask or bid orders should be passed as find_best_quote's "asks" or "bids" parameters, but "flattened" and extended with the base or rel coin ticker.

  1. "Flattening" orders means removing one top aggregation array level. For example, the original ask orders are returned like that:
"orders": {
  "DAI": [
        {
          "coin": "DAI",
          "address": {
             "address_type": "Transparent",
             "address_data": "0x123...abc"
          },
          "price": "35000",
          "pubkey": "maker_pubkey",
       }
   ]
}

.. should be flattened (removed the level of aggregation of orders by the "DAI" ticker) and sent in the find_best_quote "asks" parameter (see find_best_quote samples):

"orders" : [
  {
     "coin": "DAI",
         "address": {
         "address_type": "Transparent",
         "address_data": "0x123...abc"
      },
      "price": "35000",
      "pubkey": "maker_pubkey",
   }
]

Same should be done for bids.
TODO: we may lift this requirement of orders array flattening and do this internally in find_best_quote.

  1. Extending best_orders resulting orders with base or rel coin ticker: when you pass results of the best_orders RPC into the find_best_quote RPC you need to add an extra base ticker for asks and rel ticker for bids (see "asks" or "bids" parameter in find_best_quote samples).
    TODO: this is needed because the best_quote RPC does not return the base or rel ticker along with the order list but we may add this ticker to the response.
{
  "user_base": "BTC",
  "user_rel": "DAI",
  "method": "buy",
  "volume": "1",
  "asks": [
    {
      "base": "BTC",
      "orders": [
        {
          "coin": "DAI",
          "address": {
            "address_type": "Transparent",
            "address_data": "0x123...abc"
          },
          "price": "35000",
          "pubkey": "maker_pubkey",
          "uuid": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
          "is_mine": false,
          "base_max_volume": "1.5",
          "base_min_volume": "0.1",
          "rel_max_volume": "52500",
          "rel_min_volume": "3500",
          "conf_settings": null
        }
      ]
    }
  ],
  "bids": []
}

Response: No LR is needed, so lr_data_0 and lr_data_1 are null.

{
  "lr_data_0": null,
  "lr_data_1": null,
  "atomic_swap": {
    "volume": "1",
    "base": "DAI",
    "rel": "BTC",
    "price": "35000",
    "method": "sell",
    "order_uuid": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "match_by": null,
    "order_type": null
  },
  "total_price": "35000"
}

Use Case 2: LR Before Atomic Swap (LR_0)

This matches our user scenario. The user has one token (user_rel) but the P2P order requires another.

Request: The user wants to buy 1 BTC with WETH. The best order requires DAI.

{
  "user_base": "BTC",
  "user_rel": "WETH-ERC20",
  "method": "buy",
  "volume": "1",
  "asks": [
    {
      "base": "BTC",
      "orders": [
        {
          "coin": "DAI",
          "address": {
            "address_type": "Transparent",
            "address_data": "0x123...abc"
          },
          "price": "35000",
          "pubkey": "maker_pubkey",
          "uuid": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
          "is_mine": false,
          "base_max_volume": "1.5",
          "base_min_volume": "0.1",
          "rel_max_volume": "52500",
          "rel_min_volume": "3500",
          "conf_settings": null
        }
      ]
    }
  ],
  "bids": []
}

Response: The response includes details for the WETH → DAI swap in lr_data_0.

{
  "lr_data_0": {
    "src_amount": "12.52",
    "dst_amount": {
      "amount": "35000.123"
    },
    "src_token": {
      "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
      "symbol": "WETH",
      "name": "Wrapped Ether",
      "decimals": 18,
      "symbol_kdf": "WETH-ERC20"
    },
    "dst_token": {
      "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
      "symbol": "DAI",
      "name": "Dai Stablecoin",
      "decimals": 18,
      "symbol_kdf": "DAI"
    },
    "tx": null,
    "gas": 150000
  },
  "lr_data_1": null,
  "atomic_swap": {
    "volume": "35000.123",
    "base": "DAI",
    "rel": "BTC",
    "price": "35000",
    "method": "sell",
    "order_uuid": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
    "match_by": null,
    "order_type": null
  },
  "total_price": "12.52"
}

Use Case 3: LR After Atomic Swap (LR_1)

The user has the token required for the P2P swap but wants the final asset to be a different token.

Request: The user wants to sell 1 BTC and ultimately receive USDC. The best available order is from a buyer who will pay in DAI.

{
  "user_base": "BTC",
  "user_rel": "USDC",
  "method": "sell",
  "volume": "1",
  "asks": [],
  "bids": [
    {
      "rel": "BTC",
      "orders": [
        {
          "coin": "DAI",
          "address": {
            "address_type": "Transparent",
            "address_data": "0x123...abc"
          },
          "price": "0.00002857",
          "pubkey": "maker_pubkey",
          "uuid": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
          "is_mine": false,
          "base_max_volume": "52500",
          "base_min_volume": "3500",
          "rel_max_volume": "1.5",
          "rel_min_volume": "0.1",
          "conf_settings": null
        }
      ]
    }
  ]
}

Response: The response includes details for the DAI → USDC swap in lr_data_1.

{
  "lr_data_0": null,
  "lr_data_1": {
    "src_amount": "35000",
    "dst_amount": {
      "amount": "34995"
    },
    "src_token": {
      "address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
      "symbol": "DAI",
      "name": "Dai Stablecoin",
      "decimals": 18,
      "symbol_kdf": "DAI"
    },
    "dst_token": {
      "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "symbol": "USDC",
      "name": "USD Coin",
      "decimals": 6,
      "symbol_kdf": "USDC"
    },
    "tx": null,
    "gas": 120000
  },
  "atomic_swap": {
    "volume": "1",
    "base": "BTC",
    "rel": "DAI",
    "price": "0.00002857",
    "method": "sell",
    "order_uuid": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
    "match_by": null,
    "order_type": null
  },
  "total_price": "34995"
}

Use Case 4: Cross-Chain Swap with LR Before and After (LR_0 and LR_1)

This is the most advanced use case, demonstrating how liquidity routing can be used to bridge assets across two different EVM-compatible blockchains. The P2P atomic swap acts as the trustless bridge between the two ecosystems.

Scenario:
A user, Alex, holds WETH on the Polygon network. He has identified a promising new token, JOE, on the Avalanche network that he wants to acquire. There are no direct P2P orders for WETH/JOE. However, he finds an efficient P2P order from a maker who is selling AVAX (the native coin of the Avalanche network) in exchange for MATIC (the native coin of Polygon).

Alex can use the find_best_quote to execute a complex, three-step trade in a single logical operation:

  1. LR_0 (on Polygon): Swap his WETH for MATIC using 1inch.
  2. Atomic Swap (cross-chain): Use the newly acquired MATIC to atomically swap for the maker's AVAX.
  3. LR_1 (on Avalanche): Swap the received AVAX for his target token, JOE, using 1inch.

Request: Alex wants to sell 5 WETH on Polygon and wants to know how many JOE tokens on Avalanche he will receive by routing through the MATIC/AVAX P2P order.

{
  "user_base": "WETH-ERC20",
  "user_rel": "JOE-ERC20",
  "method": "sell",
  "volume": "5",
  "asks": [
    {
      "base": "AVAX",
      "orders": [
        {
          "coin": "MATIC",
          "address": {
            "address_type": "Transparent",
            "address_data": "0x123...abc"
          },
          "price": "500",
          "pubkey": "maker_pubkey_on_avax",
          "uuid": "d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8g",
          "is_mine": false,
          "base_max_volume": "100",
          "base_min_volume": "10",
          "rel_max_volume": "50000",
          "rel_min_volume": "5000",
          "conf_settings": null
        }
      ]
    }
  ],
  "bids": []
}

Response: The response will detail all three steps of the cross-chain swap.

{
  "lr_data_0": {
    "src_amount": "5",
    "dst_amount": {
      "amount": "21428.5"
    },
    "src_token": {
      "address": "0x7ceb23fd6bc0add59e62ac25578270cff1b9f619",
      "symbol": "WETH",
      "name": "Wrapped Ether",
      "decimals": 18,
      "symbol_kdf": "WETH-ERC20"
    },
    "dst_token": {
      "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
      "symbol": "MATIC",
      "name": "Matic",
      "decimals": 18,
      "symbol_kdf": "MATIC"
    },
    "tx": null,
    "gas": 145000
  },
  "atomic_swap": {
    "volume": "21428.5",
    "base": "MATIC",
    "rel": "AVAX",
    "price": "500",
    "method": "sell",
    "order_uuid": "d4e5f6a7-b8c9-4d0e-1f2a-3b4c5d6e7f8g",
    "match_by": null,
    "order_type": null
  },
  "lr_data_1": {
    "src_amount": "42.857",
    "dst_amount": {
      "amount": "2995.5"
    },
    "src_token": {
      "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
      "symbol": "AVAX",
      "name": "Avalanche",
      "decimals": 18,
      "symbol_kdf": "AVAX"
    },
    "dst_token": {
      "address": "0x6e84a6216eA6dACC71eE8E6b0a5B7322EEbC0fDd",
      "symbol": "JOE",
      "name": "JOE",
      "decimals": 18,
      "symbol_kdf": "JOE-ERC20"
    },
    "tx": null,
    "gas": 155000
  },
  "total_price": "599.1"
}

Conceptual Use Case: Bridging EVM and Non-EVM Chains

While the current implementation focuses on 1inch for EVM-to-EVM liquidity routing, the underlying architecture is designed to be extensible. The find_best_quote acts as an aggregator of aggregators. This means it can, in the future, incorporate other liquidity providers for different ecosystems, such as Jupiter for the Solana network.

Scenario:
Imagine a user wants to swap WETH on Ethereum for SOL on Solana. A direct cross-chain atomic swap between these two assets might not have a liquid P2P market. However, there is often deep liquidity for stablecoins like USDC on both chains.

A future version of the find_best_quote could facilitate this trade by constructing the following path:

  1. LR_0 (1inch on Ethereum): The user's WETH is swapped for USDC (ERC20) using the 1inch aggregator.
  2. Atomic Swap (Komodo DeFi): The user's USDC (ERC20) is atomically swapped for a maker's USDC (SPL) on the Solana network. This P2P swap acts as the trustless bridge for the stablecoin.
  3. LR_1 (Jupiter on Solana): The received USDC (SPL) is then swapped for SOL using the Jupiter aggregator.

Setup Required for 1inch Integration

To use the liquidity routing features powered by 1inch, some initial setup is required in KDF.

1. KDF/MM2 Configuration (MM2.json)

Your MM2 configuration file must contain the necessary information for the software to communicate with the 1inch API.

API Endpoint URL: You need to specify the 1inch API endpoint, this can be provided through komodo proxy. The code reads this from the 1inch_api field in the configuration file.

{
  "1inch_api": "https://api.1inch.dev"
}

API Key: The 1inch API requires an authentication key. The KDF codebase includes the logic to send this key as a Bearer token in the Authorization header. However, this logic is enabled only when the application is compiled with the test-ext-api feature flag. For testing, you must ensure your build process includes this feature. The key itself is expected to be in an environment variable named ONE_INCH_API_TEST_AUTH.

Add Configuration for All Required Coins and tokens: Every token involved in the swap path must be enabled in your MM2 configuration. For the scenario above, your coins array would need to include configurations for WETH-ERC20, DAI, AAVE-ERC20, and USDC. MM2 uses this configuration to find contract addresses, decimals, and other essential on-chain information. Normally this is done by wallet developers.

2. Wallet and On-Chain Setup

Before executing a swap, the user's wallet must be prepared.

Fund the Wallet:

  • The wallet must hold a sufficient balance of the source token (e.g., WETH in our scenario).
  • The wallet must also hold a sufficient balance of the native gas token of the chain (e.g., ETH on Ethereum, MATIC on Polygon) to pay for transaction fees for both the approval and the swap itself.

Activate (enable) coins and tokens used in swaps with liquidity routing
Users should first enable in their wallets coins and tokens which will be used in finding the best swap path and later in the swap with LR.

Handling allowance for tokens used in swaps
The execute_route_trade RPC will set the allowance for tokens used in a liquidity routing swap, to allow spending tokens by the liquidity routing contracts on your behalf.

In summary, a successful integration requires configuring the API endpoint and key, enabling all relevant coins in MM2, and ensuring the user's wallet is funded.

@shamardy
Copy link
Collaborator

shamardy commented Aug 1, 2025

@smk762 please wait for @dimxy to approve my comment before using it in the docs PR, he might also modify if first before approval.

@shamardy
Copy link
Collaborator

shamardy commented Aug 1, 2025

@smk762 About this

API Key: The 1inch API requires an authentication key. The KDF codebase includes the logic to send this key as a Bearer token in the Authorization header. However, this logic is enabled only when the application is compiled with the test-ext-api feature flag. For testing, you must ensure your build process includes this feature. The key itself is expected to be in an environment variable named ONE_INCH_API_TEST_AUTH.

1inch API should be added to komodo proxy and then we will require no key in the headers from KDF side and it will work without the special feature, test-ext-api is only for testing 1inch directly through KDF.

Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First review from my side! Will continue reviewing this while it's being tested. If any of the comments you want to fix in next PRs, it's fine, but we need a tracking issue for all these things.

pub const fn eth_special_contract() -> &'static str {
ONE_INCH_ETH_SPECIAL_CONTRACT
}
} // TODO: must use the 1inch call, not a const (on zk chain it's not const)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need a tracking issue for this

/// The GUI should pick tokens which resides in the same chains with user_base and/or user_rel and query "best_orders" RPC (maybe multiple times).
/// The "best_orders" results are asks or bids which can be passed into this RPC.
///
/// TODO: develop a more convenient RPC to find ask and bid orders for finding the best swap with LR.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please open a tracking issue for all the todos in this PR.

Comment on lines +116 to +117
// TODO: implement later
// trade_fee: ...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say this is important for LR, is it implemented in next PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, have not implemented this but will certainly do in the next PR

.into_iter()
.zip(prices_in_series)
.map(|((src, dst), series)| {
let dst_price = cross_prices_average(series); // estimate SRC/DST price as average from series
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that we still use the average price not the close price

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I added a new cross_prices_close function in my feature branch.
But, in fact I had to switch back to the average and even had to extend the depth for price history. Otherwise swaps fail too often because the cross_prices call returns just an empty result. When I changed the depth from 1 to 10 I have not seen empty responses yet. (Maybe this is the "correlation does not equal causation" rule but we'll see.)

let dex_fee_rate = DexFee::dex_fee_rate(&taker_ticker, &maker_ticker);
volume_with_fees / (MmNumber::from("1") + dex_fee_rate) // Deduct dex fee to get the atomic swap taker amount
} else {
user_sell_amount.clone() // TODO: use atomic_swap_taker_amount
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain this todo?


/// Select the best swap path, by minimum of total swap price, including LR steps and atomic swap)
#[allow(clippy::result_large_err)]
async fn select_best_swap(self, ctx: &MmArc) -> MmResult<(LrSwapCandidateInfo, MmNumber), LrSwapError> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do all 1inch swaps use the same gas amount? I see that the ClassicSwapData fetched from the 1inch API provides an estimated gas cost, and this should be factored in, as a swap with a better price might have a higher gas cost, making it more expensive overall

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The gas limits returned from the find_best_quote are not used in the execute_routed_trade RPC as in the trade RPC a new 1inch request is made, to get the actual 1inch swap transaction details. The gas limit is used from this new request.

@dimxy
Copy link
Collaborator Author

dimxy commented Aug 11, 2025

@smk762 please wait for @dimxy to approve my comment before using it in the docs PR, he might also modify if first before approval.

I edited #2545 (comment) and added my changes:
a note about how to extend results returned by best_orders rpc to pass into find_best_quote RPC,
and removed the need to handle token allowance by the User as the execute_routed_trade rpc does it by itself
@smk762 @shamardy

dimxy added 10 commits August 12, 2025 15:59
* dev:
  chore(rust 1.89): make CI clippy/fmt pass (wasm32, all-targets) (#2581)
  fix(utxo): deserialize sapling root for PIVX block headers (#2572)
  improvement(dep-stack): security bumps (#2562)
  fix(utxo): correct block header deserialization for AuxPow and KAWPOW coins (#2563)
* dev:
  fix(utxo): calculate min_trading_vol based on fixed tx fees (#2564)
  feat(protocol): [0] solana support (#2586)
  fix(utxo): fix header deserialization; guard AuxPoW (#2583)
* dev:
  fix build script failing to find .git/HEAD (#2601)
  refactor(EVM): rename fn, fix timeouts, add activation req validation (#2543)
  improvement(`static mut`s): `static mut` removal (#2590)
  fix(orders): set subscription on kickstart and skip GC of own pubkeys (#2597)
  fix(ordermatch): ignore loop-back; clear on null root; reject stale keep-alives (#2580)
  fix(clippy): fix clippy warnings for #2565 (#2589)
  fix(Trezor): fix utxo and eth calls due to firmware changes (#2565)
@smk762
Copy link

smk762 commented Sep 8, 2025

1inch API should be added to komodo proxy and then we will require no key in the headers from KDF side and it will work without the special feature, test-ext-api is only for testing 1inch directly through KDF.

Please add any details to this issue (and DM me API keys etc) and I'll set it up KomodoPlatform/komodo-defi-proxy#28

@dimxy
Copy link
Collaborator Author

dimxy commented Sep 8, 2025

1inch API should be added to komodo proxy and then we will require no key in the headers from KDF side and it will work without the special feature, test-ext-api is only for testing 1inch directly through KDF.

Please add any details to this issue (and DM me API keys etc) and I'll set it up KomodoPlatform/komodo-defi-proxy#28

Added a note to this PR description.
For testing I use a free API key limited to 1 req/sec and 100K req per month.

@github-actions
Copy link

@smk762
Please review it again.

@github-actions github-actions bot added the [] label Nov 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[] feature: swap improvement: swap priority: medium Moderately important tasks that should be completed but are not urgent. status: pending review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants