# Subquery Integration Tutorial SubQuery provides a [quick start tutorial](https://academy.subquery.network/quickstart/quickstart_chains/cosmos-osmosis.html) that indexes all swaps on Osmosis' on chain DEX. This tutorial builds on the quickstart and adds indexing for `SwapExactAmountOut`. There are 3 steps when creating a SubQuery project. * Update the schema file * Update the project manifest file * Update the mappings file ## 0. Update end point & block height endpoint to be used can be found in project.ts query latest block height and make sure node has the block information https://rpc.osmosis.zone/status? edit startBlock to latest height ## 1. Update `graphql` schema Add new types we want to be parsing to the existing schema.graphql file. ``` type SwapOut @entity { id: ID! sender: String! txHash: String! blockHeight: BigInt! tokenOutDenom: String tokenOutAmount: BigInt tokenInMax: BigInt! swapOutRoutes: [SwapOutRoute] @derivedFrom(field: "swap") #This is virtual field } type SwapOutRoute @entity { id: ID! pool: Pool! swap: SwapOut! tokenInDenom: String! tokenOutDenom: String } type PoolOut @entity { id: ID! swapOutRoutes: [SwapOutRoute] @derivedFrom(field: "pool") #This is virtual field } ``` Then run `yarn codegen` to generate code based off this new schema. > When you make any changes to the schema file, do not forget to regenerate your types directory. ## 2. Update the project manifest file (`project.ts`) a) Declare the chain types. These point to protobuf files that defines the format of the message to help the SubQuery project understand how to parse the data. The following chain types should be added to the existing chain types. Double check that the various .proto files are available and accessible by the project. https://github.com/osmosis-labs/osmosis/blob/main/proto/osmosis/gamm/v1beta1/tx.proto#L16 ``` chaintypes: new Map([ [ "osmosis.gamm.v1beta1", { file: "./proto/osmosis/gamm/v1beta1/tx.proto", messages: ["MsgSwapExactAmountIn", "MsgSwapExactAmountOut"], }, ], [ " osmosis.poolmanager.v1beta1", { // needed by SwapAmountOutRoute file: "./proto/osmosis/poolmanager/v1beta1/swap_route.proto", messages: ["SwapAmountOutRoute"], }, ], [ " osmosis.poolmanager.v1beta1", { // needed by MsgSwapExactAmountIn file: "./proto/osmosis/poolmanager/v1beta1/swap_route.proto", messages: ["SwapAmountInRoute"], }, ], [ "cosmos.base.v1beta1", { // needed by MsgSwapExactAmountIn file: "./proto/cosmos/base/v1beta1/coin.proto", messages: ["Coin"], }, ], ]), }, ``` Add a handler in `dataSources`. This handler will be triggered when the filter criteria is met. ``` { handler: "handleOutMsg", kind: CosmosHandlerKind.Message, filter: { type: "/osmosis.gamm.v1beta1.MsgSwapExactAmountOut", }, }, ``` ## 3. Update the mappings file (`mappingHandlers.ts`) 3. Define handler for swap out message. This is the function that will be executed when a swap out message is encountered in the manifest file. ``` export async function handleOutMsg( msg: MsgSwapExactAmountOutMessage ): Promise<void> { // You can see an example record here https://www.mintscan.io/osmosis/txs/6A22C6C978A96D99FCB08826807C6EB1DCBDCEC6044C35105B624A81A1CB6E24?height=9798771 logger.info(`New Swap Out Message received at block ${msg.block.header.height}`); // logger.info(JSON.stringify(msg.tx.tx.events)); // You can use this to preview the data // We first create a new swap record const swap = SwapOut.create({ id: `${msg.tx.hash}-${msg.idx}`, txHash: msg.tx.hash, blockHeight: BigInt(msg.block.block.header.height), sender: msg.msg.decodedMsg.sender, tokenOutDenom: msg.msg.decodedMsg.tokenOut?.denom, tokenOutAmount: msg.msg.decodedMsg.tokenOut ? BigInt(msg.msg.decodedMsg.tokenOut.amount) : undefined, tokenInMax: BigInt(msg.msg.decodedMsg.tokenInMaxAmount), }); // Save this to the DB await swap.save(); // Create swap routes from the array on the message let lastTokenOutDenom = swap.tokenOutDenom; for (const route of msg.msg.decodedMsg.routes) { const index = msg.msg.decodedMsg.routes.indexOf(route); // Check that the pool aready exists const pool = await checkGetPoolOut(route.poolId.toString()); const swapRoute = SwapOutRoute.create({ id: `${msg.tx.hash}-${msg.idx}-${index}`, poolId: pool.id, swapId: swap.id, tokenInDenom: route.tokenInDenom, tokenOutDenom: lastTokenOutDenom, }); lastTokenOutDenom = route.tokenInDenom; await swapRoute.save(); } } ``` yarn codegen yarn build Once all the changes have been completed, build the project with the command `yarn build` and then start the project with the command `yard start:docker`. (Ensure Docker is running). To test the project, open up the playground at `http://localhost:3000/` and run the following graphql query: ``` { query { swaps(first: 5) { nodes { id sender tokenOutDenom tokenOutAmount tokenInMax swapRoutes(first: 5) { totalCount } } } } } ```