At swap.coffee, we not only aggregate DEXs but also support yield protocols. We are now expanding our yield aggregator and seeking partners interested in integrating with us. Upon integration, you will gain:
- Partnership with a tier-1 protocol on the TON network.
- Access to thousands of new users who use the swap.coffee platform daily.
- A significant increase in Total Value Locked (TVL) for your protocol.
- Fork the project and clone it. If you prefer, you can create a private project. In that case, add the dev
team to your repository:
@glcanvasand@RinesThaix. - Create a new branch in your repo called
integration/<your-protocol-name>. - Implement and test the required classes (see below).
- Submit a merge request and assign it to the dev team.
- Notify one of the admins from the Telegram chat: https://t.me/swapcoffee_dev_chat about your merge request.
- We will review your request. If there are any issues, we will comment on them in the pull request. You will need to resolve them.
- After that, your protocol will appear on the Earn page.
- Download and install a JetBrains IDE (the Community version is enough).
- Open the project in IntelliJ IDEA and let the IDE download the dependencies.
- Build the containers from
docker-compose.yml. - Launch the
Application.kt. - The Swagger UI is available at http://localhost:8080/swagger-ui.
- Define the objects used in GET and POST requests and internal data classes.
- Create a service to load pool data, trading statistics, and other information.
- Develop a service that responds to REST API queries and integrate it with
YieldService. - Implement a tracking process to monitor transactions.
The project consists of several components, including workers, parsers, handlers, background loaders, and a REST API.
- The StonFi integration example is located in the
src/main/kotlin/com/example/protocols/stonfifolder. - The empty classes for your new protocol, which you need to implement, are located in the
src/main/kotlin/com/example/protocols/newprotocoldirectory.
The StonfiV1Parser identifies transactions with an opcode of 0x25938561 and parses them, and creates a new pool if
necessary.
It also updates trading metrics.
Next, the data is processed in the background and distributed among backend servers using the LoaderService.
The LoaderService periodically calls the doWork function, which can either load
all data from the database or fetch it from an external API.
Let’s examine the StonfiV1LoaderService class. It loads all known pools, calculates trading statistics, and then loads
boosts. This data is subsequently published to the YieldBoostsService and YieldTradingStatisticsService.
If you prefer not to implement custom parsers (BlockchainRecordParser), but prefer to use external APIs to load data,
ensure that the pools are saved in the liquidity_pools table, because it will be used later by YieldService.
The YieldService is a critical component of the system. All API queries are sent to this service.
The YieldService retrieves data from various protocol sources, fetches boosts and metrics, and responds to user search
queries, handling all user requests.
The YieldService exposes the following four endpoints:
GET /v1/yield/pools: Returns a list of pools based on specified criteria. The response should include only basic pool details, such as name, protocol, tokens, and trading metrics.GET /v1/yield/pool/{pool_address}: Returns detailed and actual information about a pool, including:- Active boosts
- Fees
- Reserves
- Total supply
GET /v1/yield/pool/{pool_address}/{user_address}: Returns user-specific information about the pool, including:- User’s balance
- User rewards
- Deposits
- User's locked tokens
POST /v1/yield/pool/{pool_address}/{user_address}: Creates transactions to interact with the pool, supporting actions such as deposits, withdrawals, and claiming rewards.
These endpoints located in the yield-spec.yaml. Go through the file and add resolve all TODO.
Please, note:
YieldSearchResponseApi, YieldUserDetailApi, and InteractionRequestApi objects use a oneOf structure, where
resolution is based on the yieldTypeResolver field. Do not use the yieldTypeResolver field in your own objects,
as it is
reserved for the system.
Next, you must define protocol in file YieldProtocols.kt.
Specify data class which corresponds to this protocol in YieldPoolFields.kt.
Next, consider boosts (farms). If you have boosts structure which significantly differs from YoeldBoostDex, define
your own at YieldBoost.kt.
To load new pools and calculate trading metrics, you have two options:
- Use a Parser with
LoaderService: parse latest transactions from blockchain and process it in theLoaderService. To do this:- Implement the
BlockchainRecordParserinterface using theNewProtocolRecordParsertemplate. This parser should be triggered when a transaction belongs to your protocol and should return trading metrics and new pools asBlockchainRecords. - Implement the
LoaderServiceusing theLoaderServiceNewProtocoltemplate. The service will periodically fetch new data, calculate metrics, and update boosts. For more details, refer toStonfiV1LoaderService.
- Implement the
- Direct Implementation in
LoaderService: Fetch data directly within theLoaderServiceusingAsyncHttpClientfrom external sources, such as your API or the https://indexer.swap.coffee/swagger-ui endpoint.
Once new pools are fetched, they must be stored in the database. Refer to StonfiV1LoaderService for more information.
Create a custom service, such as YourProtocolNameService, to respond to REST API requests. This service should:
- Return Detailed Pool Information: Since
LoaderServiceupdates periodically, it cannot provide real-time data liketotal_supplyandreserve_ratio. Your service should fetch and return the latest data for users. - Return list of pools where user has a liquidity: Because we can't store all user's data, and support up-to-date information about user's positions on our side, we'll ask you to upload it through the Indexer or through your REST API.
- Provide User Information: swap.coffee does not store latest user information in its database. Use the Indexer API or query a TON node to retrieve user-specific data about the pool.
- Create Transactions for Pool Interaction: This service must create transactions which will help users to interact with your service.
While YourProtocolNameService creation, you may define any functions and pass any parameters to your service.
However, ensure you add your new service to YieldService and extend the following functions:
getUserDetails, getAllPoolsForUser, processUserRequest, mapper, and mapperDetail.
To track transaction status, implement a tracing process using the StatusHandler class. This class is passed to the
parser to resolve transaction status. Currently, two types of resolvers are available:
StatusHandlerOnReceive: Marks a transaction as successful when it is executed on the blockchain.StatusHandlerEmptyOutputEvents: Marks a transaction asresolveAsSuccessonly if the sender address matches the message sender and there are no output events.
When a transaction is created, it must be registered in the system for later resolution. Use the
StatusObserverServiceStub to define the following parameters:
onAddress: The account on which the transaction will execute.queryId: The query ID from theStatusServiceStub.- A list of
StatusHandlersthat will execute whenonAddressreceives a message withqueryId.
Use StonfiV1Service#closeUserPosition as a example.
At the end of the process, you need to:
- Update
yield-spec.yamlfile. - Implement the
LoaderServiceandBlockchainRecordParserclasses. - Implement the
YourProtocolNameService(e.g.,StonfiV1Service), which creates transactions and returns up-to-date pool and user data. - Update the
YieldServiceto support your new service. - Create handlers to monitor transactions using the
StatusHandlerclass.
That's okay. Kotlin is very similar to TypeScript and has a rich documentation: https://kotlinlang.org/docs/home.html. Additionally, we have written an example of integration with Stone.fi V1 that you can refer to. If you have any questions, please feel free to ask them here: https://t.me/swapcoffee_dev_chat.
Yes, it does.
Not necessarily, but we recommend that you launch your code and test it by making REST API requests.
You can ask any questions at: https://t.me/swapcoffee_dev_chat.