{"id":14029956,"url":"https://github.com/osmosis-labs/sqs","last_synced_at":"2025-05-02T18:30:52.991Z","repository":{"id":215371680,"uuid":"706346320","full_name":"osmosis-labs/sqs","owner":"osmosis-labs","description":"Sidecar Query Server","archived":false,"fork":false,"pushed_at":"2025-05-01T12:13:31.000Z","size":137160,"stargazers_count":17,"open_issues_count":25,"forks_count":15,"subscribers_count":12,"default_branch":"v28.x","last_synced_at":"2025-05-01T13:25:40.874Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/osmosis-labs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-10-17T19:09:19.000Z","updated_at":"2025-04-24T07:09:58.000Z","dependencies_parsed_at":"2024-04-19T05:33:13.730Z","dependency_job_id":"35af52ec-15fd-49ba-af7c-50193a8a894d","html_url":"https://github.com/osmosis-labs/sqs","commit_stats":null,"previous_names":["osmosis-labs/sqs"],"tags_count":132,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osmosis-labs%2Fsqs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osmosis-labs%2Fsqs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osmosis-labs%2Fsqs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/osmosis-labs%2Fsqs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/osmosis-labs","download_url":"https://codeload.github.com/osmosis-labs/sqs/tar.gz/refs/heads/v28.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252088226,"owners_count":21692762,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-11T21:01:21.995Z","updated_at":"2025-05-02T18:30:49.080Z","avatar_url":"https://github.com/osmosis-labs.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Sidecar Query Server\n\nThis is a sidecar query server that is used for performing query tasks outside of the main chain.\nThe high-level architecture is that the chain reads data at the end of the block, parses it\nand then stores it in RAM.\n\nThe sidecar query server then reads the parsed data from cache and serves it to the client\nvia HTTP endpoints.\n\nThe use case for this is performing certain data and computationally intensive tasks outside of\nthe chain node or the clients. For example, routing falls under this category because it requires\nall pool data for performing the complex routing algorithm.\n\n![alt text](docs/image.png)\n\n## Integrator Guide\n\nFollow [this link](https://hackmd.io/@osmosis/HkyIHvCH6) to find a guide on how to\nintegrate with the sidecar query server.\n\n(Note: `apt install nano make build-essential gcc git jq chrony tar curl lz4 wget`)\n\n## Custom CosmWasm Pools\n\nThe sidecar query server supports custom CosmWasm pools.\nThere are two options of integrating them into the Osmosis router:\n\n1. Implement a pool type similar to [transmuter](https://github.com/osmosis-labs/sqs/blob/e95c66e3ee6a22d57118c74a384253f016a9bb85/router/usecase/pools/routable_transmuter_pool.go#L19)\n    - This assumes that the pool quote and spot price logic is trivial enough for implementing\n      it directly in SQS without having to interact with the chain.\n2. Utilize a [generalized CosmWasm pool type](https://github.com/osmosis-labs/sqs/blob/437086c683f4f90d915f7e042617552c68410796/router/usecase/pools/routable_cw_pool.go#L24)\n    - This assumes that the pool quote and spot price logic is complex enough for requiring\n      interaction with the chain.\n    - For quotes and spot prices, SQS service would make network API queries to the chain.\n    - This is the simplest approach but it is less performant than the first option.\n    - Due to performance reasons, the routes containing these pools are not utilized in\n      more performant split quotes. Only direct quotes are supported.\n\nTo enable support for either option, a [config.json](https://github.com/osmosis-labs/sqs/blob/437086c683f4f90d915f7e042617552c68410796/config.json#L22-L25)\nmust be updated accordingly. For option 1, add a new field under `pools` and make a PR propagating\nthis config to be able to create a new custom pool type similar to transmuter. For option 2, simply\nadd your code id to `general-cosmwasm-code-ids` in this repository. Tag `@p0mvn` in the PR and\nfollow up that the config is deployed to the sidecar query server service in production.\n\n## Osmosis Deployments\n\nOur team maintains 3 SQS deployment environments.\n\n### Production\n\n`https://sqs.osmosis.zone`\n\nThis is a geo-distributed deployment across 3 regions that is used by the\nproduction application `https://app.osmosis.zone`.\n\nIt operates on data from `osmosis-1` mainnet.\n\nNote that in this environment we block all endpoints at nginx level except for:\n\n-   `/router/quote`\n-   `/router/custom-direct-quote`\n-   `/tokens/prices`\n-   `/pools`\n-   all debug and infra endpoints\n\nThere is swagger available [here](https://sqs.osmosis.zone/swagger/index.html#/default/get-token-metadata)\n\n### Staging\n\n`https://sqs.stage.osmosis.zone`\n\nThis is a deployment with 2 nodes that is used by our stage app\n`https://stage.osmosis.zone/`. It is less stable and may experience downtime\ndue to experimental features.\n\nIt operates on data from `osmosis-1` mainnet.\n\nNote that in this environment we block all endpoints at nginx level except for:\n\n-   `/router/quote`\n-   `/router/custom-direct-quote`\n-   `/tokens/prices`\n-   `/pools`\n-   all debug and infra endpoints\n\n### Testnet\n\n`https://sqs.testnet.osmosis.zone`\n\nThis is a testnet deployment made against `osmo-test-5` testnet state.\n\nThis environment exposes all endpoints listed below.\n\n## Supported Endpoints\n\nNote that there are more endpoints that can be found in the codebase but we\ndo not expose them publicly in out production environment.\n\n### Pools Resource\n\n1. GET `/pools?IDs=\u003cIDs\u003e`\n\nDescription: Returns of pools if IDs parameter is not given. Otherwise,\nbatch fetches specific pools by the given parameter pool IDs.\n\nParameter: `IDs` - the list of pool IDs to batch fetch.\n\n```\ncurl \"http://localhost:9092/pools?IDs=1,2\" | jq .\n[\n  {\n    \"chain_model\": {\n      \"address\": \"osmo1mw0ac6rwlp5r8wapwk3zs6g29h8fcscxqakdzw9emkne6c8wjp9q0t3v8t\",\n      \"id\": 1,\n      \"pool_params\": {\n        \"swap_fee\": \"0.002000000000000000\",\n        \"exit_fee\": \"0.000000000000000000\"\n      },\n      \"future_pool_governor\": \"24h\",\n      \"total_weight\": \"1073741824000000.000000000000000000\",\n      \"total_shares\": {\n        \"denom\": \"gamm/pool/1\",\n        \"amount\": \"68705408290810473783205087\"\n      },\n      \"pool_assets\": [\n        {\n          \"token\": {\n            \"denom\": \"ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2\",\n            \"amount\": \"1099147835604\"\n          },\n          \"weight\": \"536870912000000\"\n        },\n        {\n          \"token\": {\n            \"denom\": \"uosmo\",\n            \"amount\": \"6560821009725\"\n          },\n          \"weight\": \"536870912000000\"\n        }\n      ]\n    },\n    \"balances\": [\n      {\n        \"denom\": \"ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2\",\n        \"amount\": \"1099147835604\"\n      },\n      {\n        \"denom\": \"ibc/9989AD6CCA39D1131523DB0617B50F6442081162294B4795E26746292467B525\",\n        \"amount\": \"1000000000\"\n      },\n      {\n        \"denom\": \"ibc/B9E0A1A524E98BB407D3CED8720EFEFD186002F90C1B1B7964811DD0CCC12228\",\n        \"amount\": \"999800\"\n      },\n      {\n        \"denom\": \"uosmo\",\n        \"amount\": \"6560821009725\"\n      }\n    ],\n    \"type\": 0,\n    \"spread_factor\": \"0.002000000000000000\"\n  },\n  ...\n]\n```\n\n### Router Resource\n\n1. GET `/router/quote?tokenIn=\u003ctokenIn\u003e\u0026tokenOutDenom=\u003ctokenOutDenom\u003e?singleRoute=\u003csingleRoute\u003e`\n\nDescription: returns the best quote it can compute for the given tokenIn and tokenOutDenom. If `singRoute` parameter is set to true, it gives the best single\nquote while excluding splits\n\nParameters:\n\n-   `tokenIn` the string representation of the sdk.Coin for the token in\n-   `tokenOutDenom` the string representing the denom of the token out\n-   `singleRoute` (optional) boolean flag indicating whether to return single routes (no splits).\n    False (splits enabled) by default.\n-   `humanReadable` (optional) boolean flag indicating whether a human readable denom is given as opposed to chain.\n\nResponse example:\n\n```bash\ncurl \"https://sqs.osmosis.zone/router/quote?tokenIn=1000000uosmo\u0026tokenOutDenom=uion?singleRoute=false\" | jq .\n{\n  \"amount_in\": {\n    \"denom\": \"uosmo\",\n    \"amount\": \"1000000\"\n  },\n  \"amount_out\": \"1803\",\n  \"route\": [\n    {\n      \"pools\": [\n        {\n          \"id\": 2,\n          \"type\": 0,\n          \"balances\": [],\n          \"spread_factor\": \"0.005000000000000000\",\n          \"token_out_denom\": \"uion\",\n          \"taker_fee\": \"0.001000000000000000\"\n        }\n      ],\n      \"out_amount\": \"1803\",\n      \"in_amount\": \"1000000\"\n    }\n  ],\n  \"effective_fee\": \"0.006000000000000000\"\n}\n```\n\n2. GET `/router/routes?tokenIn=\u003ctokenIn\u003e\u0026tokenOutDenom=\u003ctokenOutDenom\u003e`\n\nDescription: returns all routes that can be used for routing from tokenIn to tokenOutDenom\n\nParameters:\n\n-   `tokenIn` the string representation of the denom of the token in\n-   `tokenOutDenom` the string representing the denom of the token out\n-   `humanReadable` (optional) boolean flag indicating whether a human readable denom is given as opposed to chain.\n\nResponse example:\n\n```bash\ncurl \"https://sqs.osmosis.zone/router/routes?tokenIn=uosmo\u0026tokenOutDenom=uion\" | jq .\n{\n  \"Routes\": [\n    {\n      \"Pools\": [\n        {\n          \"ID\": 1100,\n          \"TokenOutDenom\": \"uion\"\n        }\n      ]\n    },\n    {\n      \"Pools\": [\n        {\n          \"ID\": 2,\n          \"TokenOutDenom\": \"uion\"\n        }\n      ]\n    },\n    {\n      \"Pools\": [\n        {\n          \"ID\": 1013,\n          \"TokenOutDenom\": \"uion\"\n        }\n      ]\n    },\n    {\n      \"Pools\": [\n        {\n          \"ID\": 1092,\n          \"TokenOutDenom\": \"ibc/E6931F78057F7CC5DA0FD6CEF82FF39373A6E0452BF1FD76910B93292CF356C1\"\n        },\n        {\n          \"ID\": 476,\n          \"TokenOutDenom\": \"uion\"\n        }\n      ]\n    },\n    {\n      \"Pools\": [\n        {\n          \"ID\": 1108,\n          \"TokenOutDenom\": \"ibc/9712DBB13B9631EDFA9BF61B55F1B2D290B2ADB67E3A4EB3A875F3B6081B3B84\"\n        },\n        {\n          \"ID\": 26,\n          \"TokenOutDenom\": \"uion\"\n        }\n      ]\n    }\n  ],\n  \"UniquePoolIDs\": {\n    \"1013\": {},\n    \"1092\": {},\n    \"1100\": {},\n    \"1108\": {},\n    \"2\": {},\n    \"26\": {},\n    \"476\": {}\n  }\n}\n```\n\n3. GET `/router/custom-direct-quote?tokenIn=\u003ctokenIn\u003e\u0026tokenOutDenom=\u003ctokenOutDenom\u003e\u0026poolIDs=\u003cpoolIDs\u003e`\n\nDescription: returns the quote over route with the given poolIDs. If such route does not exist, returns error.\nThis endpoint does not use the router route search. As a result, it is not affected by the minimum liquidity parameter. As long as the pool exists on-chain, it will return a quote.\n\nParameters:\n\n-   `tokenIn` the string representation of the sdk.Coin for the token in\n-   `tokenOutDenom` the string representing the denom of the token out\n-   `poolID` comma-separated list of pool IDs\n\nResponse example:\n\n```bash\ncurl \"https://sqs.osmosis.zone/router/custom-direct-quote?tokenIn=1000000uosmo\u0026tokenOutDenom=uion\u0026poolID=2\" | jq .\n{\n  \"amount_in\": {\n    \"denom\": \"uosmo\",\n    \"amount\": \"1000000\"\n  },\n  \"amount_out\": \"1803\",\n  \"route\": [\n    {\n      \"pools\": [\n        {\n          \"id\": 2,\n          \"type\": 0,\n          \"balances\": [],\n          \"spread_factor\": \"0.005000000000000000\",\n          \"token_out_denom\": \"uion\",\n          \"taker_fee\": \"0.001000000000000000\"\n        }\n      ],\n      \"out_amount\": \"1803\",\n      \"in_amount\": \"1000000\"\n    }\n  ],\n  \"effective_fee\": \"0.006000000000000000\"\n}\n```\n\n### Tokens Resource\n\n1. GET `/tokens/metadata`\n\nDescription: returns token metadata with chain denom, human denom and precision.\nFor testnet, uses osmo-test-5 asset list. For mainnet, uses osmosis-1 asset list.\nSee `config.json` and `config-testnet.json` in root for details.\n\nParameter: denoms (optional). A list of denoms. Can either be human or chain denoms. If none given,\nreturns metadata for all denoms.\n\nResponse example:\n\n```bash\ncurl \"https://sqs.osmosis.zone/tokens/metadata/statom\" | jq .\n{\n    \"chain_denom\": \"ibc/C140AFD542AE77BD7DCC83F13FDD8C5E5BB8C4929785E6EC2F4C636F98F17901\",\n    \"human_denom\": \"statom\",\n    \"precision\": 6\n}\n```\n\n2. GET `/tokens/prices`\n\nParameters:\n\n-   `base` Comma-separated list of base denominations (human-readable or chain format based on humanDenoms parameter)\n-   `humanDenoms` Specify true if input denominations are in human-readable format; defaults to false.\n\nResponse:\n\nA map where each key is a base denomination (on-chain format), containing another map with a key as the quote denomination (on-chain format) and the value as the spot price.\n\n```bash\ncurl https://sqs.osmosis.zone//tokens/prices?base=wbtc,dydx\u0026humanDenoms=true\n{\n    \"ibc/831F0B1BBB1D08A2B75311892876D71565478C532967545476DF4C2D7492E48C\": {\n        \"ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858\": \"3.104120355715761583051226000000000000\"\n    },\n    \"ibc/D1542AA8762DB13087D8364F3EA6509FD6F009A34F00426AF9E4F9FA85CBBF1F\": {\n        \"ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858\": \"51334.702258726899383983572895277207392200\"\n    }\n}\n```\n\n### System Resource\n\n1. GET `/healthcheck`\n\nDescription: returns 200 if the server is healthy.\nValidates the following conditions:\n\n-   Node is reachable\n-   Node is not syncing\n-   The latest height in cache is within threshold of the latest height in the node\n-   The latest height in cache was updated within a configurable number of seconds\n\n2. GET `/metrics`\n\nDescription: returns the prometheus metrics for the server\n\n3. GET `/version`\n\nDescription: returns the version of the server\n\n4. GET `/config`\n\nDescription: returns the configuration of the server, including the router.\n\n## Development Setup\n\n### Mainnet\n\n#### Node Configuration\n\nEnsure the following in `app.toml`\n\n```toml\n[osmosis-sqs]\n\n# SQS service is disabled by default.\nis-enabled = \"true\"\n\n# The hostname and address of the sidecar query server storage.\ngrpc-ingest-address = \"localhost:50051\"\ngrpc-ingest-max-call-size-bytes = \"50000000\"\n```\n\nTo setup a development environment against mainnet, sync the node in the default\nhome directory and then run the following commands:\n\n```bash\n# Starts the Osmosis node from the default $HOME directory\n# Starts sqs from the config.json in the root of this repository\nmake all-start\n```\n\n## Data\n\n### Pools\n\nFor every chain pool, its pool model is written to cache.\n\nAdditionally, we instrument each pool model with bank balances and OSMO-denominated TVL.\n\nSome pool models do not contain balances by default. As a result, clients have to requery balance\nfor each pool model directly from chain. Having the balances in cache allows us to avoid this and serve\npools with balances directly.\n\nThe routing algorithm requires the knowledge of TVL for prioritizing pools. As a result, each pool model\nis instrumented with OSMO-denominated TVL.\n\n### Router\n\nFor routing, we must know about the taker fee for every denom pair. As a result, in the router\nrepository, we store the taker fee keyed by the denom pair.\n\nThese taker fees are then read from cache to initialize the router.\n\n### Token Precision\n\nThe chain is agnostic to token precision. As a result, to compute OSMO-denominated TVL,\nwe query [chain registry file](https://raw.githubusercontent.com/osmosis-labs/assetlists/main/osmosis-1/generated/frontend/assetlist.json)\nparse the precision exponent and use it scaling the spot price to the right value.\n\nThe following are the tokens that are either malformed or are missing from the chain registry file:\n\n```md\nibc/CD942F878C80FBE9DEAB8F8E57F592C7252D06335F193635AF002ACBD69139CC\nibc/FE2CD1E6828EC0FAB8AF39BAC45BC25B965BA67CCBC50C13A14BD610B0D1E2C4\nibc/4F3B0EC2FE2D370D10C3671A1B7B06D2A964C721470C305CBB846ED60E6CAA20\nibc/CD20AC50CE57F1CF2EA680D7D47733DA9213641D2D116C5806A880F508609A7A\nibc/52E12CF5CA2BB903D84F5298B4BFD725D66CAB95E09AA4FC75B2904CA5485FEB\nibc/49C2B2C444B7C5F0066657A4DBF19D676E0D185FF721CFD3E14FA253BCB9BC04\nibc/7ABF696369EFB3387DF22B6A24204459FE5EFD010220E8E5618DC49DB877047B\nibc/E27CD305D33F150369AB526AEB6646A76EC3FFB1A6CA58A663B5DE657A89D55D\nfactory/osmo130w50f7ta00dxkzpxemuxw7vnj6ks5mhe0fr8v/oDOGE\nibc/5BBB6F9C8ECA31508EE5B68F2E27B57532E1595C57D0AE5C8D64E1FBCB756247\nibc/00BC6883C29D45EAA021A55CFDD5884CA8EFF9D39F698A9FEF79E13819FF94F8\nibc/BCDB35B7390806F35E716D275E1E017999F8281A81B6F128F087EF34D1DFA761\nibc/020F5162B7BC40656FC5432622647091F00D53E82EE8D21757B43D3282F25424\nibc/D3A1900B2B520E45608B5671ADA461E1109628E89B4289099557C6D3996F7DAA\nibc/1271ACDB6421652A2230DECCAA365312A32770579C2B22D2B60A89FE39106611\nibc/DEA3B0BB0006C69E75D2247E8DC57878758790556487067F67748FDC237CE2AE\nibc/72D0C53912C461FC9251E3135459746380E9030C0BFDA13D45D3BAC47AE2910E\nibc/0E30775281643124D79B8670ACD3F478AC5FAB2B1CA1E32903D0775D8A8BB064\nibc/4E2A6E691D0EB60A25AE582F29D19B20671F723DF6978258F4043DA5692120AE\nibc/F2F19568D75125D7B88303ADC021653267443679780D6A0FD3E1EC318E0C51FD\nfactory/osmo19pw5d0jset8jlhawvkscj2gsfuyd5v524tfgek/TURKEY\n```\n\nAny pool containing these tokens would have the TVL error error set to\nnon-empty string, leading to the pool being deprioritized from the router.\n\n### Pricing\n\nThere are two sources of pricing data:\n\n1. On-chain\n2. CoinGecko\n\n#### Chain\n\nOn-chain pricing has the following two-cases:\n\n**1. USDC Quote**\n\nAt the start of SQS, we pre-compute prices for all listed tokens as defined by the asset list\nwith USDC as the quote and store them in-memory (no expiration).\n\nIn subsequent blocks, whenever a pool is updated (swapped, LPed etc), we detect that and recompute the price during ingest time via background worker and update internal memory.\n\n**2. Non-USDC Quote**\nComputed on-demand and result is stored in cache with TTL.\n\nGeneral computation logic:\n\n1. Compute routes between 2 tokens\n2. Compute spot price over pools in that route\n3. If there occurs an error in computing spot price, we fallback to computing a price\n   by swapping 10 units of the quote token (which in most cases today should be USDC).\n   The choise of 10 is such that we do not consider extremely low-liquidity routes that\n   may change frequently while also derisk the price impact with high-value non-USDC quotes.\n\n#### CoinGecko\n\nUnless specified by using the parameter `pricingSource`, the [GET /tokens/prices](#tokens-resource) endpoint uses the above chain pricing source by default in obtaining a price quote. Coingecko pricing source is also available by using the `pricingSource` parameter. Coingecko pricing source also serves as a fallback mechanism if the following conditions are met:\n\n1. The quote from on-chain pricing is unavailable for any reason.\n2. The quote is USDC quote.\n\nInternally, the Coingecko pricing source looks for the price quote in the its pricing cache and return it if it exists. Otherwise, it fetches the price from the Coingecko API endpoint and store it in the cache with an expiration time specified in the config.json file.\n\n### Configuration\n\nSee `docs/architecture/config.md` for details.\n\n## Debugging\n\n### Containers\n\nFor debugging SQS Docker containers with dlv, build the binary using `make docker-build-debug`.\nThis builds the binary with the debug symbols and then builds the Docker image with the debug binary.\nIt also starts sqs via dlv inside the container while exposing port 4000.\n\nA client can then attach their debugger via port 4000.\n\nSee `.vscode/launch.json` for the \"Debug Docker Container\" configuration.\n\n## Useful Osmosis Resources\n\n-   [ADR-002 SQS GRPC Refactor](https://www.notion.so/osmosiszone/ADR-002-SQS-GRPC-Ingest-Refactor-19fa05956d0344f58d40fbab57c08af7)\n-   [ADR-004 Cosmos SDK Streaming For SQS](https://www.notion.so/osmosiszone/ADR-003-Cosmos-SDK-Streaming-for-SQS-64dbc8b9ba6149259bf9870a43b7a4fc)\n-   [ADR-006 Streaming \u0026 GRPC Ingest](https://www.notion.so/osmosiszone/ADR-006-Streaming-GRPC-SQS-Ingest-4e3b2ff7d23e43e2a1f3c43adc3c26bc?pvs=13)\n-   [C4 L3 SQS Deployments](https://app.excalidraw.com/s/72t6r0pKvg5/4xLEjXi3KiU)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fosmosis-labs%2Fsqs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fosmosis-labs%2Fsqs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fosmosis-labs%2Fsqs/lists"}