├── .env.example ├── .gitignore ├── README.md ├── babel.config.cjs ├── docs └── openapi.yaml ├── jest.config.cjs ├── package-lock.json ├── package.json ├── src ├── ApiApplication.ts ├── DefinitionBuilder.ts ├── IndexerApplication.ts ├── api.ts ├── api │ ├── controllers │ │ ├── AssetController.ts │ │ ├── BaseApiController.ts │ │ ├── DexController.ts │ │ ├── LiquidityPoolController.ts │ │ ├── OrderBookController.ts │ │ ├── OrdersController.ts │ │ ├── PingController.ts │ │ └── SyncController.ts │ └── resources │ │ ├── AssetResource.ts │ │ ├── BaseEntityResource.ts │ │ ├── LiquidityPoolDepositResource.ts │ │ ├── LiquidityPoolResource.ts │ │ ├── LiquidityPoolStateResource.ts │ │ ├── LiquidityPoolSwapResource.ts │ │ ├── LiquidityPoolTickResource.ts │ │ ├── LiquidityPoolWithdrawResource.ts │ │ ├── OperationStatusResource.ts │ │ ├── OrderBookMatchResource.ts │ │ ├── OrderBookOrderResource.ts │ │ ├── OrderBookResource.ts │ │ ├── OrderBookTickResource.ts │ │ └── SyncResource.ts ├── apiServices.ts ├── config.ts ├── constants.ts ├── db │ ├── entities │ │ ├── Asset.ts │ │ ├── LiquidityPool.ts │ │ ├── LiquidityPoolDeposit.ts │ │ ├── LiquidityPoolState.ts │ │ ├── LiquidityPoolSwap.ts │ │ ├── LiquidityPoolTick.ts │ │ ├── LiquidityPoolWithdraw.ts │ │ ├── LiquidityPoolZap.ts │ │ ├── OperationStatus.ts │ │ ├── OrderBook.ts │ │ ├── OrderBookMatch.ts │ │ ├── OrderBookOrder.ts │ │ ├── OrderBookTick.ts │ │ └── Sync.ts │ └── migrations │ │ ├── 1692446359397-CreateAssetTable.ts │ │ ├── 1692532768196-CreateLiquidityPoolsTable.ts │ │ ├── 1692628719789-CreateLiquidityPoolStatesTable.ts │ │ ├── 1692629574101-CreateLiquidityPoolDepositsTable.ts │ │ ├── 1692629978609-CreateLiquidityPoolWithdrawsTable.ts │ │ ├── 1692634746860-CreateLiquidityPoolSwapsTable.ts │ │ ├── 1692634752527-CreateLiquidityPoolZapsTable.ts │ │ ├── 1693421645762-CreateSyncsTable.ts │ │ ├── 1694101486899-CreateOperationStatusesTable.ts │ │ ├── 1696953524778-CreateLiquidityPoolTicks.ts │ │ ├── 1699486894637-AddSenderStakeKeyHashOrders.ts │ │ ├── 1700495200089-AddActualReceivedSwapOrders.ts │ │ ├── 1703352414322-CreateOrderBooksTable.ts │ │ ├── 1703352431901-CreateOrderBookOrdersTable.ts │ │ ├── 1703861310521-CreateOrderBookMatchesTable.ts │ │ ├── 1708799513557-CreateOrderBookTicksTable.ts │ │ ├── 1711724722571-AddOrderAddressLiquidityPools.ts │ │ ├── 1712896760348-AddMetaLiquidityPoolSwaps.ts │ │ ├── 1712896777699-AddMetaLiquidityPoolDeposits.ts │ │ ├── 1712896783030-AddMetaLiquidityPoolWithdraws.ts │ │ ├── 1712896788861-AddMetaLiquidityPoolZaps.ts │ │ ├── 1712896804175-AddMetaOrderBookOrders.ts │ │ ├── 1712896807992-AddMetaOrderBookMatches.ts │ │ ├── 1714923640130-CreateIndexes.ts │ │ ├── 1715612872956-AddMetaAssets.ts │ │ ├── 1731944573000-CreateStakeKeyHashIndexes.ts │ │ └── 1731944573001-AddMetaLiquidityPools.ts ├── dex │ ├── AxoAnalyzer.ts │ ├── BaseAmmDexAnalyzer.ts │ ├── BaseHybridDexAnalyzer.ts │ ├── BaseOrderBookDexAnalyzer.ts │ ├── GeniusYieldAnalyzer.ts │ ├── MinswapAnalyzer.ts │ ├── MinswapV2Analyzer.ts │ ├── MuesliSwapAnalyzer.ts │ ├── SpectrumAnalyzer.ts │ ├── SplashAnalyzer.ts │ ├── SundaeSwapAnalyzer.ts │ ├── SundaeSwapV3Analyzer.ts │ ├── TeddySwapAnalyzer.ts │ ├── VyFiAnalyzer.ts │ ├── WingRidersAnalyzer.ts │ ├── WingRidersV2Analyzer.ts │ ├── definitions │ │ ├── genius-yield │ │ │ ├── order.ts │ │ │ └── partial-fill.ts │ │ ├── minswap-v2 │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ ├── swap.ts │ │ │ └── zap.ts │ │ ├── minswap │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ ├── swap.ts │ │ │ └── zap.ts │ │ ├── muesliswap │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ └── swap.ts │ │ ├── spectrum │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ └── swap.ts │ │ ├── splash │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ └── swap.ts │ │ ├── sundaeswap-v3 │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ ├── swap.ts │ │ │ └── zap.ts │ │ ├── sundaeswap │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ ├── swap.ts │ │ │ └── zap.ts │ │ ├── teddyswap │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ └── swap.ts │ │ ├── vyfinance │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ └── swap.ts │ │ ├── wingriders-v2 │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ └── swap.ts │ │ └── wingriders │ │ │ ├── pool-deposit.ts │ │ │ ├── pool-withdraw.ts │ │ │ ├── pool.ts │ │ │ └── swap.ts │ └── metadata.json ├── events.types.ts ├── handlers │ ├── AmmOperationHandler.ts │ ├── HybridOperationHandler.ts │ └── OrderBookOperationHandler.ts ├── indexer.ts ├── indexerServices.ts ├── indexers │ ├── AmmDexTransactionIndexer.ts │ ├── BaseIndexer.ts │ ├── HybridDexTransactionIndexer.ts │ ├── OrderBookDexTransactionIndexer.ts │ └── SyncIndexer.ts ├── jobs │ ├── BaseJob.ts │ ├── UpdateAmountReceived.ts │ ├── UpdateLiquidityPoolTicks.ts │ ├── UpdateLiquidityPoolTvlJob.ts │ └── UpdateOrderBookTicks.ts ├── listeners │ ├── BaseEventListener.ts │ └── PoolStateListener.ts ├── logger.ts ├── services │ ├── BaseService.ts │ ├── DatabaseService.ts │ ├── EventService.ts │ ├── QueueService.ts │ ├── TokenMetadataService.ts │ └── WebsocketService.ts ├── storage │ ├── BaseCacheStorage.ts │ └── CacheStorage.ts ├── types.ts └── utils.ts ├── tests ├── minswap.test.ts ├── muesliswap.test.ts ├── setup.ts ├── spectrum.test.ts ├── sundaeswap.test.ts ├── teddyswap.test.ts └── wingriders.test.ts └── tsconfig.json /.env.example: -------------------------------------------------------------------------------- 1 | LOG_DIR="logs" 2 | VERBOSE=true 3 | 4 | OGMIOS_HOST= 5 | OGMIOS_PORT= 6 | OGMIOS_TLS= 7 | 8 | DATABASE_HOST= 9 | DATABASE_PORT= 10 | DATABASE_USERNAME= 11 | DATABASE_PASSWORD= 12 | DATABASE= 13 | DATABASE_TYPE= 14 | 15 | OPERATION_WEBSOCKET_PORT= 16 | 17 | API_PORT= 18 | 19 | GITHUB_ACCESS_TOKEN="" 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | *.log 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | node_modules 7 | dist 8 | .idea 9 | .DS_Store 10 | .env 11 | -------------------------------------------------------------------------------- /babel.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ], 11 | "@babel/preset-typescript", 12 | ], 13 | "plugins": [ 14 | [ 15 | "@babel/plugin-proposal-decorators", 16 | { 17 | "version": "2023-05" 18 | } 19 | ] 20 | ] 21 | }; -------------------------------------------------------------------------------- /jest.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | rootDir: ".", 3 | preset: 'ts-jest', 4 | // preset: 'ts-jest/presets/default-esm', 5 | testMatch: ['/tests/**/*.test.ts'], 6 | testEnvironment: 'node', 7 | modulePathIgnorePatterns: [ 8 | '/dist/', 9 | ], 10 | transform: { 11 | "^.+\\.ts?$": [ 12 | "ts-jest", 13 | { 14 | useESM: true, 15 | }, 16 | ], 17 | // "^.+\\.ts?$": "babel-jest", 18 | }, 19 | roots: [''], 20 | modulePaths: [''], 21 | moduleDirectories: ["node_modules", ""], 22 | extensionsToTreatAsEsm: ['.ts'], 23 | moduleNameMapper: { 24 | "^(\\.{1,2}/.*)\\.js$": "$1", 25 | }, 26 | setupFiles: [ 27 | '/tests/setup.ts', 28 | ], 29 | }; 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@indigo-labs/iris", 3 | "version": "1.0.0", 4 | "author": "Zachary Sluder", 5 | "keywords": [ 6 | "Iris", 7 | "Cardano", 8 | "DEX" 9 | ], 10 | "description": "", 11 | "main": "./dist/index.js", 12 | "types": "./dist/index.d.ts", 13 | "files": [ 14 | "dist/**/*" 15 | ], 16 | "type": "module", 17 | "scripts": { 18 | "build": "tsc", 19 | "indexer": "NODE_NO_WARNINGS=1 node --es-module-specifier-resolution=node ./dist/indexer.js", 20 | "api": "NODE_NO_WARNINGS=1 node --es-module-specifier-resolution=node ./dist/api.js", 21 | "test": "node --no-warnings --experimental-vm-modules node_modules/jest/bin/jest.js --verbose", 22 | "jest": "jest" 23 | }, 24 | "license": "ISC", 25 | "devDependencies": { 26 | "@babel/core": "^7.24.5", 27 | "@babel/preset-env": "^7.24.5", 28 | "@babel/preset-typescript": "^7.24.1", 29 | "@cardano-ogmios/client": "^6.9.0", 30 | "@types/cors": "^2.8.14", 31 | "@types/express": "^4.17.17", 32 | "@types/helmet": "^4.0.0", 33 | "@types/jest": "^29.5.12", 34 | "@types/lodash": "^4.14.197", 35 | "@types/mysql": "^2.15.21", 36 | "@types/node": "^18.11.18", 37 | "@types/winston": "^2.4.4", 38 | "@types/winston-syslog": "^2.4.0", 39 | "@types/ws": "^8.5.5", 40 | "babel-jest": "^29.7.0", 41 | "jest": "^29.7.0", 42 | "ts-jest": "^29.1.2", 43 | "ts-node": "^10.9.2", 44 | "typescript": "^4.9.4" 45 | }, 46 | "dependencies": { 47 | "axios": "^1.5.1", 48 | "cors": "^2.8.5", 49 | "dotenv": "^16.3.1", 50 | "express": "^4.18.2", 51 | "helmet": "^7.0.0", 52 | "lodash": "^4.17.21", 53 | "lucid-cardano": "^0.10.7", 54 | "mysql2": "^3.6.0", 55 | "node-cache": "^5.1.2", 56 | "pg": "^8.11.5", 57 | "queue-promise": "^2.2.1", 58 | "reflect-metadata": "^0.1.13", 59 | "typeorm": "^0.3.17", 60 | "winston-daily-rotate-file": "^4.7.1", 61 | "winston-syslog": "^2.7.0", 62 | "ws": "^8.13.0" 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/ApiApplication.ts: -------------------------------------------------------------------------------- 1 | import express, { Application } from 'express'; 2 | import helmet from "helmet"; 3 | import cors from "cors"; 4 | import CONFIG from './config'; 5 | import { logError, logInfo } from './logger'; 6 | import { BaseApiController } from './api/controllers/BaseApiController'; 7 | import { AssetController } from './api/controllers/AssetController'; 8 | import { BaseService } from './services/BaseService'; 9 | import { dbApiService } from './apiServices'; 10 | import { LiquidityPoolController } from './api/controllers/LiquidityPoolController'; 11 | import { SyncController } from './api/controllers/SyncController'; 12 | import { DexController } from './api/controllers/DexController'; 13 | import { ApplicationContext } from './constants'; 14 | import { OrdersController } from './api/controllers/OrdersController'; 15 | import { PingController } from './api/controllers/PingController'; 16 | import { OrderBookController } from './api/controllers/OrderBookController'; 17 | 18 | export class ApiApplication { 19 | 20 | private _express: Application; 21 | private readonly _controllers: BaseApiController[]; 22 | 23 | /** 24 | * ApiApplication constructor. 25 | */ 26 | constructor(controllers: BaseApiController[] = []) { 27 | this._controllers = controllers; 28 | this._express = express(); 29 | 30 | this._express.use(cors()); 31 | this._express.use(express.json()); 32 | this._express.use(helmet()); 33 | } 34 | 35 | /** 36 | * Start application. 37 | */ 38 | public async start(): Promise { 39 | this.bootControllers(); 40 | 41 | return Promise.all([ 42 | this.bootServices(), 43 | this._express.listen(CONFIG.API_PORT), 44 | ]).then(() => { 45 | logInfo(`ApiApplication started on port ${CONFIG.API_PORT}`, ApplicationContext.Api); 46 | }); 47 | } 48 | 49 | /** 50 | * Boot all API controllers. 51 | */ 52 | private bootControllers(): void { 53 | const controllers: BaseApiController[] = [ 54 | ...this._controllers, 55 | new PingController('/ping'), 56 | new SyncController('/sync'), 57 | new AssetController('/assets'), 58 | new LiquidityPoolController('/liquidity-pools'), 59 | new OrderBookController('/order-books'), 60 | new DexController('/dex'), 61 | new OrdersController('/orders'), 62 | ]; 63 | 64 | controllers.forEach((controller: BaseApiController) => { 65 | controller.bootRoutes(); 66 | 67 | this._express.use('/api', controller.router); 68 | }); 69 | } 70 | 71 | /** 72 | * Boot all necessary services for application. 73 | */ 74 | private bootServices(): Promise { 75 | logInfo('Booting services...'); 76 | 77 | const services: BaseService[] = [ 78 | dbApiService, 79 | ]; 80 | 81 | return Promise.all(services.map((service: BaseService) => service.boot(this))) 82 | .then(() => { 83 | logInfo('Services booted'); 84 | }).catch((reason) => { 85 | logError(reason); 86 | process.exit(0); 87 | }); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/api.ts: -------------------------------------------------------------------------------- 1 | import { logError } from './logger'; 2 | import { ApiApplication } from './ApiApplication'; 3 | import { ApplicationContext } from './constants'; 4 | 5 | export const apiApp: ApiApplication = new ApiApplication(); 6 | 7 | await apiApp.start() 8 | .catch((reason) => { 9 | logError(`ApiApplication failed to start : ${reason}`, ApplicationContext.Api); 10 | }); 11 | -------------------------------------------------------------------------------- /src/api/controllers/BaseApiController.ts: -------------------------------------------------------------------------------- 1 | import express, { Router } from 'express'; 2 | 3 | export abstract class BaseApiController { 4 | 5 | public router: Router; 6 | public basePath: string; 7 | 8 | constructor(basePath: string) { 9 | this.router = express.Router(); 10 | this.basePath = basePath; 11 | } 12 | 13 | abstract bootRoutes(): void; 14 | 15 | public formatPaginatedResponse(page: number, limit: number, totalPages: number, data: any): Object { 16 | return { 17 | data: data, 18 | pagination: { 19 | page, 20 | limit, 21 | totalPages, 22 | }, 23 | }; 24 | } 25 | 26 | public successResponse(): Object { 27 | return { 28 | success: true, 29 | }; 30 | } 31 | 32 | public failResponse(message: string): Object { 33 | return { 34 | success: false, 35 | message, 36 | }; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/api/controllers/DexController.ts: -------------------------------------------------------------------------------- 1 | import { BaseApiController } from './BaseApiController'; 2 | import express from 'express'; 3 | import metadata from '../../dex/metadata.json' assert { type: "json" }; 4 | 5 | export class DexController extends BaseApiController { 6 | 7 | bootRoutes(): void { 8 | this.router.get(`${this.basePath}/metadata`, this.metadata); 9 | } 10 | 11 | private metadata(request: express.Request, response: express.Response) { 12 | response.send(metadata); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/api/controllers/PingController.ts: -------------------------------------------------------------------------------- 1 | import { BaseApiController } from './BaseApiController'; 2 | import express from 'express'; 3 | 4 | export class PingController extends BaseApiController { 5 | 6 | bootRoutes(): void { 7 | this.router.get(`${this.basePath}`, this.ping); 8 | } 9 | 10 | private ping(request: express.Request, response: express.Response) { 11 | response.send({ 12 | success: true, 13 | }); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/api/controllers/SyncController.ts: -------------------------------------------------------------------------------- 1 | import { BaseApiController } from './BaseApiController'; 2 | import express from 'express'; 3 | import { dbApiService } from '../../apiServices'; 4 | import { EntityManager } from 'typeorm'; 5 | import { Sync } from '../../db/entities/Sync'; 6 | import { SyncResource } from '../resources/SyncResource'; 7 | 8 | export class SyncController extends BaseApiController { 9 | 10 | bootRoutes(): void { 11 | this.router.get(`${this.basePath}`, this.latestSync); 12 | } 13 | 14 | private latestSync(request: express.Request, response: express.Response) { 15 | dbApiService.query((manager: EntityManager) => { 16 | return manager.findOne(Sync, { 17 | where: { 18 | id: 1, 19 | }, 20 | }); 21 | }).then((sync: Sync) => { 22 | const resource: SyncResource = new SyncResource(); 23 | 24 | response.send(resource.toJson(sync)); 25 | }); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/api/resources/AssetResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { Asset } from '../../db/entities/Asset'; 3 | 4 | export class AssetResource extends BaseEntityResource { 5 | 6 | toJson(entity: Asset): Object { 7 | let response: any = { 8 | policyId: entity.policyId, 9 | nameHex: entity.nameHex, 10 | decimals: entity.decimals, 11 | isLpToken: Boolean(entity.isLpToken), 12 | meta: entity.meta, 13 | }; 14 | 15 | if (! entity.isLpToken) { 16 | response.name = entity.name; 17 | response.ticker = entity.ticker; 18 | response.logo = entity.logo; 19 | response.description = entity.description; 20 | response.isVerified = entity.isVerified; 21 | } 22 | 23 | return response; 24 | } 25 | 26 | toCompressed(entity: Asset): Object { 27 | let response: any = { 28 | t: 'Asset', 29 | pId: entity.policyId, 30 | nH: entity.nameHex, 31 | d: entity.decimals, 32 | isLp: Boolean(entity.isLpToken), 33 | }; 34 | 35 | if (! entity.isLpToken) { 36 | response.n = entity.name; 37 | response.ti = entity.ticker; 38 | response.l = entity.logo; 39 | response.de = entity.description; 40 | response.v = entity.isVerified; 41 | } 42 | 43 | return response; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/api/resources/BaseEntityResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity } from 'typeorm'; 2 | 3 | export abstract class BaseEntityResource { 4 | 5 | abstract toJson(entity: BaseEntity): Object; 6 | 7 | abstract toCompressed(entity: BaseEntity): Object; 8 | 9 | public manyToJson(entities: BaseEntity[]): Object[] { 10 | return entities.map((entity: BaseEntity) => this.toJson(entity)); 11 | } 12 | 13 | public manyToCompressed(entities: BaseEntity[]): Object[] { 14 | return entities.map((entity: BaseEntity) => this.toCompressed(entity)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/api/resources/LiquidityPoolResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { LiquidityPool } from '../../db/entities/LiquidityPool'; 3 | import { AssetResource } from './AssetResource'; 4 | import { LiquidityPoolStateResource } from './LiquidityPoolStateResource'; 5 | import { stringify } from '../../utils'; 6 | 7 | export class LiquidityPoolResource extends BaseEntityResource { 8 | 9 | private _assetResource: AssetResource; 10 | private _stateResource: LiquidityPoolStateResource; 11 | 12 | constructor() { 13 | super(); 14 | 15 | this._assetResource = new AssetResource(); 16 | this._stateResource = new LiquidityPoolStateResource(false); 17 | } 18 | 19 | toJson(entity: LiquidityPool): Object { 20 | return { 21 | dex: entity.dex, 22 | identifier: entity.identifier, 23 | address: entity.address, 24 | orderAddress: entity.orderAddress, 25 | tokenA: entity.tokenA ? this._assetResource.toJson(entity.tokenA) : null, 26 | tokenB: entity.tokenB ? this._assetResource.toJson(entity.tokenB) : null, 27 | createdSlot: entity.createdSlot, 28 | state: entity.latestState ? this._stateResource.toJson(entity.latestState) : null, 29 | meta: entity.meta ? stringify(entity.meta) : null, 30 | }; 31 | } 32 | 33 | toCompressed(entity: LiquidityPool): Object { 34 | return { 35 | t: 'LiquidityPool', 36 | d: entity.dex, 37 | i: entity.identifier, 38 | a: entity.address, 39 | oA: entity.orderAddress, 40 | tA: entity.tokenA ? this._assetResource.toCompressed(entity.tokenA) : null, 41 | tB: entity.tokenB ? this._assetResource.toCompressed(entity.tokenB) : null, 42 | cS: entity.createdSlot, 43 | s: entity.latestState ? this._stateResource.toCompressed(entity.latestState) : null, 44 | m: entity.meta ? stringify(entity.meta) : null, 45 | }; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/api/resources/LiquidityPoolStateResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { LiquidityPoolState } from '../../db/entities/LiquidityPoolState'; 3 | import { LiquidityPoolResource } from './LiquidityPoolResource'; 4 | import { AssetResource } from './AssetResource'; 5 | 6 | export class LiquidityPoolStateResource extends BaseEntityResource { 7 | 8 | private readonly _includePool: boolean; 9 | private _assetResource: AssetResource; 10 | private readonly _poolResource: LiquidityPoolResource | undefined = undefined; 11 | 12 | constructor(includePool: boolean = true) { 13 | super(); 14 | 15 | this._includePool = includePool; 16 | this._assetResource = new AssetResource(); 17 | 18 | if (this._includePool) { 19 | this._poolResource = new LiquidityPoolResource(); 20 | } 21 | } 22 | 23 | toJson(entity: LiquidityPoolState): Object { 24 | let response: any = { 25 | reserveA: Number(entity.reserveA), 26 | reserveB: Number(entity.reserveB), 27 | lpTokens: Number(entity.lpTokens ?? 0), 28 | tvl: Number(entity.tvl ?? 0), 29 | feePercent: Number(entity.feePercent ?? 0), 30 | slot: Number(entity.slot ?? 0), 31 | }; 32 | 33 | if (this._includePool && this._poolResource) { 34 | response.liquidityPool = entity.liquidityPool ? this._poolResource.toJson(entity.liquidityPool): null; 35 | } 36 | 37 | if (entity.tokenLp) { 38 | response.tokenLp = this._assetResource.toJson(entity.tokenLp); 39 | } 40 | 41 | return response; 42 | } 43 | 44 | toCompressed(entity: LiquidityPoolState): Object { 45 | let response: any = { 46 | t: 'LiquidityPoolState', 47 | rA: Number(entity.reserveA), 48 | rB: Number(entity.reserveB), 49 | lpTs: Number(entity.lpTokens), 50 | tvl: Number(entity.tvl), 51 | f: Number(entity.feePercent), 52 | s: Number(entity.slot), 53 | }; 54 | 55 | if (this._includePool && this._poolResource) { 56 | response.p = entity.liquidityPool ? this._poolResource.toCompressed(entity.liquidityPool): null; 57 | } 58 | 59 | if (entity.tokenLp) { 60 | response.tLp = this._assetResource.toCompressed(entity.tokenLp); 61 | } 62 | 63 | return response; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/api/resources/LiquidityPoolTickResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { LiquidityPoolTick } from '../../db/entities/LiquidityPoolTick'; 3 | import {LiquidityPoolResource} from "./LiquidityPoolResource"; 4 | import * as process from 'process'; 5 | 6 | export class LiquidityPoolTickResource extends BaseEntityResource { 7 | 8 | toJson(entity: LiquidityPoolTick): Object { 9 | let response: any = { 10 | resolution: entity.resolution, 11 | open: entity.open, 12 | high: entity.high, 13 | low: entity.low, 14 | close: entity.close, 15 | volume: entity.volume, 16 | time: entity.time, 17 | }; 18 | 19 | if (entity.liquidityPool) { 20 | response.liquidityPool = (new LiquidityPoolResource()).toJson(entity.liquidityPool); 21 | } 22 | 23 | return response; 24 | } 25 | 26 | toCompressed(entity: LiquidityPoolTick): Object { 27 | let response: any = { 28 | t: 'LiquidityPoolTick', 29 | r: entity.resolution, 30 | o: entity.open, 31 | h: entity.high, 32 | l: entity.low, 33 | c: entity.close, 34 | v: entity.volume, 35 | ti: entity.time, 36 | }; 37 | 38 | if (entity.liquidityPool) { 39 | response.lP = (new LiquidityPoolResource()).toCompressed(entity.liquidityPool); 40 | } 41 | 42 | return response; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/api/resources/LiquidityPoolWithdrawResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { AssetResource } from './AssetResource'; 3 | import { LiquidityPoolResource } from './LiquidityPoolResource'; 4 | import { LiquidityPoolWithdraw } from '../../db/entities/LiquidityPoolWithdraw'; 5 | import { OperationStatusResource } from './OperationStatusResource'; 6 | import { OperationStatus } from '../../db/entities/OperationStatus'; 7 | import { stringify } from '../../utils'; 8 | 9 | export class LiquidityPoolWithdrawResource extends BaseEntityResource { 10 | 11 | private _assetResource: AssetResource; 12 | private _poolResource: LiquidityPoolResource; 13 | private _operationResource: OperationStatusResource; 14 | 15 | constructor() { 16 | super(); 17 | 18 | this._assetResource = new AssetResource(); 19 | this._poolResource = new LiquidityPoolResource(); 20 | this._operationResource = new OperationStatusResource(); 21 | } 22 | 23 | toJson(entity: LiquidityPoolWithdraw): Object { 24 | const response: any = { 25 | lpToken: this._assetResource.toJson(entity.lpToken), 26 | lpTokenAmount: Number(entity.lpTokenAmount), 27 | minReceiveA: Number(entity.minReceiveA), 28 | minReceiveB: Number(entity.minReceiveB), 29 | dexFeesPaid: Number(entity.dexFeesPaid), 30 | senderPubKeyHash: entity.senderPubKeyHash, 31 | senderStakeKeyHash: entity.senderStakeKeyHash, 32 | slot: Number(entity.slot), 33 | txHash: entity.txHash, 34 | outputIndex: Number(entity.outputIndex), 35 | meta: stringify(entity.meta), 36 | }; 37 | 38 | if (entity.liquidityPool) { 39 | response.liquidityPool = this._poolResource.toJson(entity.liquidityPool); 40 | } 41 | 42 | if (entity.statuses?.length > 0) { 43 | response.statuses = entity.statuses.map((status: OperationStatus) => this._operationResource.toJson(status)); 44 | } 45 | 46 | return response; 47 | } 48 | 49 | toCompressed(entity: LiquidityPoolWithdraw): Object { 50 | const response: any = { 51 | t: 'LiquidityPoolWithdraw', 52 | lpT: this._assetResource.toCompressed(entity.lpToken), 53 | lpA: Number(entity.lpTokenAmount), 54 | mA: Number(entity.minReceiveA), 55 | mB: Number(entity.minReceiveB), 56 | fP: Number(entity.dexFeesPaid), 57 | pkh: entity.senderPubKeyHash, 58 | skh: entity.senderStakeKeyHash, 59 | s: Number(entity.slot), 60 | tH: entity.txHash, 61 | oI: Number(entity.outputIndex), 62 | m: stringify(entity.meta), 63 | }; 64 | 65 | if (entity.liquidityPool) { 66 | response.lp = this._poolResource.toCompressed(entity.liquidityPool); 67 | } 68 | 69 | if (entity.statuses?.length > 0) { 70 | response.st = entity.statuses.map((status: OperationStatus) => this._operationResource.toCompressed(status)); 71 | } 72 | 73 | if (entity.transaction) { 74 | response.tr = stringify(entity.transaction); 75 | } 76 | 77 | return response; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/api/resources/OperationStatusResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { OperationStatus } from '../../db/entities/OperationStatus'; 3 | import { LiquidityPoolSwap } from '../../db/entities/LiquidityPoolSwap'; 4 | import { LiquidityPoolSwapResource } from './LiquidityPoolSwapResource'; 5 | import { LiquidityPoolDeposit } from '../../db/entities/LiquidityPoolDeposit'; 6 | import { LiquidityPoolDepositResource } from './LiquidityPoolDepositResource'; 7 | import { LiquidityPoolWithdraw } from '../../db/entities/LiquidityPoolWithdraw'; 8 | import { LiquidityPoolWithdrawResource } from './LiquidityPoolWithdrawResource'; 9 | 10 | export class OperationStatusResource extends BaseEntityResource { 11 | 12 | toJson(entity: OperationStatus): Object { 13 | let response: any = { 14 | status: entity.status, 15 | slot: Number(entity.slot), 16 | txHash: entity.txHash, 17 | outputIndex: Number(entity.outputIndex), 18 | operationTxHash: entity.operationTxHash, 19 | operationOutputIndex: entity.operationOutputIndex, 20 | }; 21 | 22 | if (entity.operationEntity) { 23 | switch (entity.operationEntity.constructor) { 24 | case LiquidityPoolSwap: 25 | response.operationEntity = (new LiquidityPoolSwapResource()).toJson(entity.operationEntity as LiquidityPoolSwap); break; 26 | case LiquidityPoolDeposit: 27 | response.operationEntity = (new LiquidityPoolDepositResource()).toJson(entity.operationEntity as LiquidityPoolDeposit); break; 28 | case LiquidityPoolWithdraw: 29 | response.operationEntity = (new LiquidityPoolWithdrawResource()).toJson(entity.operationEntity as LiquidityPoolWithdraw); break; 30 | // todo include zaps 31 | } 32 | } 33 | 34 | return response; 35 | } 36 | 37 | toCompressed(entity: OperationStatus): Object { 38 | let response: any = { 39 | t: 'OperationStatus', 40 | st: entity.status, 41 | s: Number(entity.slot), 42 | tH: entity.txHash, 43 | oI: Number(entity.outputIndex), 44 | oTx: entity.operationTxHash, 45 | oOi: entity.operationOutputIndex, 46 | }; 47 | 48 | if (entity.operationEntity) { 49 | switch (entity.operationEntity.constructor) { 50 | case LiquidityPoolSwap: 51 | response.oE = (new LiquidityPoolSwapResource()).toCompressed(entity.operationEntity as LiquidityPoolSwap); break; 52 | case LiquidityPoolDeposit: 53 | response.oE = (new LiquidityPoolDepositResource()).toCompressed(entity.operationEntity as LiquidityPoolDeposit); break; 54 | case LiquidityPoolWithdraw: 55 | response.oE = (new LiquidityPoolWithdrawResource()).toCompressed(entity.operationEntity as LiquidityPoolWithdraw); break; 56 | } 57 | } 58 | 59 | return response; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/api/resources/OrderBookMatchResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { OrderBookMatch } from '../../db/entities/OrderBookMatch'; 3 | import { AssetResource } from './AssetResource'; 4 | import { OrderBookResource } from './OrderBookResource'; 5 | import { OrderBookOrderResource } from './OrderBookOrderResource'; 6 | import { stringify } from '../../utils'; 7 | 8 | export class OrderBookMatchResource extends BaseEntityResource { 9 | 10 | private _assetResource: AssetResource; 11 | private _orderBookResource: OrderBookResource; 12 | private _orderBookOrderResource: OrderBookOrderResource; 13 | 14 | constructor() { 15 | super(); 16 | 17 | this._assetResource = new AssetResource(); 18 | this._orderBookResource = new OrderBookResource(); 19 | this._orderBookOrderResource = new OrderBookOrderResource(); 20 | } 21 | 22 | toJson(entity: OrderBookMatch): Object { 23 | let response: any = { 24 | referenceOrder: this._orderBookOrderResource.toJson(entity.referenceOrder), 25 | fromToken: entity.matchedToken ? this._assetResource.toJson(entity.matchedToken) : null, 26 | matchedAmount: Number(entity.matchedAmount), 27 | receiverPubKeyHash: entity.receiverPubKeyHash, 28 | receiverStakeKeyHash: entity.receiverStakeKeyHash, 29 | slot: Number(entity.slot), 30 | txHash: entity.txHash, 31 | outputIndex: Number(entity.slot), 32 | meta: stringify(entity.meta), 33 | }; 34 | 35 | if (entity.orderBook) { 36 | response.orderBook = this._orderBookResource.toJson(entity.orderBook); 37 | } 38 | 39 | return response; 40 | } 41 | 42 | toCompressed(entity: OrderBookMatch): Object { 43 | let response: any = { 44 | t: 'OrderBookMatch', 45 | rO: this._orderBookOrderResource.toCompressed(entity.referenceOrder), 46 | fT: entity.matchedToken ? this._assetResource.toCompressed(entity.matchedToken) : null, 47 | mA: Number(entity.matchedAmount), 48 | pkh: entity.receiverPubKeyHash, 49 | skh: entity.receiverStakeKeyHash, 50 | s: Number(entity.slot), 51 | tH: entity.txHash, 52 | oI: Number(entity.outputIndex), 53 | m: stringify(entity.meta), 54 | }; 55 | 56 | if (entity.orderBook) { 57 | response.oB = this._orderBookResource.toCompressed(entity.orderBook); 58 | } 59 | 60 | if (entity.transaction) { 61 | response.tr = stringify(entity.transaction); 62 | } 63 | 64 | return response; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/api/resources/OrderBookOrderResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { OrderBookOrder } from '../../db/entities/OrderBookOrder'; 3 | import { AssetResource } from './AssetResource'; 4 | import { OrderBookResource } from './OrderBookResource'; 5 | import { stringify } from '../../utils'; 6 | 7 | export class OrderBookOrderResource extends BaseEntityResource { 8 | 9 | private _assetResource: AssetResource; 10 | private _orderBookResource: OrderBookResource; 11 | 12 | constructor() { 13 | super(); 14 | 15 | this._assetResource = new AssetResource(); 16 | this._orderBookResource = new OrderBookResource(); 17 | } 18 | 19 | toJson(entity: OrderBookOrder): Object { 20 | let response: any = { 21 | fromToken: entity.fromToken ? this._assetResource.toJson(entity.fromToken) : null, 22 | toToken: entity.toToken ? this._assetResource.toJson(entity.toToken) : null, 23 | identifier: entity.identifier, 24 | originalOfferAmount: Number(entity.originalOfferAmount), 25 | unFilledOfferAmount: Number(entity.unFilledOfferAmount), 26 | askedAmount: Number(entity.askedAmount), 27 | price: Number(entity.price), 28 | numPartialFills: Number(entity.numPartialFills), 29 | isCancelled: Number(entity.isCancelled), 30 | dexFeesPaid: Number(entity.dexFeesPaid), 31 | senderPubKeyHash: entity.senderPubKeyHash, 32 | senderStakeKeyHash: entity.senderStakeKeyHash, 33 | slot: Number(entity.slot), 34 | txHash: entity.txHash, 35 | outputIndex: Number(entity.slot), 36 | meta: stringify(entity.meta), 37 | }; 38 | 39 | if (entity.orderBook) { 40 | response.orderBook = this._orderBookResource.toJson(entity.orderBook); 41 | } 42 | 43 | return response; 44 | } 45 | 46 | toCompressed(entity: OrderBookOrder): Object { 47 | let response: any = { 48 | t: 'OrderBookOrder', 49 | fT: entity.fromToken ? this._assetResource.toCompressed(entity.fromToken) : null, 50 | tT: entity.toToken ? this._assetResource.toCompressed(entity.toToken) : null, 51 | i: entity.identifier, 52 | oA: Number(entity.originalOfferAmount), 53 | uA: Number(entity.unFilledOfferAmount), 54 | aA: Number(entity.askedAmount), 55 | p: Number(entity.price), 56 | pF: Number(entity.numPartialFills), 57 | iC: Number(entity.isCancelled), 58 | fP: Number(entity.dexFeesPaid), 59 | pkh: entity.senderPubKeyHash, 60 | skh: entity.senderStakeKeyHash, 61 | s: Number(entity.slot), 62 | tH: entity.txHash, 63 | oI: Number(entity.outputIndex), 64 | m: stringify(entity.meta), 65 | }; 66 | 67 | if (entity.orderBook) { 68 | response.oB = this._orderBookResource.toCompressed(entity.orderBook); 69 | } 70 | 71 | if (entity.transaction) { 72 | response.tr = stringify(entity.transaction); 73 | } 74 | 75 | return response; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/api/resources/OrderBookResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { AssetResource } from './AssetResource'; 3 | import { OrderBook } from '../../db/entities/OrderBook'; 4 | 5 | export class OrderBookResource extends BaseEntityResource { 6 | 7 | private _assetResource: AssetResource; 8 | 9 | constructor() { 10 | super(); 11 | 12 | this._assetResource = new AssetResource(); 13 | } 14 | 15 | toJson(entity: OrderBook): Object { 16 | return { 17 | dex: entity.dex, 18 | identifier: entity.identifier, 19 | tokenA: entity.tokenA ? this._assetResource.toJson(entity.tokenA) : null, 20 | tokenB: this._assetResource.toJson(entity.tokenB), 21 | createdSlot: entity.createdSlot, 22 | }; 23 | } 24 | 25 | toCompressed(entity: OrderBook): Object { 26 | return { 27 | t: 'OrderBook', 28 | d: entity.dex, 29 | i: entity.identifier, 30 | tA: entity.tokenA ? this._assetResource.toCompressed(entity.tokenA) : null, 31 | tB: this._assetResource.toCompressed(entity.tokenB), 32 | cS: entity.createdSlot, 33 | }; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/api/resources/OrderBookTickResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { OrderBookTick } from '../../db/entities/OrderBookTick'; 3 | import {OrderBookResource} from './OrderBookResource'; 4 | 5 | export class OrderBookTickResource extends BaseEntityResource { 6 | 7 | toJson(entity: OrderBookTick): Object { 8 | let response: any = { 9 | resolution: entity.resolution, 10 | open: entity.open, 11 | high: entity.high, 12 | low: entity.low, 13 | close: entity.close, 14 | volume: entity.volume, 15 | time: entity.time, 16 | }; 17 | 18 | if (entity.orderBook) { 19 | response.orderBook = (new OrderBookResource()).toJson(entity.orderBook); 20 | } 21 | 22 | return response; 23 | } 24 | 25 | toCompressed(entity: OrderBookTick): Object { 26 | let response: any = { 27 | t: 'OrderBookTick', 28 | r: entity.resolution, 29 | o: entity.open, 30 | h: entity.high, 31 | l: entity.low, 32 | c: entity.close, 33 | v: entity.volume, 34 | ti: entity.time, 35 | }; 36 | 37 | if (entity.orderBook) { 38 | response.oB = (new OrderBookResource()).toCompressed(entity.orderBook); 39 | } 40 | 41 | return response; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/api/resources/SyncResource.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntityResource } from './BaseEntityResource'; 2 | import { Sync } from '../../db/entities/Sync'; 3 | 4 | export class SyncResource extends BaseEntityResource { 5 | 6 | toJson(entity: Sync): Object { 7 | return { 8 | slot: Number(entity.slot), 9 | blockHash: entity.blockHash, 10 | }; 11 | } 12 | 13 | toCompressed(entity: Sync): Object { 14 | return { 15 | t: 'Sync', 16 | s: Number(entity.slot), 17 | bH: entity.blockHash, 18 | }; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/apiServices.ts: -------------------------------------------------------------------------------- 1 | import { DatabaseService } from './services/DatabaseService'; 2 | import { ApplicationContext } from './constants'; 3 | 4 | const dbApiService: DatabaseService = new DatabaseService(ApplicationContext.Api); 5 | 6 | export { 7 | dbApiService, 8 | } 9 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv'; 2 | 3 | dotenv.config(); 4 | 5 | type Config = { 6 | LOG_DIR: string, 7 | VERBOSE: boolean, 8 | 9 | OGMIOS_HOST: string, 10 | OGMIOS_PORT: number, 11 | OGMIOS_TLS: boolean, 12 | 13 | DATABASE_HOST: string, 14 | DATABASE_PORT: number, 15 | DATABASE_USERNAME: string, 16 | DATABASE_PASSWORD: string, 17 | DATABASE: string, 18 | DATABASE_TYPE: string, 19 | 20 | OPERATION_WEBSOCKET_PORT: number, 21 | 22 | API_PORT: number, 23 | 24 | GITHUB_ACCESS_TOKEN: string, 25 | } 26 | 27 | const CONFIG: Config = { 28 | LOG_DIR: process.env.LOG_DIR || 'logs', 29 | VERBOSE: process.env.VERBOSE === 'true', 30 | 31 | OGMIOS_HOST: process.env.OGMIOS_HOST || 'localhost', 32 | OGMIOS_PORT: Number(process.env.OGMIOS_PORT) || 1337, 33 | OGMIOS_TLS: process.env.OGMIOS_TLS === 'true', 34 | 35 | DATABASE_HOST: process.env.DATABASE_HOST || 'localhost', 36 | DATABASE_PORT: Number(process.env.DATABASE_PORT) || 3306, 37 | DATABASE_USERNAME: process.env.DATABASE_USERNAME || '', 38 | DATABASE_PASSWORD: process.env.DATABASE_PASSWORD || '', 39 | DATABASE: process.env.DATABASE || '', 40 | DATABASE_TYPE: process.env.DATABASE_TYPE || 'mysql', 41 | 42 | OPERATION_WEBSOCKET_PORT: Number(process.env.OPERATION_WEBSOCKET_PORT) || 8080, 43 | 44 | API_PORT: Number(process.env.API_PORT) || 8081, 45 | 46 | GITHUB_ACCESS_TOKEN: process.env.GITHUB_ACCESS_TOKEN || '', 47 | } 48 | 49 | export default CONFIG; 50 | -------------------------------------------------------------------------------- /src/db/entities/Asset.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; 2 | 3 | @Entity({ name: 'assets' }) 4 | @Index(['policyId', 'nameHex'], { unique: true }) 5 | export class Asset extends BaseEntity { 6 | 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @Column({ length: 56 }) 11 | policyId: string; 12 | 13 | @Column() 14 | nameHex: string; 15 | 16 | @Column() 17 | isLpToken: boolean; 18 | 19 | @Column({ default: false }) 20 | isVerified: boolean; 21 | 22 | @Column({ nullable: true, default: null }) 23 | decimals: number; 24 | 25 | @Column({ nullable: true, default: null }) 26 | name: string; 27 | 28 | @Column({ nullable: true, default: null }) 29 | ticker: string; 30 | 31 | @Column({ nullable: true, default: null }) 32 | logo: string; 33 | 34 | @Column({ nullable: true, default: null }) 35 | description: string; 36 | 37 | @Column({ nullable: true }) 38 | meta: string; 39 | 40 | /** 41 | * Asset constructor. 42 | */ 43 | constructor(policyId: string, nameHex: string) { 44 | super(); 45 | 46 | this.policyId = policyId; 47 | this.nameHex = nameHex; 48 | } 49 | 50 | static fromId(id: string): Asset { 51 | id = id.replace('.', ''); 52 | 53 | return new Asset( 54 | id.slice(0, 56), 55 | id.slice(56), 56 | ); 57 | } 58 | 59 | identifier(dilimeter: '' | '.' = ''): string { 60 | return `${this.policyId}${dilimeter}${this.nameHex}`; 61 | } 62 | 63 | get assetName(): string { 64 | return Buffer.from(this.nameHex, 'hex').toString(); 65 | } 66 | 67 | } 68 | 69 | export type Token = Asset | 'lovelace'; 70 | -------------------------------------------------------------------------------- /src/db/entities/LiquidityPool.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, JoinColumn, OneToMany, OneToOne, PrimaryGeneratedColumn, Relation } from 'typeorm'; 2 | import { Asset } from './Asset'; 3 | import { Dex } from '../../constants'; 4 | import { LiquidityPoolState } from './LiquidityPoolState'; 5 | 6 | @Entity({ name: 'liquidity_pools' }) 7 | export class LiquidityPool extends BaseEntity { 8 | 9 | @PrimaryGeneratedColumn() 10 | id: number; 11 | 12 | @Column() 13 | dex: string; 14 | 15 | @Column({ unique: true }) 16 | identifier: string; 17 | 18 | @Column() 19 | address: string; 20 | 21 | @Column({ nullable: true }) 22 | orderAddress: string; 23 | 24 | @OneToOne(() => Asset, { nullable: true }) 25 | @JoinColumn() 26 | tokenA: Relation; 27 | 28 | @OneToOne(() => Asset) 29 | @JoinColumn() 30 | tokenB: Relation; 31 | 32 | @Column({ type: 'bigint', unsigned: true }) 33 | createdSlot: number; 34 | 35 | @Column({ nullable: true }) 36 | meta: string; 37 | 38 | @OneToOne(() => LiquidityPoolState) 39 | @JoinColumn() 40 | latestState: Relation; 41 | 42 | @OneToMany(() => LiquidityPoolState, (state: LiquidityPoolState) => state.liquidityPool) 43 | @JoinColumn() 44 | states: Relation[]; 45 | 46 | static make( 47 | dex: Dex, 48 | identifier: string, 49 | address: string, 50 | tokenA: Asset | undefined, 51 | tokenB: Asset, 52 | createdSlot: number, 53 | ): LiquidityPool { 54 | let pool: LiquidityPool = new LiquidityPool(); 55 | 56 | pool.dex = dex; 57 | pool.identifier = identifier; 58 | pool.address = address; 59 | pool.tokenA = tokenA; 60 | pool.tokenB = tokenB; 61 | pool.createdSlot = createdSlot; 62 | 63 | return pool; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/db/entities/LiquidityPoolTick.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn, Relation } from 'typeorm'; 2 | import { LiquidityPool } from './LiquidityPool'; 3 | 4 | @Entity({ name: 'liquidity_pool_ticks' }) 5 | export class LiquidityPoolTick extends BaseEntity { 6 | 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @ManyToOne(() => LiquidityPool) 11 | @JoinColumn() 12 | liquidityPool: Relation; 13 | 14 | @Column() 15 | resolution: string; 16 | 17 | @Column() 18 | time: number; 19 | 20 | @Column({ type: 'double' }) 21 | open: number; 22 | 23 | @Column({ type: 'double' }) 24 | high: number; 25 | 26 | @Column({ type: 'double' }) 27 | low: number; 28 | 29 | @Column({ type: 'double' }) 30 | close: number; 31 | 32 | @Column({ type: 'double' }) 33 | volume: number; 34 | 35 | @Column({ type: 'bigint', unsigned: true }) 36 | tvl: number; 37 | 38 | static make( 39 | liquidityPool: LiquidityPool, 40 | resolution: string, 41 | time: number, 42 | open: number, 43 | high: number, 44 | low: number, 45 | close: number, 46 | tvl: number = 0, 47 | volume: number = 0, 48 | ): LiquidityPoolTick { 49 | let instance: LiquidityPoolTick = new LiquidityPoolTick(); 50 | 51 | instance.liquidityPool = liquidityPool; 52 | instance.resolution = resolution; 53 | instance.time = time; 54 | instance.open = open; 55 | instance.high = high; 56 | instance.low = low; 57 | instance.close = close; 58 | instance.tvl = tvl; 59 | instance.volume = volume; 60 | 61 | return instance; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/db/entities/LiquidityPoolWithdraw.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, JoinColumn, OneToMany, OneToOne, PrimaryGeneratedColumn, Relation } from 'typeorm'; 2 | import { LiquidityPool } from './LiquidityPool'; 3 | import { Asset } from './Asset'; 4 | import { Dex } from '../../constants'; 5 | import { OperationStatus } from './OperationStatus'; 6 | import { Transaction } from '../../types'; 7 | 8 | @Entity({ name: 'liquidity_pool_withdraws' }) 9 | export class LiquidityPoolWithdraw extends BaseEntity { 10 | 11 | dex: Dex; 12 | liquidityPoolIdentifier: string | undefined; 13 | transaction: Transaction | undefined; 14 | backupDex: string; 15 | 16 | @PrimaryGeneratedColumn() 17 | id: number; 18 | 19 | @OneToOne(() => LiquidityPool) 20 | @JoinColumn() 21 | liquidityPool: Relation; 22 | 23 | @OneToOne(() => Asset) 24 | @JoinColumn() 25 | lpToken: Relation; 26 | 27 | @Column({ type: 'bigint', unsigned: true }) 28 | lpTokenAmount: number; 29 | 30 | @Column({ type: 'bigint', nullable: true, unsigned: true }) 31 | minReceiveA: number | undefined; 32 | 33 | @Column({ type: 'bigint', nullable: true, unsigned: true }) 34 | minReceiveB: number | undefined; 35 | 36 | @Column({ type: 'varchar' }) 37 | dexFeesPaid: number; 38 | 39 | @Column() 40 | senderPubKeyHash: string; 41 | 42 | @Column({ nullable: true }) 43 | senderStakeKeyHash: string; 44 | 45 | @Column({ type: 'bigint', unsigned: true }) 46 | slot: number; 47 | 48 | @Column() 49 | txHash: string; 50 | 51 | @Column() 52 | outputIndex: number; 53 | 54 | @Column({ nullable: true }) 55 | meta: string; 56 | 57 | @OneToMany(() => OperationStatus, (status: OperationStatus) => status.operationId) 58 | @JoinColumn() 59 | statuses: OperationStatus[]; 60 | 61 | static make( 62 | dex: Dex, 63 | liquidityPoolIdentifier: string | undefined, 64 | lpToken: Asset, 65 | lpTokenAmount: number, 66 | minReceiveA: number | undefined, 67 | minReceiveB: number | undefined, 68 | dexFeesPaid: number, 69 | senderPubKeyHash: string, 70 | senderStakeKeyHash: string, 71 | slot: number, 72 | txHash: string, 73 | outputIndex: number, 74 | transaction?: Transaction, 75 | backupDex: string = '', 76 | ): LiquidityPoolWithdraw { 77 | let instance: LiquidityPoolWithdraw = new LiquidityPoolWithdraw(); 78 | 79 | instance.dex = dex; 80 | instance.liquidityPoolIdentifier = liquidityPoolIdentifier; 81 | instance.lpToken = lpToken; 82 | instance.lpTokenAmount = lpTokenAmount; 83 | instance.minReceiveA = minReceiveA ? minReceiveA : undefined; 84 | instance.minReceiveB = minReceiveB ? minReceiveB : undefined; 85 | instance.dexFeesPaid = dexFeesPaid; 86 | instance.senderPubKeyHash = senderPubKeyHash; 87 | instance.senderStakeKeyHash = senderStakeKeyHash; 88 | instance.slot = slot; 89 | instance.txHash = txHash; 90 | instance.outputIndex = outputIndex; 91 | instance.transaction = transaction; 92 | instance.backupDex = backupDex; 93 | 94 | return instance; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/db/entities/OperationStatus.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; 2 | import { DexOperationStatus } from '../../constants'; 3 | 4 | @Entity({ name: 'operation_statuses' }) 5 | @Index(['operationId', 'operationType', 'status'], { unique: true }) 6 | export class OperationStatus extends BaseEntity { 7 | 8 | operationEntity: any; 9 | operationTxHash: string; 10 | operationOutputIndex: number; 11 | 12 | @PrimaryGeneratedColumn() 13 | id: number; 14 | 15 | @Column() 16 | operationId: number; 17 | 18 | @Column({ type: 'varchar' }) 19 | operationType: string; 20 | 21 | @Column() 22 | status: DexOperationStatus; 23 | 24 | @Column({ type: 'bigint', unsigned: true }) 25 | slot: number; 26 | 27 | @Column() 28 | txHash: string; 29 | 30 | @Column() 31 | outputIndex: number; 32 | 33 | static make( 34 | status: DexOperationStatus, 35 | slot: number, 36 | txHash: string, 37 | outputIndex: number, 38 | operationTxHash: string, 39 | operationOutputIndex: number, 40 | operationId?: number, 41 | operationType?: string, 42 | ): OperationStatus { 43 | let instance: OperationStatus = new OperationStatus(); 44 | 45 | instance.status = status; 46 | instance.slot = slot; 47 | instance.txHash = txHash; 48 | instance.outputIndex = outputIndex; 49 | instance.operationTxHash = operationTxHash; 50 | instance.operationOutputIndex = operationOutputIndex; 51 | 52 | if (operationId) { 53 | instance.operationId = operationId; 54 | } 55 | if (operationType) { 56 | instance.operationType = operationType; 57 | } 58 | 59 | return instance; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/db/entities/OrderBook.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn, Relation } from 'typeorm'; 2 | import { Asset } from './Asset'; 3 | import { Dex } from '../../constants'; 4 | import { tokenId } from '../../utils'; 5 | 6 | @Entity({ name: 'order_books' }) 7 | export class OrderBook extends BaseEntity { 8 | 9 | @PrimaryGeneratedColumn() 10 | id: number; 11 | 12 | @Column() 13 | identifier: string; 14 | 15 | @Column() 16 | dex: string; 17 | 18 | @OneToOne(() => Asset, { nullable: true, eager: true }) 19 | @JoinColumn() 20 | tokenA: Relation; 21 | 22 | @OneToOne(() => Asset, { eager: true }) 23 | @JoinColumn() 24 | tokenB: Relation; 25 | 26 | @Column({ type: 'bigint', unsigned: true }) 27 | createdSlot: number; 28 | 29 | static make( 30 | dex: Dex, 31 | tokenA: Asset | undefined, 32 | tokenB: Asset, 33 | createdSlot: number, 34 | ): OrderBook { 35 | let book: OrderBook = new OrderBook(); 36 | 37 | book.identifier = `${dex}.${tokenId(tokenA ?? 'lovelace')}.${tokenId(tokenB)}` 38 | book.dex = dex; 39 | book.tokenA = tokenA; 40 | book.tokenB = tokenB; 41 | book.createdSlot = createdSlot; 42 | 43 | return book; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/db/entities/OrderBookMatch.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn, Relation } from 'typeorm'; 2 | import { Asset, Token } from './Asset'; 3 | import { OrderBook } from './OrderBook'; 4 | import { Dex } from '../../constants'; 5 | import { OrderBookOrder } from './OrderBookOrder'; 6 | import { Transaction } from '../../types'; 7 | 8 | @Entity({ name: 'order_book_matches' }) 9 | export class OrderBookMatch extends BaseEntity { 10 | 11 | dex: Dex; 12 | consumedTxHash: string; 13 | partialFillOrderIdentifier: string; 14 | transaction: Transaction | undefined; 15 | unFilledAmount: number; 16 | 17 | @PrimaryGeneratedColumn() 18 | id: number; 19 | 20 | @OneToOne(() => OrderBook) 21 | @JoinColumn() 22 | orderBook: Relation; 23 | 24 | @OneToOne(() => OrderBookOrder, { nullable: false, eager: true }) 25 | @JoinColumn() 26 | referenceOrder: Relation; 27 | 28 | @OneToOne(() => Asset, { eager: true }) 29 | @JoinColumn() 30 | matchedToken: Relation; 31 | 32 | @Column({ type: 'bigint', unsigned: true }) 33 | matchedAmount: number; 34 | 35 | @Column() 36 | receiverPubKeyHash: string; 37 | 38 | @Column({ nullable: true }) 39 | receiverStakeKeyHash: string; 40 | 41 | @Column({ type: 'bigint', unsigned: true }) 42 | slot: number; 43 | 44 | @Column() 45 | txHash: string; 46 | 47 | @Column() 48 | outputIndex: number; 49 | 50 | @Column({ nullable: true }) 51 | meta: string; 52 | 53 | static make( 54 | dex: Dex, 55 | matchedToken: Token | undefined, 56 | matchedAmount: number, 57 | receiverPubKeyHash: string, 58 | receiverStakeKeyHash: string, 59 | slot: number, 60 | txHash: string, 61 | outputIndex: number, 62 | consumedTxHash: string, 63 | partialFillOrderIdentifier: string = '', 64 | referenceOrder: OrderBookOrder | undefined = undefined, 65 | transaction?: Transaction, 66 | unFilledAmount: number = 0, 67 | ): OrderBookMatch { 68 | let instance: OrderBookMatch = new OrderBookMatch(); 69 | 70 | instance.dex = dex; 71 | instance.matchedToken = matchedToken === 'lovelace' ? undefined : matchedToken; 72 | instance.matchedAmount = matchedAmount; 73 | instance.receiverPubKeyHash = receiverPubKeyHash; 74 | instance.receiverStakeKeyHash = receiverStakeKeyHash; 75 | instance.slot = slot; 76 | instance.txHash = txHash; 77 | instance.outputIndex = outputIndex; 78 | instance.consumedTxHash = consumedTxHash; 79 | instance.partialFillOrderIdentifier = partialFillOrderIdentifier; 80 | instance.transaction = transaction; 81 | instance.unFilledAmount = unFilledAmount; 82 | 83 | if (referenceOrder) { 84 | instance.referenceOrder = referenceOrder; 85 | } 86 | 87 | return instance; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/db/entities/OrderBookTick.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn, Relation } from 'typeorm'; 2 | import { OrderBook } from './OrderBook'; 3 | 4 | @Entity({ name: 'order_book_ticks' }) 5 | export class OrderBookTick extends BaseEntity { 6 | 7 | @PrimaryGeneratedColumn() 8 | id: number; 9 | 10 | @ManyToOne(() => OrderBook) 11 | @JoinColumn() 12 | orderBook: Relation; 13 | 14 | @Column() 15 | resolution: string; 16 | 17 | @Column() 18 | time: number; 19 | 20 | @Column({ type: 'double' }) 21 | open: number; 22 | 23 | @Column({ type: 'double' }) 24 | high: number; 25 | 26 | @Column({ type: 'double' }) 27 | low: number; 28 | 29 | @Column({ type: 'double' }) 30 | close: number; 31 | 32 | @Column({ type: 'double' }) 33 | volume: number; 34 | 35 | @Column({ type: 'bigint', unsigned: true }) 36 | tvl: number; 37 | 38 | static make( 39 | orderBook: OrderBook, 40 | resolution: string, 41 | time: number, 42 | open: number, 43 | high: number, 44 | low: number, 45 | close: number, 46 | tvl: number = 0, 47 | volume: number = 0, 48 | ): OrderBookTick { 49 | let instance: OrderBookTick = new OrderBookTick(); 50 | 51 | instance.orderBook = orderBook; 52 | instance.resolution = resolution; 53 | instance.time = time; 54 | instance.open = open; 55 | instance.high = high; 56 | instance.low = low; 57 | instance.close = close; 58 | instance.tvl = tvl; 59 | instance.volume = volume; 60 | 61 | return instance; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/db/entities/Sync.ts: -------------------------------------------------------------------------------- 1 | import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; 2 | 3 | @Entity({ name: 'syncs' }) 4 | export class Sync extends BaseEntity { 5 | 6 | @PrimaryGeneratedColumn() 7 | id: number; 8 | 9 | @Column() 10 | blockHash: string; 11 | 12 | @Column({ type: 'bigint', unsigned: true }) 13 | slot: number; 14 | 15 | static make( 16 | blockHash: string, 17 | slot: number, 18 | ): Sync { 19 | let instance: Sync = new Sync(); 20 | 21 | instance.id = 1; 22 | instance.blockHash = blockHash; 23 | instance.slot = slot; 24 | 25 | return instance; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/db/migrations/1692446359397-CreateAssetTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableIndex } from "typeorm"; 2 | 3 | export class CreatAssetTable1692446359397 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'assets', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'policyId', 19 | type: 'varchar(56)', 20 | }, 21 | { 22 | name: 'nameHex', 23 | type: 'varchar', 24 | }, 25 | { 26 | name: 'isLpToken', 27 | type: 'boolean', 28 | }, 29 | { 30 | name: 'isVerified', 31 | type: 'boolean', 32 | default: false, 33 | }, 34 | { 35 | name: 'decimals', 36 | type: 'int', 37 | isNullable: true, 38 | default: null, 39 | }, 40 | { 41 | name: 'name', 42 | type: 'varchar', 43 | isNullable: true, 44 | }, 45 | { 46 | name: 'ticker', 47 | type: 'varchar', 48 | isNullable: true, 49 | }, 50 | { 51 | name: 'logo', 52 | type: 'longtext', 53 | isNullable: true, 54 | }, 55 | { 56 | name: 'description', 57 | type: 'longtext', 58 | isNullable: true, 59 | }, 60 | ], 61 | }), 62 | true 63 | ); 64 | 65 | await queryRunner.createIndex( 66 | 'assets', 67 | new TableIndex({ 68 | columnNames: ['policyId', 'nameHex',], 69 | isUnique: true, 70 | }) 71 | ); 72 | } 73 | 74 | public async down(queryRunner: QueryRunner): Promise { 75 | await queryRunner.dropTable('assets', true, true, true); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/db/migrations/1692532768196-CreateLiquidityPoolsTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableForeignKey, TableIndex } from "typeorm" 2 | 3 | export class CreatLiquidityPoolsTable1692532768196 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'liquidity_pools', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'dex', 19 | type: 'varchar', 20 | }, 21 | { 22 | name: 'identifier', 23 | type: 'varchar', 24 | isUnique: true, 25 | }, 26 | { 27 | name: 'address', 28 | type: 'varchar', 29 | }, 30 | { 31 | name: 'tokenAId', 32 | type: 'int', 33 | isNullable: true, 34 | }, 35 | { 36 | name: 'tokenBId', 37 | type: 'int', 38 | }, 39 | { 40 | name: 'latestStateId', 41 | type: 'int', 42 | isNullable: true, 43 | }, 44 | { 45 | name: 'createdSlot', 46 | type: 'bigint', 47 | unsigned: true, 48 | }, 49 | ], 50 | }), 51 | true 52 | ); 53 | 54 | await queryRunner.createForeignKeys('liquidity_pools', [ 55 | new TableForeignKey({ 56 | columnNames: ['tokenAId'], 57 | referencedColumnNames: ['id'], 58 | referencedTableName: 'assets', 59 | onDelete: 'CASCADE' 60 | }), 61 | new TableForeignKey({ 62 | columnNames: ['tokenBId'], 63 | referencedColumnNames: ['id'], 64 | referencedTableName: 'assets', 65 | onDelete: 'CASCADE' 66 | }), 67 | ]); 68 | 69 | await queryRunner.createIndices('liquidity_pools', [ 70 | new TableIndex({ 71 | columnNames: ['dex', 'tokenAId', 'tokenBId'], 72 | }), 73 | new TableIndex({ 74 | columnNames: ['tokenAId'], 75 | }), 76 | new TableIndex({ 77 | columnNames: ['tokenBId'], 78 | }), 79 | new TableIndex({ 80 | columnNames: ['identifier'], 81 | }), 82 | ]); 83 | } 84 | 85 | public async down(queryRunner: QueryRunner): Promise { 86 | await queryRunner.dropTable('liquidity_pools', true, true, true); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/db/migrations/1692628719789-CreateLiquidityPoolStatesTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableForeignKey, TableIndex } from "typeorm" 2 | 3 | export class CreatLiquidityPoolStatesTable1692628719789 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'liquidity_pool_states', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'liquidityPoolId', 19 | type: 'int', 20 | }, 21 | { 22 | name: 'tokenLpId', 23 | type: 'int', 24 | }, 25 | { 26 | name: 'reserveA', 27 | type: 'bigint', 28 | unsigned: true, 29 | }, 30 | { 31 | name: 'reserveB', 32 | type: 'bigint', 33 | unsigned: true, 34 | }, 35 | { 36 | name: 'lpTokens', 37 | type: 'bigint', 38 | unsigned: true, 39 | }, 40 | { 41 | name: 'tvl', 42 | type: 'bigint', 43 | isNullable: true, 44 | unsigned: true, 45 | }, 46 | { 47 | name: 'feePercent', 48 | type: 'float', 49 | }, 50 | { 51 | name: 'slot', 52 | type: 'bigint', 53 | unsigned: true, 54 | }, 55 | { 56 | name: 'txHash', 57 | type: 'varchar(64)', 58 | }, 59 | ], 60 | }), 61 | true 62 | ); 63 | 64 | await queryRunner.createForeignKeys('liquidity_pool_states', [ 65 | new TableForeignKey({ 66 | columnNames: ['liquidityPoolId'], 67 | referencedColumnNames: ['id'], 68 | referencedTableName: 'liquidity_pools', 69 | onDelete: 'CASCADE' 70 | }), 71 | new TableForeignKey({ 72 | columnNames: ['tokenLpId'], 73 | referencedColumnNames: ['id'], 74 | referencedTableName: 'assets', 75 | onDelete: 'CASCADE' 76 | }) 77 | ]); 78 | 79 | await queryRunner.createIndices('liquidity_pool_states', [ 80 | new TableIndex({ 81 | columnNames: ['liquidityPoolId'], 82 | }), 83 | new TableIndex({ 84 | columnNames: ['slot'], 85 | }), 86 | ]); 87 | } 88 | 89 | public async down(queryRunner: QueryRunner): Promise { 90 | await queryRunner.dropTable('liquidity_pool_states', true, true, true); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/db/migrations/1693421645762-CreateSyncsTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table } from "typeorm" 2 | 3 | export class CreateSyncsTable1693421645762 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'syncs', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'slot', 19 | type: 'bigint', 20 | unsigned: true, 21 | }, 22 | { 23 | name: 'blockHash', 24 | type: 'varchar(64)', 25 | }, 26 | ], 27 | }), 28 | true 29 | ); 30 | } 31 | 32 | public async down(queryRunner: QueryRunner): Promise { 33 | await queryRunner.dropTable('syncs', true); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/db/migrations/1694101486899-CreateOperationStatusesTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableIndex } from "typeorm" 2 | import { DexOperationStatus } from '../../constants'; 3 | 4 | export class CreateOperationStatusesTable1694101486899 implements MigrationInterface { 5 | 6 | public async up(queryRunner: QueryRunner): Promise { 7 | await queryRunner.createTable( 8 | new Table({ 9 | name: 'operation_statuses', 10 | columns: [ 11 | { 12 | name: 'id', 13 | type: 'int', 14 | isPrimary: true, 15 | isGenerated: true, 16 | generationStrategy: 'increment' 17 | }, 18 | { 19 | name: 'operationId', 20 | type: 'int', 21 | }, 22 | { 23 | name: 'operationType', 24 | type: 'varchar', 25 | }, 26 | { 27 | name: 'status', 28 | type: 'int', 29 | default: DexOperationStatus.Pending, 30 | }, 31 | { 32 | name: 'slot', 33 | type: 'bigint', 34 | unsigned: true, 35 | }, 36 | { 37 | name: 'txHash', 38 | type: 'varchar(64)', 39 | }, 40 | { 41 | name: 'outputIndex', 42 | type: 'int', 43 | }, 44 | ], 45 | }), 46 | true 47 | ); 48 | 49 | await queryRunner.createIndices('operation_statuses', [ 50 | new TableIndex({ 51 | columnNames: ['operationId', 'operationType', 'status'], 52 | isUnique: true, 53 | }), 54 | new TableIndex({ 55 | columnNames: ['operationId'], 56 | }), 57 | ]); 58 | } 59 | 60 | public async down(queryRunner: QueryRunner): Promise { 61 | await queryRunner.dropTable('operation_statuses', true, true, true); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/db/migrations/1696953524778-CreateLiquidityPoolTicks.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableForeignKey, TableIndex } from "typeorm" 2 | 3 | export class CreateLiquidityPoolTicks1696953524778 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'liquidity_pool_ticks', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'liquidityPoolId', 19 | type: 'int', 20 | }, 21 | { 22 | name: 'resolution', 23 | type: 'varchar', 24 | }, 25 | { 26 | name: 'time', 27 | type: 'int', 28 | }, 29 | { 30 | name: 'open', 31 | type: 'double', 32 | }, 33 | { 34 | name: 'high', 35 | type: 'double', 36 | }, 37 | { 38 | name: 'low', 39 | type: 'double', 40 | }, 41 | { 42 | name: 'close', 43 | type: 'double', 44 | }, 45 | { 46 | name: 'volume', 47 | type: 'double', 48 | }, 49 | { 50 | name: 'tvl', 51 | type: 'bigint', 52 | isNullable: true, 53 | unsigned: true, 54 | }, 55 | ], 56 | }), 57 | true 58 | ); 59 | 60 | await queryRunner.createForeignKeys('liquidity_pool_ticks', [ 61 | new TableForeignKey({ 62 | columnNames: ['liquidityPoolId'], 63 | referencedColumnNames: ['id'], 64 | referencedTableName: 'liquidity_pools', 65 | onDelete: 'CASCADE' 66 | }), 67 | ]); 68 | 69 | await queryRunner.createIndices('liquidity_pool_ticks', [ 70 | new TableIndex({ 71 | columnNames: ['liquidityPoolId'], 72 | }), 73 | new TableIndex({ 74 | columnNames: ['liquidityPoolId', 'resolution'], 75 | }), 76 | new TableIndex({ 77 | columnNames: ['liquidityPoolId', 'resolution', 'time'], 78 | isUnique: true, 79 | }), 80 | ]); 81 | } 82 | 83 | public async down(queryRunner: QueryRunner): Promise { 84 | await queryRunner.dropTable('liquidity_pool_ticks', true, true, true); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/db/migrations/1699486894637-AddSenderStakeKeyHashOrders.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm" 2 | 3 | export class AddSenderStakeKeyHashOrders1699486894637 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pool_swaps ADD COLUMN senderStakeKeyHash VARCHAR(56) NULL AFTER senderPubKeyHash`, 8 | ); 9 | await queryRunner.query( 10 | `ALTER TABLE liquidity_pool_deposits ADD COLUMN senderStakeKeyHash VARCHAR(56) NULL AFTER senderPubKeyHash`, 11 | ); 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pool_withdraws ADD COLUMN senderStakeKeyHash VARCHAR(56) NULL AFTER senderPubKeyHash`, 14 | ); 15 | await queryRunner.query( 16 | `ALTER TABLE liquidity_pool_zaps ADD COLUMN senderStakeKeyHash VARCHAR(56) NULL AFTER senderPubKeyHash`, 17 | ); 18 | } 19 | 20 | public async down(queryRunner: QueryRunner): Promise { 21 | await queryRunner.query( 22 | `ALTER TABLE liquidity_pool_swaps DROP COLUMN senderStakeKeyHash`, 23 | ); 24 | await queryRunner.query( 25 | `ALTER TABLE liquidity_pool_deposits DROP COLUMN senderStakeKeyHash`, 26 | ); 27 | await queryRunner.query( 28 | `ALTER TABLE liquidity_pool_withdraws DROP COLUMN senderStakeKeyHash`, 29 | ); 30 | await queryRunner.query( 31 | `ALTER TABLE liquidity_pool_withdraws DROP COLUMN senderStakeKeyHash`, 32 | ); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/db/migrations/1700495200089-AddActualReceivedSwapOrders.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm" 2 | 3 | export class AddActualReceivedSwapOrders1700495200089 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pool_swaps ADD COLUMN actualReceive BIGINT UNSIGNED NULL AFTER minReceive`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pool_swaps DROP COLUMN actualReceive`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1703352414322-CreateOrderBooksTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableForeignKey, TableIndex } from "typeorm" 2 | 3 | export class CreateOrderBooksTable1703352414322 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'order_books', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'identifier', 19 | type: 'varchar', 20 | }, 21 | { 22 | name: 'dex', 23 | type: 'varchar', 24 | }, 25 | { 26 | name: 'tokenAId', 27 | type: 'int', 28 | isNullable: true, 29 | }, 30 | { 31 | name: 'tokenBId', 32 | type: 'int', 33 | }, 34 | { 35 | name: 'createdSlot', 36 | type: 'bigint', 37 | unsigned: true, 38 | }, 39 | ], 40 | }), 41 | true 42 | ); 43 | 44 | await queryRunner.createForeignKeys('order_books', [ 45 | new TableForeignKey({ 46 | columnNames: ['tokenAId'], 47 | referencedColumnNames: ['id'], 48 | referencedTableName: 'assets', 49 | onDelete: 'CASCADE' 50 | }), 51 | new TableForeignKey({ 52 | columnNames: ['tokenBId'], 53 | referencedColumnNames: ['id'], 54 | referencedTableName: 'assets', 55 | onDelete: 'CASCADE' 56 | }), 57 | ]); 58 | 59 | await queryRunner.createIndices('order_books', [ 60 | new TableIndex({ 61 | columnNames: ['dex', 'tokenAId', 'tokenBId'], 62 | }), 63 | new TableIndex({ 64 | columnNames: ['identifier'], 65 | }), 66 | ]); 67 | } 68 | 69 | public async down(queryRunner: QueryRunner): Promise { 70 | await queryRunner.dropTable('order_books', true, true, true); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/db/migrations/1703861310521-CreateOrderBookMatchesTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableForeignKey } from "typeorm" 2 | 3 | export class CreateOrderBookMatchesTable1703861310521 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'order_book_matches', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'orderBookId', 19 | type: 'int', 20 | }, 21 | { 22 | name: 'referenceOrderId', 23 | type: 'int', 24 | isNullable: true, 25 | }, 26 | { 27 | name: 'matchedTokenId', 28 | type: 'int', 29 | isNullable: true, 30 | }, 31 | { 32 | name: 'matchedAmount', 33 | type: 'bigint', 34 | unsigned: true, 35 | }, 36 | { 37 | name: 'receiverPubKeyHash', 38 | type: 'varchar', 39 | }, 40 | { 41 | name: 'receiverStakeKeyHash', 42 | type: 'varchar', 43 | }, 44 | { 45 | name: 'slot', 46 | type: 'bigint', 47 | unsigned: true, 48 | }, 49 | { 50 | name: 'txHash', 51 | type: 'varchar(64)', 52 | }, 53 | { 54 | name: 'outputIndex', 55 | type: 'int', 56 | }, 57 | ], 58 | }), 59 | true 60 | ); 61 | 62 | await queryRunner.createForeignKeys('order_book_matches', [ 63 | new TableForeignKey({ 64 | columnNames: ['orderBookId'], 65 | referencedColumnNames: ['id'], 66 | referencedTableName: 'order_books', 67 | onDelete: 'CASCADE' 68 | }), 69 | new TableForeignKey({ 70 | columnNames: ['referenceOrderId'], 71 | referencedColumnNames: ['id'], 72 | referencedTableName: 'order_book_orders', 73 | onDelete: 'CASCADE' 74 | }), 75 | new TableForeignKey({ 76 | columnNames: ['matchedTokenId'], 77 | referencedColumnNames: ['id'], 78 | referencedTableName: 'assets', 79 | onDelete: 'CASCADE' 80 | }), 81 | ]); 82 | } 83 | 84 | public async down(queryRunner: QueryRunner): Promise { 85 | await queryRunner.dropTable('order_book_matches', true, true, true); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/db/migrations/1708799513557-CreateOrderBookTicksTable.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, Table, TableForeignKey, TableIndex } from "typeorm" 2 | 3 | export class CreateOrderBookTicksTable1708799513557 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createTable( 7 | new Table({ 8 | name: 'order_book_ticks', 9 | columns: [ 10 | { 11 | name: 'id', 12 | type: 'int', 13 | isPrimary: true, 14 | isGenerated: true, 15 | generationStrategy: 'increment' 16 | }, 17 | { 18 | name: 'orderBookId', 19 | type: 'int', 20 | }, 21 | { 22 | name: 'resolution', 23 | type: 'varchar', 24 | }, 25 | { 26 | name: 'time', 27 | type: 'int', 28 | }, 29 | { 30 | name: 'open', 31 | type: 'double', 32 | }, 33 | { 34 | name: 'high', 35 | type: 'double', 36 | }, 37 | { 38 | name: 'low', 39 | type: 'double', 40 | }, 41 | { 42 | name: 'close', 43 | type: 'double', 44 | }, 45 | { 46 | name: 'volume', 47 | type: 'double', 48 | }, 49 | { 50 | name: 'tvl', 51 | type: 'bigint', 52 | isNullable: true, 53 | unsigned: true, 54 | }, 55 | ], 56 | }), 57 | true 58 | ); 59 | 60 | await queryRunner.createForeignKeys('order_book_ticks', [ 61 | new TableForeignKey({ 62 | columnNames: ['orderBookId'], 63 | referencedColumnNames: ['id'], 64 | referencedTableName: 'order_books', 65 | onDelete: 'CASCADE' 66 | }), 67 | ]); 68 | 69 | await queryRunner.createIndices('order_book_ticks', [ 70 | new TableIndex({ 71 | columnNames: ['orderBookId'], 72 | }), 73 | new TableIndex({ 74 | columnNames: ['orderBookId', 'resolution'], 75 | }), 76 | new TableIndex({ 77 | columnNames: ['orderBookId', 'resolution', 'time'], 78 | isUnique: true, 79 | }), 80 | ]); 81 | } 82 | 83 | public async down(queryRunner: QueryRunner): Promise { 84 | await queryRunner.dropTable('order_book_ticks', true, true, true); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/db/migrations/1711724722571-AddOrderAddressLiquidityPools.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddOrderAddressLiquidityPools1711724722571 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pools ADD COLUMN orderAddress VARCHAR(255) NULL AFTER address`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pools DROP COLUMN orderAddress`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1712896760348-AddMetaLiquidityPoolSwaps.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddMetaLiquidityPoolSwaps1712896760348 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pool_swaps ADD COLUMN meta VARCHAR(255) NULL AFTER outputIndex`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pool_swaps DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1712896777699-AddMetaLiquidityPoolDeposits.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddMetaLiquidityPoolDeposits1712896777699 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pool_deposits ADD COLUMN meta VARCHAR(255) NULL AFTER outputIndex`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pool_deposits DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1712896783030-AddMetaLiquidityPoolWithdraws.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddMetaLiquidityPoolWithdraws1712896783030 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pool_withdraws ADD COLUMN meta VARCHAR(255) NULL AFTER outputIndex`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pool_withdraws DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1712896788861-AddMetaLiquidityPoolZaps.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddMetaLiquidityPoolZaps1712896788861 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pool_zaps ADD COLUMN meta VARCHAR(255) NULL AFTER outputIndex`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pool_zaps DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1712896804175-AddMetaOrderBookOrders.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddMetaOrderBookOrders1712896804175 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE order_book_orders ADD COLUMN meta VARCHAR(255) NULL AFTER outputIndex`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE order_book_orders DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1712896807992-AddMetaOrderBookMatches.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddMetaOrderBookMatches1712896807992 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE order_book_matches ADD COLUMN meta VARCHAR(255) NULL AFTER outputIndex`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE order_book_matches DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1715612872956-AddMetaAssets.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from "typeorm"; 2 | 3 | export class AddMetaAssets1715612872956 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE assets ADD COLUMN meta VARCHAR(255) NULL AFTER description`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE assets DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/db/migrations/1731944573000-CreateStakeKeyHashIndexes.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner, TableIndex } from 'typeorm'; 2 | 3 | export class CreateStakeKeyHashIndexes1731944573000 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.createIndices('liquidity_pool_swaps', [ 7 | new TableIndex({ 8 | columnNames: ['senderStakeKeyHash'], 9 | isUnique: false, 10 | }), 11 | ]); 12 | await queryRunner.createIndices('liquidity_pool_deposits', [ 13 | new TableIndex({ 14 | columnNames: ['senderStakeKeyHash'], 15 | isUnique: false, 16 | }), 17 | ]); 18 | await queryRunner.createIndices('liquidity_pool_withdraws', [ 19 | new TableIndex({ 20 | columnNames: ['senderStakeKeyHash'], 21 | isUnique: false, 22 | }), 23 | ]); 24 | await queryRunner.createIndices('liquidity_pool_zaps', [ 25 | new TableIndex({ 26 | columnNames: ['senderStakeKeyHash'], 27 | isUnique: false, 28 | }), 29 | ]); 30 | } 31 | 32 | public async down(queryRunner: QueryRunner): Promise { 33 | await queryRunner.dropIndices('liquidity_pool_swaps', [ 34 | new TableIndex({ 35 | columnNames: ['senderStakeKeyHash'], 36 | isUnique: false, 37 | }), 38 | ]); 39 | await queryRunner.dropIndices('liquidity_pool_deposits', [ 40 | new TableIndex({ 41 | columnNames: ['senderStakeKeyHash'], 42 | isUnique: false, 43 | }), 44 | ]); 45 | await queryRunner.dropIndices('liquidity_pool_withdraws', [ 46 | new TableIndex({ 47 | columnNames: ['senderStakeKeyHash'], 48 | isUnique: false, 49 | }), 50 | ]); 51 | await queryRunner.dropIndices('liquidity_pool_zaps', [ 52 | new TableIndex({ 53 | columnNames: ['senderStakeKeyHash'], 54 | isUnique: false, 55 | }), 56 | ]); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/db/migrations/1731944573001-AddMetaLiquidityPools.ts: -------------------------------------------------------------------------------- 1 | import { MigrationInterface, QueryRunner } from 'typeorm'; 2 | 3 | export class AddMetaLiquidityPools1731944573001 implements MigrationInterface { 4 | 5 | public async up(queryRunner: QueryRunner): Promise { 6 | await queryRunner.query( 7 | `ALTER TABLE liquidity_pools ADD COLUMN meta VARCHAR(255) NULL AFTER createdSlot`, 8 | ); 9 | } 10 | 11 | public async down(queryRunner: QueryRunner): Promise { 12 | await queryRunner.query( 13 | `ALTER TABLE liquidity_pools DROP COLUMN meta`, 14 | ); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/dex/AxoAnalyzer.ts: -------------------------------------------------------------------------------- 1 | import { BaseOrderBookDexAnalyzer } from './BaseOrderBookDexAnalyzer'; 2 | import { 3 | AssetBalance, 4 | OrderBookDexOperation, 5 | OrderBookOrderCancellation, 6 | Transaction, 7 | } from '../types'; 8 | import { OrderBookOrder } from '../db/entities/OrderBookOrder'; 9 | import { OrderBookMatch } from '../db/entities/OrderBookMatch'; 10 | 11 | /** 12 | * Axo constants. 13 | */ 14 | const METADATA_LABEL: string = '721'; 15 | const METADATA_PRICE_HEX: string = '7072696365'; 16 | const METADATA_START_DATE_HEX: string = '737461727444617465'; 17 | const METADATA_END_DATE_HEX: string = '656e6444617465'; 18 | 19 | export class AxoAnalyzer extends BaseOrderBookDexAnalyzer { 20 | 21 | public startSlot: number = 110315300; 22 | 23 | public async analyzeTransaction(transaction: Transaction): Promise { 24 | return Promise.all([ 25 | this.orders(transaction), 26 | this.matches(transaction), 27 | this.cancellations(transaction), 28 | ]).then((operations: OrderBookDexOperation[][]) => operations.flat()); 29 | } 30 | 31 | protected orders(transaction: Transaction): Promise | OrderBookOrder[] { 32 | if (! transaction.metadata || ! transaction.metadata[METADATA_LABEL]) { 33 | return []; 34 | } 35 | 36 | const metadata = transaction.metadata[METADATA_LABEL]; 37 | const tokenPolicyId: string | undefined = Object.keys(metadata)[0]; 38 | 39 | if (! tokenPolicyId) return []; 40 | 41 | const orderTokenBalance: AssetBalance | undefined = transaction.outputs[0].assetBalances 42 | .find((balance: AssetBalance) => balance.asset.policyId === tokenPolicyId && balance.quantity === 1n); 43 | const tokenSentToUser: boolean = transaction.outputs.length > 1 && transaction.outputs[1].assetBalances 44 | .some((balance: AssetBalance) => balance.asset.policyId === tokenPolicyId && balance.quantity === 1n) 45 | 46 | if (! orderTokenBalance || ! tokenSentToUser) return []; 47 | 48 | // return transaction.outputs.map((output: Utxo) => { 49 | // if (! output.datum || ! transaction.metadata) { 50 | // return undefined; 51 | // } 52 | // 53 | // return []; 54 | // }) 55 | // .flat().filter((order: OrderBookOrder | undefined) => order !== undefined) as (OrderBookOrder)[]; 56 | 57 | 58 | return Promise.resolve([]); 59 | } 60 | 61 | protected matches(transaction: Transaction): Promise<(OrderBookMatch | OrderBookOrder)[]> | (OrderBookMatch | OrderBookOrder)[] { 62 | return Promise.resolve([]); 63 | } 64 | 65 | protected cancellations(transaction: Transaction): Promise | OrderBookOrderCancellation[] { 66 | return Promise.resolve([]); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/dex/BaseOrderBookDexAnalyzer.ts: -------------------------------------------------------------------------------- 1 | import { OrderBookDexOperation, Transaction } from '../types'; 2 | import { OrderBookOrder } from '../db/entities/OrderBookOrder'; 3 | import { OrderBookMatch } from '../db/entities/OrderBookMatch'; 4 | import { IndexerApplication } from '../IndexerApplication'; 5 | 6 | export abstract class BaseOrderBookDexAnalyzer { 7 | 8 | public app: IndexerApplication; 9 | 10 | public abstract startSlot: number; 11 | 12 | constructor(app: IndexerApplication) { 13 | this.app = app; 14 | } 15 | 16 | public abstract analyzeTransaction(transaction: Transaction): Promise; 17 | 18 | protected abstract orders(transaction: Transaction): Promise | OrderBookOrder[]; 19 | 20 | protected abstract matches(transaction: Transaction): Promise<(OrderBookMatch | OrderBookOrder)[]> | (OrderBookMatch | OrderBookOrder)[]; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/dex/definitions/genius-yield/order.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/geniusyield/dex-contracts-api/blob/8add6b608235095fa019fb6566d8ef1cd81080bf/src/GeniusYield/Scripts/Dex/PartialOrder.hs#L75-L108 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | bytes: DatumParameterKey.SenderPubKeyHash 12 | }, 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | constructor: 0, 18 | fields: [ 19 | { 20 | bytes: DatumParameterKey.SenderPubKeyHash 21 | } 22 | ] 23 | }, 24 | (field: DefinitionField, foundParameters: DatumParameters) => { 25 | if ('fields' in field) { 26 | if (field.constructor === 1) { 27 | return; 28 | } 29 | 30 | const constr: DefinitionField = field.fields[0]; 31 | 32 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 33 | const field: DefinitionField = constr.fields[0].fields[0]; 34 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 35 | 36 | return; 37 | } 38 | } 39 | 40 | throw new Error("Template definition does not match with 'bytes'"); 41 | } 42 | ] 43 | }, 44 | { 45 | constructor: 0, 46 | fields: [ 47 | { 48 | bytes: DatumParameterKey.SwapInTokenPolicyId 49 | }, 50 | { 51 | bytes: DatumParameterKey.SwapInTokenAssetName 52 | } 53 | ] 54 | }, 55 | { 56 | int: DatumParameterKey.OriginalOffer 57 | }, 58 | { 59 | int: DatumParameterKey.LeftOverOffer 60 | }, 61 | { 62 | constructor: 0, 63 | fields: [ 64 | { 65 | bytes: DatumParameterKey.SwapOutTokenPolicyId 66 | }, 67 | { 68 | bytes: DatumParameterKey.SwapOutTokenAssetName 69 | } 70 | ] 71 | }, 72 | { 73 | constructor: 0, 74 | fields: [ 75 | { 76 | int: DatumParameterKey.PriceDenominator 77 | }, 78 | { 79 | int: DatumParameterKey.PriceNumerator 80 | } 81 | ] 82 | }, 83 | { 84 | bytes: DatumParameterKey.TokenAssetName 85 | }, 86 | { 87 | constructor: 1, 88 | fields: [] 89 | }, 90 | { 91 | constructor: 1, 92 | fields: [] 93 | }, 94 | { 95 | int: DatumParameterKey.PastOrderFills 96 | }, 97 | { 98 | int: DatumParameterKey.MakerFee 99 | }, 100 | { 101 | int: DatumParameterKey.TakerFee 102 | }, 103 | { 104 | constructor: 0, 105 | fields: [ 106 | { 107 | int: DatumParameterKey.ContainedFee 108 | }, 109 | { 110 | int: DatumParameterKey.ContainedFeePayment 111 | }, 112 | { 113 | int: DatumParameterKey.Unknown 114 | } 115 | ] 116 | }, 117 | { 118 | int: DatumParameterKey.Unknown 119 | } 120 | ] 121 | } 122 | -------------------------------------------------------------------------------- /src/dex/definitions/genius-yield/partial-fill.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | bytes: DatumParameterKey.ConsumedTxHash, 11 | } 12 | ] 13 | }, 14 | { 15 | int: DatumParameterKey.Action 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/dex/definitions/minswap-v2/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | bytes: DatumParameterKey.SenderPubKeyHash, 11 | } 12 | ] 13 | }, 14 | { 15 | constructor: 0, 16 | fields: [ 17 | { 18 | constructor: 0, 19 | fields: [ 20 | { 21 | bytes:DatumParameterKey.SenderPubKeyHash, 22 | } 23 | ] 24 | }, 25 | { 26 | constructor: 0, 27 | fields: [ 28 | { 29 | constructor: 0, 30 | fields: [ 31 | { 32 | constructor: 0, 33 | fields: [ 34 | { 35 | bytes: DatumParameterKey.SenderStakingKeyHash, 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | ] 44 | }, 45 | { 46 | constructor: 0, 47 | fields: [] 48 | }, 49 | { 50 | constructor: 0, 51 | fields: [ 52 | { 53 | constructor: 0, 54 | fields: [ 55 | { 56 | bytes: DatumParameterKey.SenderPubKeyHash, 57 | } 58 | ] 59 | }, 60 | { 61 | constructor: 0, 62 | fields: [ 63 | { 64 | constructor: 0, 65 | fields: [ 66 | { 67 | constructor: 0, 68 | fields: [ 69 | { 70 | bytes: DatumParameterKey.SenderStakingKeyHash, 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | ] 79 | }, 80 | { 81 | constructor: 0, 82 | fields: [] 83 | }, 84 | { 85 | constructor: 0, 86 | fields: [ 87 | { 88 | bytes: DatumParameterKey.LpTokenPolicyId 89 | }, 90 | { 91 | bytes: DatumParameterKey.LpTokenAssetName 92 | } 93 | ] 94 | }, 95 | { 96 | constructor: 4, 97 | fields: [ 98 | { 99 | constructor: 0, 100 | fields: [ 101 | { 102 | int: DatumParameterKey.DepositA 103 | }, 104 | { 105 | int: DatumParameterKey.DepositB 106 | } 107 | ] 108 | }, 109 | { 110 | int: DatumParameterKey.MinReceive 111 | }, 112 | { 113 | constructor: 0, 114 | fields: [] 115 | } 116 | ] 117 | }, 118 | { 119 | int: DatumParameterKey.BatcherFee 120 | }, 121 | { 122 | constructor: 1, 123 | fields: [] 124 | } 125 | ] 126 | } 127 | -------------------------------------------------------------------------------- /src/dex/definitions/minswap-v2/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | bytes: DatumParameterKey.SenderPubKeyHash, 11 | } 12 | ] 13 | }, 14 | { 15 | constructor: 0, 16 | fields: [ 17 | { 18 | constructor: 0, 19 | fields: [ 20 | { 21 | bytes: DatumParameterKey.SenderPubKeyHash, 22 | } 23 | ] 24 | }, 25 | { 26 | constructor: 0, 27 | fields: [ 28 | { 29 | constructor: 0, 30 | fields: [ 31 | { 32 | constructor: 0, 33 | fields: [ 34 | { 35 | bytes: DatumParameterKey.SenderStakingKeyHash, 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | ] 42 | } 43 | ] 44 | }, 45 | { 46 | constructor: 0, 47 | fields: [] 48 | }, 49 | { 50 | constructor: 0, 51 | fields: [ 52 | { 53 | constructor: 0, 54 | fields: [ 55 | { 56 | bytes: DatumParameterKey.SenderPubKeyHash, 57 | } 58 | ] 59 | }, 60 | { 61 | constructor: 0, 62 | fields: [ 63 | { 64 | constructor: 0, 65 | fields: [ 66 | { 67 | constructor: 0, 68 | fields: [ 69 | { 70 | bytes: DatumParameterKey.SenderStakingKeyHash, 71 | } 72 | ] 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | ] 79 | }, 80 | { 81 | constructor: 0, 82 | fields: [] 83 | }, 84 | { 85 | constructor: 0, 86 | fields: [ 87 | { 88 | bytes: DatumParameterKey.LpTokenPolicyId 89 | }, 90 | { 91 | bytes: DatumParameterKey.LpTokenAssetName 92 | } 93 | ] 94 | }, 95 | { 96 | constructor: 5, 97 | fields: [ 98 | { 99 | constructor: 0, 100 | fields: [ 101 | { 102 | int: DatumParameterKey.LpTokens 103 | } 104 | ] 105 | }, 106 | { 107 | int: DatumParameterKey.MinReceiveA 108 | }, 109 | { 110 | int: DatumParameterKey.MinReceiveB 111 | }, 112 | { 113 | constructor: 0, 114 | fields: [] 115 | } 116 | ] 117 | }, 118 | { 119 | int: DatumParameterKey.BatcherFee 120 | }, 121 | { 122 | constructor: 1, 123 | fields: [] 124 | } 125 | ] 126 | } -------------------------------------------------------------------------------- /src/dex/definitions/minswap-v2/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/minswap/minswap-dex-v2/blob/main/src/types/pool.ts 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | (field: DefinitionField, parameters: DatumParameters, shouldExtract: boolean = true) => { 11 | return; 12 | }, 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.PoolAssetAPolicyId 18 | }, 19 | { 20 | bytes: DatumParameterKey.PoolAssetAAssetName 21 | } 22 | ] 23 | }, 24 | { 25 | constructor: 0, 26 | fields: [ 27 | { 28 | bytes: DatumParameterKey.PoolAssetBPolicyId 29 | }, 30 | { 31 | bytes: DatumParameterKey.PoolAssetBAssetName 32 | } 33 | ] 34 | }, 35 | { 36 | int: DatumParameterKey.TotalLpTokens 37 | }, 38 | { 39 | int: DatumParameterKey.ReserveA 40 | }, 41 | { 42 | int: DatumParameterKey.ReserveB 43 | }, 44 | { 45 | int: DatumParameterKey.BaseFee 46 | }, 47 | { 48 | int: DatumParameterKey.FeeSharingNumerator 49 | }, 50 | (field: DefinitionField, parameters: DatumParameters, shouldExtract: boolean = true) => { 51 | return; 52 | }, 53 | ] 54 | } -------------------------------------------------------------------------------- /src/dex/definitions/minswap-v2/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | /** 4 | * https://github.com/minswap/minswap-dex-v2/blob/main/src/types/order.ts 5 | */ 6 | export default { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | constructor: 0, 11 | fields: [ 12 | { 13 | bytes: DatumParameterKey.SenderPubKeyHash, 14 | } 15 | ] 16 | }, 17 | { 18 | constructor: 0, 19 | fields: [ 20 | { 21 | constructor: 0, 22 | fields: [ 23 | { 24 | bytes: DatumParameterKey.SenderPubKeyHash, 25 | } 26 | ] 27 | }, 28 | { 29 | constructor: 0, 30 | fields: [ 31 | { 32 | constructor: 0, 33 | fields: [ 34 | { 35 | constructor: 0, 36 | fields: [ 37 | { 38 | bytes: DatumParameterKey.SenderStakingKeyHash, 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ] 47 | }, 48 | { 49 | constructor: 0, 50 | fields: [] 51 | }, 52 | { 53 | constructor: 0, 54 | fields: [ 55 | { 56 | constructor: 0, 57 | fields: [ 58 | { 59 | bytes: DatumParameterKey.SenderPubKeyHash, 60 | } 61 | ] 62 | }, 63 | { 64 | constructor: 0, 65 | fields: [ 66 | { 67 | constructor: 0, 68 | fields: [ 69 | { 70 | constructor: 0, 71 | fields: [ 72 | { 73 | bytes: DatumParameterKey.SenderStakingKeyHash, 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | }, 83 | { 84 | constructor: 0, 85 | fields: [] 86 | }, 87 | { 88 | constructor: 0, 89 | fields: [ 90 | { 91 | bytes: DatumParameterKey.LpTokenPolicyId 92 | }, 93 | { 94 | bytes: DatumParameterKey.LpTokenAssetName 95 | } 96 | ] 97 | }, 98 | { 99 | constructor: 0, 100 | fields: [ 101 | { 102 | constructor: DatumParameterKey.Direction, 103 | fields: [] 104 | }, 105 | { 106 | constructor: 0, 107 | fields: [ 108 | { 109 | int: DatumParameterKey.SwapInAmount 110 | } 111 | ] 112 | }, 113 | { 114 | int: DatumParameterKey.MinReceive 115 | }, 116 | { 117 | constructor: DatumParameterKey.Unknown, 118 | fields: [] 119 | } 120 | ] 121 | }, 122 | { 123 | int: DatumParameterKey.BatcherFee 124 | }, 125 | { 126 | constructor: 1, 127 | fields: [] 128 | } 129 | ] 130 | } -------------------------------------------------------------------------------- /src/dex/definitions/minswap-v2/zap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | /** 4 | * https://github.com/minswap/minswap-dex-v2/blob/main/src/types/order.ts 5 | */ 6 | export default { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | constructor: 0, 11 | fields: [ 12 | { 13 | bytes: DatumParameterKey.SenderPubKeyHash, 14 | } 15 | ] 16 | }, 17 | { 18 | constructor: 0, 19 | fields: [ 20 | { 21 | constructor: 0, 22 | fields: [ 23 | { 24 | bytes: DatumParameterKey.SenderPubKeyHash, 25 | } 26 | ] 27 | }, 28 | { 29 | constructor: 0, 30 | fields: [ 31 | { 32 | constructor: 0, 33 | fields: [ 34 | { 35 | constructor: 0, 36 | fields: [ 37 | { 38 | bytes: DatumParameterKey.SenderStakingKeyHash, 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | ] 45 | } 46 | ] 47 | }, 48 | { 49 | constructor: 0, 50 | fields: [] 51 | }, 52 | { 53 | constructor: 0, 54 | fields: [ 55 | { 56 | constructor: 0, 57 | fields: [ 58 | { 59 | bytes: DatumParameterKey.SenderPubKeyHash, 60 | } 61 | ] 62 | }, 63 | { 64 | constructor: 0, 65 | fields: [ 66 | { 67 | constructor: 0, 68 | fields: [ 69 | { 70 | constructor: 0, 71 | fields: [ 72 | { 73 | bytes: DatumParameterKey.SenderPubKeyHash, 74 | } 75 | ] 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | }, 83 | { 84 | constructor: 0, 85 | fields: [] 86 | }, 87 | { 88 | constructor: 0, 89 | fields: [ 90 | { 91 | bytes: DatumParameterKey.LpTokenPolicyId 92 | }, 93 | { 94 | bytes: DatumParameterKey.LpTokenAssetName 95 | } 96 | ] 97 | }, 98 | { 99 | constructor: 4, 100 | fields: [ 101 | { 102 | constructor: 0, 103 | fields: [ 104 | { 105 | int: DatumParameterKey.SwapInA 106 | }, 107 | { 108 | int: DatumParameterKey.SwapInB 109 | } 110 | ] 111 | }, 112 | { 113 | int: DatumParameterKey.MinReceive 114 | }, 115 | { 116 | constructor: 0, 117 | fields: [] 118 | } 119 | ] 120 | }, 121 | { 122 | int: DatumParameterKey.BatcherFee 123 | }, 124 | { 125 | constructor: 1, 126 | fields: [] 127 | } 128 | ] 129 | } -------------------------------------------------------------------------------- /src/dex/definitions/minswap/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/minswap/sdk/blob/main/src/types/order.ts 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.SenderPubKeyHash, 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | constructor: 0, 26 | fields: [ 27 | { 28 | constructor: 0, 29 | fields: [ 30 | { 31 | bytes: DatumParameterKey.SenderStakingKeyHash, 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | ] 38 | } 39 | ] 40 | }, 41 | (field: DefinitionField, foundParameters: DatumParameters) => { 42 | if ('fields' in field) { 43 | if (field.constructor === 1) { 44 | return; 45 | } 46 | 47 | const constr: DefinitionField = field.fields[0]; 48 | 49 | if ('fields' in constr && 'bytes' in constr.fields[0]) { 50 | const nestedField: DefinitionField = constr.fields[0]; 51 | foundParameters[DatumParameterKey.ReceiverPubKeyHash] = nestedField.bytes; 52 | } 53 | 54 | if ('fields' in field.fields[1] && 'fields' in field.fields[1].fields[0] && 'fields' in field.fields[1].fields[0].fields[0] && 'bytes' in field.fields[1].fields[0].fields[0].fields[0]) { 55 | foundParameters[DatumParameterKey.ReceiverStakingKeyHash] = field.fields[1].fields[0].fields[0].fields[0].bytes; 56 | } 57 | return; 58 | } 59 | 60 | throw new Error("Template definition does not match with 'bytes'"); 61 | }, 62 | (field: DefinitionField, foundParameters: DatumParameters) => { 63 | return; 64 | }, 65 | { 66 | constructor: 2, 67 | fields: [ 68 | { 69 | int: DatumParameterKey.MinReceive 70 | } 71 | ] 72 | }, 73 | { 74 | int: DatumParameterKey.BatcherFee 75 | }, 76 | { 77 | int: DatumParameterKey.DepositFee 78 | } 79 | ] 80 | } 81 | -------------------------------------------------------------------------------- /src/dex/definitions/minswap/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/minswap/sdk/blob/main/src/types/order.ts 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.SenderPubKeyHash 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | constructor: 0, 26 | fields: [ 27 | { 28 | constructor: 0, 29 | fields: [ 30 | { 31 | bytes: DatumParameterKey.SenderStakingKeyHash 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | ] 38 | } 39 | ] 40 | }, 41 | (field: DefinitionField, foundParameters: DatumParameters) => { 42 | if ('fields' in field) { 43 | if (field.constructor === 1) { 44 | return; 45 | } 46 | 47 | const constr: DefinitionField = field.fields[0]; 48 | 49 | if ('fields' in constr && 'bytes' in constr.fields[0]) { 50 | const nestedField: DefinitionField = constr.fields[0]; 51 | foundParameters[DatumParameterKey.ReceiverPubKeyHash] = nestedField.bytes; 52 | } 53 | 54 | if ('fields' in field.fields[1] && 'fields' in field.fields[1].fields[0] && 'fields' in field.fields[1].fields[0].fields[0] && 'bytes' in field.fields[1].fields[0].fields[0].fields[0]) { 55 | foundParameters[DatumParameterKey.ReceiverStakingKeyHash] = field.fields[1].fields[0].fields[0].fields[0].bytes; 56 | } 57 | return; 58 | } 59 | 60 | throw new Error("Template definition does not match with 'bytes'"); 61 | }, 62 | (field: DefinitionField, foundParameters: DatumParameters) => { 63 | return 64 | }, 65 | { 66 | constructor: 3, 67 | fields: [ 68 | { 69 | int: DatumParameterKey.MinReceiveA 70 | }, 71 | { 72 | int: DatumParameterKey.MinReceiveB 73 | }, 74 | ] 75 | }, 76 | { 77 | int: DatumParameterKey.BatcherFee 78 | }, 79 | { 80 | int: DatumParameterKey.DepositFee 81 | } 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /src/dex/definitions/minswap/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/CatspersCoffee/contracts/blob/bd6831e6806798032f6bb754d94a06d72d4d28a1/dex/src/Minswap/ConstantProductPool/OnChain.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.PoolAssetAPolicyId 15 | }, 16 | { 17 | bytes: DatumParameterKey.PoolAssetAAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetBPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetBAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | int: DatumParameterKey.TotalLpTokens 34 | }, 35 | { 36 | int: DatumParameterKey.RootKLast 37 | }, 38 | (field: DefinitionField, foundParameters: DatumParameters) => { 39 | // Un-needed data for SenderPubKeyHash & SenderStakingKeyHash 40 | 41 | return; 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /src/dex/definitions/minswap/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/CatspersCoffee/contracts/blob/bd6831e6806798032f6bb754d94a06d72d4d28a1/dex/src/Minswap/BatchOrder/Types.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.SenderPubKeyHash 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | constructor: 0, 26 | fields: [ 27 | { 28 | constructor: 0, 29 | fields: [ 30 | { 31 | bytes: DatumParameterKey.SenderStakingKeyHash 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | ] 38 | } 39 | ] 40 | }, 41 | (field: DefinitionField, foundParameters: DatumParameters) => { 42 | if ('fields' in field) { 43 | if (field.constructor === 1) { 44 | return; 45 | } 46 | 47 | const constr: DefinitionField = field.fields[0]; 48 | 49 | if ('fields' in constr && 'bytes' in constr.fields[0]) { 50 | const nestedField: DefinitionField = constr.fields[0]; 51 | foundParameters[DatumParameterKey.ReceiverPubKeyHash] = nestedField.bytes; 52 | } 53 | 54 | if ('fields' in field.fields[1] && 'fields' in field.fields[1].fields[0] && 'fields' in field.fields[1].fields[0].fields[0] && 'bytes' in field.fields[1].fields[0].fields[0].fields[0]) { 55 | foundParameters[DatumParameterKey.ReceiverStakingKeyHash] = field.fields[1].fields[0].fields[0].fields[0].bytes; 56 | } 57 | return; 58 | } 59 | 60 | throw new Error("Template definition does not match with 'bytes'"); 61 | }, 62 | { 63 | constructor: 1, 64 | fields: [] 65 | }, 66 | { 67 | constructor: 0, 68 | fields: [ 69 | { 70 | constructor: DatumParameterKey.Action, 71 | fields: [ 72 | { 73 | bytes: DatumParameterKey.SwapOutTokenPolicyId 74 | }, 75 | { 76 | bytes: DatumParameterKey.SwapOutTokenAssetName 77 | } 78 | ] 79 | }, 80 | { 81 | int: DatumParameterKey.MinReceive 82 | } 83 | ] 84 | }, 85 | { 86 | int: DatumParameterKey.BatcherFee 87 | }, 88 | { 89 | int: DatumParameterKey.DepositFee 90 | } 91 | ] 92 | } 93 | -------------------------------------------------------------------------------- /src/dex/definitions/minswap/zap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | constructor: 0, 11 | fields: [ 12 | { 13 | bytes: DatumParameterKey.SenderPubKeyHash, 14 | } 15 | ] 16 | }, 17 | { 18 | constructor: 0, 19 | fields: [ 20 | { 21 | constructor: 0, 22 | fields: [ 23 | { 24 | constructor: 0, 25 | fields: [ 26 | { 27 | bytes: DatumParameterKey.SenderStakingKeyHash, 28 | } 29 | ] 30 | } 31 | ] 32 | } 33 | ] 34 | } 35 | ] 36 | }, 37 | { 38 | constructor: 0, 39 | fields: [ 40 | { 41 | constructor: 0, 42 | fields: [ 43 | { 44 | bytes: DatumParameterKey.ReceiverPubKeyHash, 45 | } 46 | ] 47 | }, 48 | { 49 | constructor: 0, 50 | fields: [ 51 | { 52 | constructor: 0, 53 | fields: [ 54 | { 55 | constructor: 0, 56 | fields: [ 57 | { 58 | bytes: DatumParameterKey.ReceiverStakingKeyHash, 59 | } 60 | ] 61 | } 62 | ] 63 | } 64 | ] 65 | } 66 | ] 67 | }, 68 | { 69 | constructor: 1, 70 | fields: [] 71 | }, 72 | { 73 | constructor: 4, 74 | fields: [ 75 | { 76 | constructor: 0, 77 | fields: [ 78 | { 79 | bytes: DatumParameterKey.TokenPolicyId 80 | }, 81 | { 82 | bytes: DatumParameterKey.TokenAssetName 83 | } 84 | ] 85 | }, 86 | { 87 | int: DatumParameterKey.MinReceive 88 | } 89 | ] 90 | }, 91 | { 92 | int: DatumParameterKey.BatcherFee 93 | }, 94 | { 95 | int: DatumParameterKey.DepositFee 96 | } 97 | ] 98 | } 99 | -------------------------------------------------------------------------------- /src/dex/definitions/muesliswap/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.SenderPubKeyHash 15 | } 16 | ] 17 | }, 18 | (field: DefinitionField, foundParameters: DatumParameters) => { 19 | if ('fields' in field) { 20 | if (field.constructor === 1) { 21 | return; 22 | } 23 | 24 | const constr: DefinitionField = field.fields[0]; 25 | 26 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 27 | const field: DefinitionField = constr.fields[0].fields[0]; 28 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 29 | 30 | return; 31 | } 32 | } 33 | 34 | throw new Error("Template definition does not match with 'bytes'"); 35 | } 36 | ] 37 | }, 38 | { 39 | constructor: 0, 40 | fields: [ 41 | { 42 | constructor: 0, 43 | fields: [ 44 | { 45 | bytes: DatumParameterKey.ReceiverPubKeyHash 46 | } 47 | ] 48 | }, 49 | { 50 | constructor: 0, 51 | fields: [ 52 | { 53 | constructor: 0, 54 | fields: [ 55 | { 56 | constructor: 0, 57 | fields: [ 58 | { 59 | bytes: DatumParameterKey.ReceiverStakingKeyHash 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | ] 66 | } 67 | ] 68 | }, 69 | { 70 | constructor: 1, 71 | fields: [] 72 | }, 73 | { 74 | constructor: 0, 75 | fields: [ 76 | { 77 | int: DatumParameterKey.MinReceive 78 | } 79 | ] 80 | }, 81 | { 82 | int: DatumParameterKey.BatcherFee 83 | }, 84 | { 85 | int: DatumParameterKey.DepositFee 86 | }, 87 | { 88 | bytes: DatumParameterKey.LpTokenAssetName 89 | }, 90 | { 91 | bytes: DatumParameterKey.TokenAssetName // Factory token name 92 | } 93 | ] 94 | } 95 | 96 | -------------------------------------------------------------------------------- /src/dex/definitions/muesliswap/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.SenderPubKeyHash 15 | } 16 | ] 17 | }, 18 | (field: DefinitionField, foundParameters: DatumParameters) => { 19 | if ('fields' in field) { 20 | if (field.constructor === 1) { 21 | return; 22 | } 23 | 24 | const constr: DefinitionField = field.fields[0]; 25 | 26 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 27 | const field: DefinitionField = constr.fields[0].fields[0]; 28 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 29 | 30 | return; 31 | } 32 | } 33 | 34 | throw new Error("Template definition does not match with 'bytes'"); 35 | } 36 | ] 37 | }, 38 | { 39 | constructor: 0, 40 | fields: [ 41 | { 42 | constructor: 0, 43 | fields: [ 44 | { 45 | bytes: DatumParameterKey.ReceiverPubKeyHash 46 | } 47 | ] 48 | }, 49 | { 50 | constructor: 0, 51 | fields: [ 52 | { 53 | constructor: 0, 54 | fields: [ 55 | { 56 | constructor: 0, 57 | fields: [ 58 | { 59 | bytes: DatumParameterKey.ReceiverStakingKeyHash 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | ] 66 | } 67 | ] 68 | }, 69 | { 70 | constructor: 1, 71 | fields: [] 72 | }, 73 | { 74 | constructor: 1, 75 | fields: [ 76 | { 77 | int: DatumParameterKey.MinReceiveA 78 | }, 79 | { 80 | int: DatumParameterKey.MinReceiveB 81 | } 82 | ] 83 | }, 84 | { 85 | int: DatumParameterKey.BatcherFee 86 | }, 87 | { 88 | int: DatumParameterKey.DepositFee 89 | }, 90 | { 91 | bytes: DatumParameterKey.LpTokenAssetName 92 | }, 93 | { 94 | bytes: DatumParameterKey.TokenAssetName // Factory token name 95 | } 96 | ] 97 | } 98 | -------------------------------------------------------------------------------- /src/dex/definitions/muesliswap/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/MuesliSwapTeam/muesliswap-cardano-pool-contracts/blob/main/dex/src/MuesliSwapPools/ConstantProductPool/OnChain.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.PoolAssetAPolicyId 15 | }, 16 | { 17 | bytes: DatumParameterKey.PoolAssetAAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetBPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetBAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | int: DatumParameterKey.TotalLpTokens 34 | }, 35 | { 36 | int: DatumParameterKey.LpFee 37 | }, 38 | (field: DefinitionField, foundParameters: DatumParameters) => { 39 | return; // Concentrated LPs 40 | }, 41 | (field: DefinitionField, foundParameters: DatumParameters) => { 42 | return; // Concentrated LPs 43 | }, 44 | (field: DefinitionField, foundParameters: DatumParameters) => { 45 | return; // Concentrated LPs 46 | }, 47 | (field: DefinitionField, foundParameters: DatumParameters) => { 48 | return; // Concentrated LPs 49 | }, 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /src/dex/definitions/muesliswap/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.SenderPubKeyHash 18 | } 19 | ] 20 | }, 21 | (field: DefinitionField, foundParameters: DatumParameters) => { 22 | if ('fields' in field) { 23 | if (field.constructor === 1) { 24 | return; 25 | } 26 | 27 | const constr: DefinitionField = field.fields[0]; 28 | 29 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 30 | const field: DefinitionField = constr.fields[0].fields[0]; 31 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 32 | 33 | return; 34 | } 35 | } 36 | 37 | throw new Error("Template definition does not match with 'bytes'"); 38 | } 39 | ] 40 | }, 41 | { 42 | bytes: DatumParameterKey.SwapOutTokenPolicyId 43 | }, 44 | { 45 | bytes: DatumParameterKey.SwapOutTokenAssetName 46 | }, 47 | { 48 | bytes: DatumParameterKey.SwapInTokenPolicyId 49 | }, 50 | { 51 | bytes: DatumParameterKey.SwapInTokenAssetName 52 | }, 53 | { 54 | int: DatumParameterKey.MinReceive 55 | }, 56 | (field: DefinitionField, foundParameters: DatumParameters) => { 57 | if ('fields' in field) { 58 | foundParameters[DatumParameterKey.AllowPartialFill] = field.constructor; 59 | return; 60 | } 61 | 62 | if ('int' in field) { 63 | foundParameters[DatumParameterKey.TotalFees] = field['int']; 64 | return; 65 | } 66 | 67 | throw new Error("Template definition does not match with 'bytes'"); 68 | }, 69 | (field: DefinitionField, foundParameters: DatumParameters) => { 70 | if ('fields' in field) { 71 | foundParameters[DatumParameterKey.AllowPartialFill] = field.constructor; 72 | return; 73 | } 74 | 75 | if ('int' in field) { 76 | foundParameters[DatumParameterKey.TotalFees] = field['int']; 77 | return; 78 | } 79 | 80 | throw new Error("Template definition does not match with 'bytes'"); 81 | }, 82 | ] 83 | } 84 | ] 85 | }; 86 | -------------------------------------------------------------------------------- /src/dex/definitions/spectrum/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Deposit.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 15 | }, 16 | { 17 | bytes: DatumParameterKey.TokenAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetAPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetAAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.PoolAssetBPolicyId 37 | }, 38 | { 39 | bytes: DatumParameterKey.PoolAssetBAssetName 40 | } 41 | ] 42 | }, 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | bytes: DatumParameterKey.LpTokenPolicyId 48 | }, 49 | { 50 | bytes: DatumParameterKey.LpTokenAssetName 51 | } 52 | ] 53 | }, 54 | { 55 | int: DatumParameterKey.ExecutionFee 56 | }, 57 | { 58 | bytes: DatumParameterKey.SenderPubKeyHash 59 | }, 60 | (field: DefinitionField, foundParameters: DatumParameters) => { 61 | if ('fields' in field) { 62 | if (field.constructor === 1) { 63 | return; 64 | } 65 | 66 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 67 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 68 | } 69 | } 70 | }, 71 | { 72 | int: DatumParameterKey.Deposit 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /src/dex/definitions/spectrum/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Redeem.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 15 | }, 16 | { 17 | bytes: DatumParameterKey.TokenAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetAPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetAAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.PoolAssetBPolicyId 37 | }, 38 | { 39 | bytes: DatumParameterKey.PoolAssetBAssetName 40 | } 41 | ] 42 | }, 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | bytes: DatumParameterKey.LpTokenPolicyId 48 | }, 49 | { 50 | bytes: DatumParameterKey.LpTokenAssetName 51 | } 52 | ] 53 | }, 54 | { 55 | int: DatumParameterKey.ExecutionFee 56 | }, 57 | { 58 | bytes: DatumParameterKey.SenderPubKeyHash 59 | }, 60 | (field: DefinitionField, foundParameters: DatumParameters) => { 61 | if ('fields' in field) { 62 | if (field.constructor === 1) { 63 | return; 64 | } 65 | 66 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 67 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 68 | } 69 | } 70 | }, 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /src/dex/definitions/spectrum/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | /** 4 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Pool.hs#L48 5 | */ 6 | export default { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | constructor: 0, 11 | fields: [ 12 | { 13 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 14 | }, 15 | { 16 | bytes: DatumParameterKey.TokenAssetName 17 | } 18 | ] 19 | }, 20 | { 21 | constructor: 0, 22 | fields: [ 23 | { 24 | bytes: DatumParameterKey.PoolAssetAPolicyId 25 | }, 26 | { 27 | bytes: DatumParameterKey.PoolAssetAAssetName 28 | } 29 | ] 30 | }, 31 | { 32 | constructor: 0, 33 | fields: [ 34 | { 35 | bytes: DatumParameterKey.PoolAssetBPolicyId 36 | }, 37 | { 38 | bytes: DatumParameterKey.PoolAssetBAssetName 39 | } 40 | ] 41 | }, 42 | { 43 | constructor: 0, 44 | fields: [ 45 | { 46 | bytes: DatumParameterKey.LpTokenPolicyId 47 | }, 48 | { 49 | bytes: DatumParameterKey.LpTokenAssetName 50 | } 51 | ] 52 | }, 53 | { 54 | int: DatumParameterKey.LpFee 55 | }, 56 | [ 57 | { 58 | bytes: DatumParameterKey.StakeAdminPolicy 59 | } 60 | ], 61 | { 62 | int: DatumParameterKey.LqBound 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /src/dex/definitions/spectrum/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Swap.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.SwapInTokenPolicyId 15 | }, 16 | { 17 | bytes: DatumParameterKey.SwapInTokenAssetName 18 | } 19 | ], 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.SwapOutTokenPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.SwapOutTokenAssetName 29 | } 30 | ], 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 37 | }, 38 | { 39 | bytes: DatumParameterKey.TokenAssetName 40 | } 41 | ], 42 | }, 43 | { 44 | int: DatumParameterKey.LpFee 45 | }, 46 | { 47 | int: DatumParameterKey.LpFeeNumerator // Execution fee numerator 48 | }, 49 | { 50 | int: DatumParameterKey.LpFeeDenominator // Execution fee denominator 51 | }, 52 | { 53 | bytes: DatumParameterKey.SenderPubKeyHash 54 | }, 55 | (field: DefinitionField, foundParameters: DatumParameters) => { 56 | if ('fields' in field) { 57 | if (field.constructor === 1) { 58 | return; 59 | } 60 | 61 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 62 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 63 | } 64 | } 65 | }, 66 | { 67 | int: DatumParameterKey.SwapInAmount 68 | }, 69 | { 70 | int: DatumParameterKey.MinReceive 71 | } 72 | ], 73 | } 74 | -------------------------------------------------------------------------------- /src/dex/definitions/splash/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Deposit.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 15 | }, 16 | { 17 | bytes: DatumParameterKey.TokenAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetAPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetAAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.PoolAssetBPolicyId 37 | }, 38 | { 39 | bytes: DatumParameterKey.PoolAssetBAssetName 40 | } 41 | ] 42 | }, 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | bytes: DatumParameterKey.LpTokenPolicyId 48 | }, 49 | { 50 | bytes: DatumParameterKey.LpTokenAssetName 51 | } 52 | ] 53 | }, 54 | { 55 | int: DatumParameterKey.ExecutionFee 56 | }, 57 | { 58 | bytes: DatumParameterKey.SenderPubKeyHash 59 | }, 60 | (field: DefinitionField, foundParameters: DatumParameters) => { 61 | if ('fields' in field) { 62 | if (field.constructor === 1) { 63 | return; 64 | } 65 | 66 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 67 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 68 | } 69 | } 70 | }, 71 | { 72 | int: DatumParameterKey.Deposit 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /src/dex/definitions/splash/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Redeem.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 15 | }, 16 | { 17 | bytes: DatumParameterKey.TokenAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetAPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetAAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.PoolAssetBPolicyId 37 | }, 38 | { 39 | bytes: DatumParameterKey.PoolAssetBAssetName 40 | } 41 | ] 42 | }, 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | bytes: DatumParameterKey.LpTokenPolicyId 48 | }, 49 | { 50 | bytes: DatumParameterKey.LpTokenAssetName 51 | } 52 | ] 53 | }, 54 | { 55 | int: DatumParameterKey.ExecutionFee 56 | }, 57 | { 58 | bytes: DatumParameterKey.SenderPubKeyHash 59 | }, 60 | (field: DefinitionField, foundParameters: DatumParameters) => { 61 | if ('fields' in field) { 62 | if (field.constructor === 1) { 63 | return; 64 | } 65 | 66 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 67 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 68 | } 69 | } 70 | }, 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /src/dex/definitions/splash/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionBytes, DefinitionConstr, DefinitionField, DefinitionInt } from '../../../types'; 3 | 4 | export default (field: DefinitionField, parameters: DatumParameters) => { 5 | if (! ('fields' in field)) return parameters; 6 | 7 | const fields: DefinitionField[] = field.fields; 8 | 9 | parameters[DatumParameterKey.TokenPolicyId] = ((fields[0] as DefinitionConstr).fields[0] as DefinitionBytes).bytes; 10 | parameters[DatumParameterKey.TokenAssetName] = ((fields[0] as DefinitionConstr).fields[1] as DefinitionBytes).bytes; 11 | parameters[DatumParameterKey.PoolAssetAPolicyId] = ((fields[1] as DefinitionConstr).fields[0] as DefinitionBytes).bytes; 12 | parameters[DatumParameterKey.PoolAssetAAssetName] = ((fields[1] as DefinitionConstr).fields[1] as DefinitionBytes).bytes; 13 | parameters[DatumParameterKey.PoolAssetBPolicyId] = ((fields[2] as DefinitionConstr).fields[0] as DefinitionBytes).bytes; 14 | parameters[DatumParameterKey.PoolAssetBAssetName] = ((fields[2] as DefinitionConstr).fields[1] as DefinitionBytes).bytes; 15 | parameters[DatumParameterKey.LpTokenPolicyId] = ((fields[3] as DefinitionConstr).fields[0] as DefinitionBytes).bytes; 16 | parameters[DatumParameterKey.LpTokenAssetName] = ((fields[3] as DefinitionConstr).fields[1] as DefinitionBytes).bytes; 17 | parameters[DatumParameterKey.LpFee] = (fields[4] as DefinitionInt).int; 18 | 19 | parameters[DatumParameterKey.TreasuryFee] = 0; 20 | parameters[DatumParameterKey.PoolAssetATreasury] = 0; 21 | parameters[DatumParameterKey.PoolAssetBTreasury] = 0; 22 | 23 | if (fields[5] instanceof Array) return parameters; 24 | 25 | parameters[DatumParameterKey.TreasuryFee] = (fields[5] as DefinitionInt).int; 26 | parameters[DatumParameterKey.PoolAssetATreasury] = (fields[6] as DefinitionInt).int; 27 | parameters[DatumParameterKey.PoolAssetBTreasury] = (fields[7] as DefinitionInt).int; 28 | 29 | return parameters; 30 | } 31 | -------------------------------------------------------------------------------- /src/dex/definitions/splash/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | bytes: DatumParameterKey.Action 9 | }, 10 | { 11 | bytes: DatumParameterKey.Beacon 12 | }, 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.SwapInTokenPolicyId 18 | }, 19 | { 20 | bytes: DatumParameterKey.SwapInTokenAssetName 21 | } 22 | ] 23 | }, 24 | { 25 | int: DatumParameterKey.SwapInAmount 26 | }, 27 | { 28 | int: DatumParameterKey.BaseFee 29 | }, 30 | { 31 | int: DatumParameterKey.MinReceive 32 | }, 33 | { 34 | constructor: 0, 35 | fields: [ 36 | { 37 | bytes: DatumParameterKey.SwapOutTokenPolicyId 38 | }, 39 | { 40 | bytes: DatumParameterKey.SwapOutTokenAssetName 41 | } 42 | ] 43 | }, 44 | { 45 | constructor: 0, 46 | fields: [ 47 | { 48 | int: DatumParameterKey.LpFeeNumerator, 49 | }, 50 | { 51 | int: DatumParameterKey.LpFeeDenominator, 52 | } 53 | ] 54 | }, 55 | { 56 | int: DatumParameterKey.ExecutionFee 57 | }, 58 | { 59 | constructor: 0, 60 | fields: [ 61 | { 62 | constructor: 0, 63 | fields: [ 64 | { 65 | bytes: DatumParameterKey.SenderPubKeyHash 66 | } 67 | ] 68 | }, 69 | { 70 | constructor: 0, 71 | fields: [ 72 | { 73 | constructor: 0, 74 | fields: [ 75 | (field: DefinitionField, parameters: DatumParameters) => { 76 | if ('fields' in field) { 77 | if (field.constructor === 1) return; 78 | 79 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 80 | parameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 81 | } 82 | } 83 | 84 | return; 85 | }, 86 | ] 87 | } 88 | ] 89 | } 90 | ] 91 | }, 92 | { 93 | bytes: DatumParameterKey.SenderPubKeyHash 94 | }, 95 | [ 96 | { 97 | bytes: DatumParameterKey.Batcher 98 | } 99 | ] 100 | ] 101 | } -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap-v3/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | bytes: DatumParameterKey.PoolIdentifier 11 | } 12 | ] 13 | }, 14 | { 15 | constructor: 0, 16 | fields: [ 17 | { 18 | bytes: DatumParameterKey.SenderStakingKeyHash 19 | } 20 | ] 21 | }, 22 | { 23 | int: DatumParameterKey.ProtocolFee 24 | }, 25 | { 26 | constructor: 0, 27 | fields: [ 28 | { 29 | constructor: 0, 30 | fields: [ 31 | { 32 | constructor: 0, 33 | fields: [ 34 | { 35 | bytes: DatumParameterKey.SenderPubKeyHash 36 | } 37 | ] 38 | }, 39 | { 40 | constructor: 0, 41 | fields: [ 42 | { 43 | constructor: 0, 44 | fields: [ 45 | { 46 | constructor: 0, 47 | fields: [ 48 | { 49 | bytes: DatumParameterKey.SenderStakingKeyHash 50 | } 51 | ] 52 | } 53 | ] 54 | } 55 | ] 56 | } 57 | ] 58 | }, 59 | { 60 | constructor: 0, 61 | fields: [] 62 | } 63 | ] 64 | }, 65 | { 66 | constructor: 2, 67 | fields: [ 68 | [ 69 | [ 70 | { 71 | bytes: DatumParameterKey.PoolAssetAPolicyId 72 | }, 73 | { 74 | bytes: DatumParameterKey.PoolAssetAAssetName 75 | }, 76 | { 77 | int: DatumParameterKey.DepositA 78 | } 79 | ], 80 | [ 81 | { 82 | bytes: DatumParameterKey.PoolAssetBPolicyId 83 | }, 84 | { 85 | bytes: DatumParameterKey.PoolAssetBAssetName 86 | }, 87 | { 88 | int: DatumParameterKey.DepositB 89 | } 90 | ] 91 | ] 92 | ] 93 | }, 94 | { 95 | bytes: DatumParameterKey.CancelDatum 96 | } 97 | ] 98 | } -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap-v3/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | bytes: DatumParameterKey.PoolIdentifier 12 | } 13 | ] 14 | }, 15 | { 16 | constructor: 0, 17 | fields: [ 18 | { 19 | bytes: DatumParameterKey.SenderStakingKeyHash 20 | } 21 | ] 22 | }, 23 | { 24 | int: DatumParameterKey.ProtocolFee 25 | }, 26 | { 27 | constructor: 0, 28 | fields: [ 29 | { 30 | constructor: 0, 31 | fields: [ 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.SenderPubKeyHash 37 | } 38 | ] 39 | }, 40 | { 41 | constructor: 0, 42 | fields: [ 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | constructor: 0, 48 | fields: [ 49 | { 50 | bytes: DatumParameterKey.SenderStakingKeyHash 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | ] 59 | }, 60 | { 61 | constructor: 0, 62 | fields: [] 63 | } 64 | ] 65 | }, 66 | { 67 | constructor: 3, 68 | fields: [ 69 | [ 70 | { 71 | bytes: DatumParameterKey.LpTokenPolicyId 72 | }, 73 | { 74 | bytes: DatumParameterKey.LpTokenAssetName 75 | }, 76 | { 77 | int: DatumParameterKey.LpTokens 78 | } 79 | ] 80 | ] 81 | }, 82 | { 83 | bytes: DatumParameterKey.CancelDatum 84 | } 85 | ] 86 | } 87 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap-v3/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | bytes: DatumParameterKey.PoolIdentifier, 9 | }, 10 | [ 11 | [ 12 | { 13 | bytes: DatumParameterKey.PoolAssetAPolicyId 14 | }, 15 | { 16 | bytes: DatumParameterKey.PoolAssetAAssetName 17 | } 18 | ], 19 | [ 20 | { 21 | bytes: DatumParameterKey.PoolAssetBPolicyId 22 | }, 23 | { 24 | bytes: DatumParameterKey.PoolAssetBAssetName 25 | } 26 | ] 27 | ], 28 | { 29 | int: DatumParameterKey.TotalLpTokens 30 | }, 31 | { 32 | int: DatumParameterKey.OpeningFee 33 | }, 34 | { 35 | int: DatumParameterKey.FinalFee 36 | }, 37 | (field: DefinitionField, parameters: DatumParameters) => { 38 | return parameters; 39 | }, 40 | ], 41 | }; 42 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap-v3/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | bytes: DatumParameterKey.PoolIdentifier, 12 | }, 13 | ], 14 | }, 15 | { 16 | constructor: DatumParameterKey.Unknown, 17 | fields: [ 18 | { 19 | bytes: DatumParameterKey.Unknown, 20 | }, 21 | ], 22 | }, 23 | { 24 | int: DatumParameterKey.ProtocolFee, 25 | }, 26 | { 27 | constructor: 0, 28 | fields: [ 29 | { 30 | constructor: 0, 31 | fields: [ 32 | { 33 | constructor: DatumParameterKey.Unknown, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.SenderPubKeyHash, 37 | }, 38 | ], 39 | }, 40 | (field: DefinitionField, foundParameters: DatumParameters) => { 41 | if ('fields' in field) { 42 | if (field.constructor === 1) { 43 | return; 44 | } 45 | 46 | const constr: DefinitionField = field.fields[0]; 47 | 48 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 49 | const field: DefinitionField = constr.fields[0].fields[0]; 50 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 51 | 52 | return; 53 | } 54 | } 55 | 56 | throw new Error("Template definition does not match with 'bytes'"); 57 | } 58 | ], 59 | }, 60 | (field: DefinitionField, parameters: DatumParameters, shouldExtract: boolean = true) => { 61 | return; 62 | }, 63 | ], 64 | }, 65 | { 66 | constructor: 1, 67 | fields: [ 68 | [ 69 | { 70 | bytes: DatumParameterKey.SwapInTokenPolicyId, 71 | }, 72 | { 73 | bytes: DatumParameterKey.SwapInTokenAssetName, 74 | }, 75 | { 76 | int: DatumParameterKey.SwapInAmount, 77 | }, 78 | ], 79 | [ 80 | { 81 | bytes: DatumParameterKey.SwapOutTokenPolicyId, 82 | }, 83 | { 84 | bytes: DatumParameterKey.SwapOutTokenAssetName, 85 | }, 86 | { 87 | int: DatumParameterKey.MinReceive, 88 | }, 89 | ], 90 | ], 91 | }, 92 | (field: DefinitionField, parameters: DatumParameters, shouldExtract: boolean = true) => { 93 | return; 94 | }, 95 | ], 96 | } 97 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap-v3/zap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | bytes: DatumParameterKey.PoolIdentifier, 12 | } 13 | ] 14 | }, 15 | { 16 | constructor: 0, 17 | fields: [ 18 | { 19 | bytes: DatumParameterKey.SenderStakingKeyHash, 20 | } 21 | ] 22 | }, 23 | { 24 | int: DatumParameterKey.ProtocolFee, 25 | }, 26 | { 27 | constructor: 0, 28 | fields: [ 29 | { 30 | constructor: 0, 31 | fields: [ 32 | { 33 | constructor: 1, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.SenderPubKeyHash, 37 | } 38 | ] 39 | }, 40 | { 41 | constructor: 0, 42 | fields: [ 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | constructor: 0, 48 | fields: [ 49 | { 50 | bytes: DatumParameterKey.SenderStakingKeyHash, 51 | } 52 | ] 53 | } 54 | ] 55 | } 56 | ] 57 | } 58 | ] 59 | }, 60 | (field: DefinitionField, parameters: DatumParameters, shouldExtract: boolean = true) => { 61 | return; 62 | }, 63 | ] 64 | }, 65 | { 66 | constructor: 1, 67 | fields: [ 68 | [ 69 | { 70 | bytes: DatumParameterKey.PoolAssetAPolicyId 71 | }, 72 | { 73 | bytes: DatumParameterKey.PoolAssetAAssetName 74 | }, 75 | { 76 | int: DatumParameterKey.DepositA 77 | } 78 | ], 79 | [ 80 | { 81 | bytes: DatumParameterKey.PoolAssetBPolicyId 82 | }, 83 | { 84 | bytes: DatumParameterKey.PoolAssetBAssetName 85 | }, 86 | { 87 | int: DatumParameterKey.DepositB 88 | } 89 | ] 90 | ] 91 | }, 92 | { 93 | bytes: DatumParameterKey.CancelDatum, 94 | } 95 | ] 96 | } 97 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | bytes: DatumParameterKey.PoolIdentifier 9 | }, 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | constructor: 0, 18 | fields: [ 19 | { 20 | constructor: 0, 21 | fields: [ 22 | { 23 | bytes: DatumParameterKey.SenderPubKeyHash 24 | } 25 | ] 26 | }, 27 | (field: DefinitionField, foundParameters: DatumParameters) => { 28 | if ('fields' in field) { 29 | if (field.constructor === 1) { 30 | return; 31 | } 32 | 33 | const constr: DefinitionField = field.fields[0]; 34 | 35 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 36 | const field: DefinitionField = constr.fields[0].fields[0]; 37 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 38 | 39 | return; 40 | } 41 | } 42 | 43 | throw new Error("Template definition does not match with 'bytes'"); 44 | } 45 | ] 46 | }, 47 | { 48 | constructor: 1, 49 | fields: [] 50 | } 51 | ] 52 | }, 53 | { 54 | constructor: 1, 55 | fields: [] 56 | } 57 | ] 58 | }, 59 | { 60 | int: DatumParameterKey.ScooperFee 61 | }, 62 | { 63 | constructor: 2, 64 | fields: [ 65 | { 66 | constructor: 1, 67 | fields: [ 68 | { 69 | constructor: 0, 70 | fields: [ 71 | { 72 | int: DatumParameterKey.DepositA 73 | }, 74 | { 75 | int: DatumParameterKey.DepositB 76 | } 77 | ] 78 | } 79 | ] 80 | } 81 | ] 82 | } 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | bytes: DatumParameterKey.PoolIdentifier 9 | }, 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | constructor: 0, 18 | fields: [ 19 | { 20 | constructor: 0, 21 | fields: [ 22 | { 23 | bytes: DatumParameterKey.SenderPubKeyHash 24 | } 25 | ] 26 | }, 27 | (field: DefinitionField, foundParameters: DatumParameters) => { 28 | if ('fields' in field) { 29 | if (field.constructor === 1) { 30 | return; 31 | } 32 | 33 | const constr: DefinitionField = field.fields[0]; 34 | 35 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 36 | const field: DefinitionField = constr.fields[0].fields[0]; 37 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 38 | 39 | return; 40 | } 41 | } 42 | 43 | throw new Error("Template definition does not match with 'bytes'"); 44 | } 45 | ] 46 | }, 47 | { 48 | constructor: 1, 49 | fields: [] 50 | } 51 | ] 52 | }, 53 | { 54 | constructor: 1, 55 | fields: [] 56 | } 57 | ] 58 | }, 59 | { 60 | int: DatumParameterKey.ScooperFee 61 | }, 62 | { 63 | constructor: 1, 64 | fields: [ 65 | { 66 | int: DatumParameterKey.LpTokens 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | constructor: 0, 11 | fields: [ 12 | { 13 | bytes: DatumParameterKey.PoolAssetAPolicyId 14 | }, 15 | { 16 | bytes: DatumParameterKey.PoolAssetAAssetName 17 | } 18 | ] 19 | }, 20 | { 21 | constructor: 0, 22 | fields: [ 23 | { 24 | bytes: DatumParameterKey.PoolAssetBPolicyId 25 | }, 26 | { 27 | bytes: DatumParameterKey.PoolAssetBAssetName 28 | } 29 | ] 30 | } 31 | ] 32 | }, 33 | { 34 | bytes: DatumParameterKey.PoolIdentifier 35 | }, 36 | { 37 | int: DatumParameterKey.TotalLpTokens 38 | }, 39 | { 40 | constructor: 0, 41 | fields: [ 42 | { 43 | int: DatumParameterKey.LpFeeNumerator 44 | }, 45 | { 46 | int: DatumParameterKey.LpFeeDenominator 47 | } 48 | ] 49 | } 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | bytes: DatumParameterKey.PoolIdentifier 9 | }, 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | constructor: 0, 18 | fields: [ 19 | { 20 | constructor: 0, 21 | fields: [ 22 | { 23 | bytes: DatumParameterKey.SenderPubKeyHash 24 | } 25 | ] 26 | }, 27 | (field: DefinitionField, foundParameters: DatumParameters) => { 28 | if ('fields' in field) { 29 | if (field.constructor === 1) { 30 | return; 31 | } 32 | 33 | const constr: DefinitionField = field.fields[0]; 34 | 35 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 36 | const field: DefinitionField = constr.fields[0].fields[0]; 37 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 38 | 39 | return; 40 | } 41 | } 42 | 43 | throw new Error("Template definition does not match with 'bytes'"); 44 | } 45 | ] 46 | }, 47 | { 48 | constructor: 1, 49 | fields: [] 50 | } 51 | ] 52 | }, 53 | { 54 | constructor: 1, 55 | fields: [] 56 | } 57 | ] 58 | }, 59 | { 60 | int: DatumParameterKey.ScooperFee 61 | }, 62 | { 63 | constructor: 0, 64 | fields: [ 65 | { 66 | constructor: DatumParameterKey.Action, 67 | fields: [] 68 | }, 69 | { 70 | int: DatumParameterKey.SwapInAmount 71 | }, 72 | { 73 | constructor: 0, 74 | fields: [ 75 | { 76 | int: DatumParameterKey.MinReceive 77 | } 78 | ] 79 | } 80 | ] 81 | } 82 | ] 83 | } 84 | -------------------------------------------------------------------------------- /src/dex/definitions/sundaeswap/zap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | /** 4 | * https://github.com/SundaeSwap-finance/sundae-sdk/blob/27bdb4b092a3180b05b79b3a8c8cb880dc211efe/packages/core/src/classes/Extensions/DatumBuilders/DatumBuilder.Lucid.class.ts#L137 5 | */ 6 | export default { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | bytes: DatumParameterKey.PoolIdentifier 11 | }, 12 | { 13 | constructor: 0, 14 | fields: [ 15 | { 16 | constructor: 0, 17 | fields: [ 18 | { 19 | constructor: 0, 20 | fields: [ 21 | { 22 | constructor: 1, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.RequestScriptHash 26 | } 27 | ] 28 | }, 29 | { 30 | constructor: 1, 31 | fields: [] 32 | } 33 | ] 34 | }, 35 | { 36 | constructor: 0, 37 | fields: [ 38 | { 39 | bytes: DatumParameterKey.Unknown 40 | } 41 | ] 42 | } 43 | ] 44 | }, 45 | { 46 | constructor: 0, 47 | fields: [ 48 | { 49 | bytes: DatumParameterKey.ReceiverPubKeyHash 50 | } 51 | ] 52 | } 53 | ] 54 | }, 55 | { 56 | int: DatumParameterKey.ScooperFee 57 | }, 58 | { 59 | constructor: 0, 60 | fields: [ 61 | { 62 | constructor: DatumParameterKey.Action, // 0 -> Token A, 1 -> Token B 63 | fields: [] 64 | }, 65 | { 66 | int: DatumParameterKey.DepositA 67 | }, 68 | { 69 | constructor: 0, 70 | fields: [ 71 | { 72 | int: DatumParameterKey.DepositB 73 | } 74 | ] 75 | } 76 | ] 77 | } 78 | ] 79 | } 80 | -------------------------------------------------------------------------------- /src/dex/definitions/teddyswap/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Deposit.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 15 | }, 16 | { 17 | bytes: DatumParameterKey.TokenAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetAPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetAAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.PoolAssetBPolicyId 37 | }, 38 | { 39 | bytes: DatumParameterKey.PoolAssetBAssetName 40 | } 41 | ] 42 | }, 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | bytes: DatumParameterKey.LpTokenPolicyId 48 | }, 49 | { 50 | bytes: DatumParameterKey.LpTokenAssetName 51 | } 52 | ] 53 | }, 54 | { 55 | int: DatumParameterKey.ExecutionFee 56 | }, 57 | { 58 | bytes: DatumParameterKey.SenderPubKeyHash 59 | }, 60 | (field: DefinitionField, foundParameters: DatumParameters) => { 61 | if ('fields' in field) { 62 | if (field.constructor === 1) { 63 | return; 64 | } 65 | 66 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 67 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 68 | } 69 | } 70 | }, 71 | { 72 | int: DatumParameterKey.Deposit 73 | } 74 | ] 75 | } 76 | -------------------------------------------------------------------------------- /src/dex/definitions/teddyswap/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Redeem.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 15 | }, 16 | { 17 | bytes: DatumParameterKey.TokenAssetName 18 | } 19 | ] 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.PoolAssetAPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.PoolAssetAAssetName 29 | } 30 | ] 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.PoolAssetBPolicyId 37 | }, 38 | { 39 | bytes: DatumParameterKey.PoolAssetBAssetName 40 | } 41 | ] 42 | }, 43 | { 44 | constructor: 0, 45 | fields: [ 46 | { 47 | bytes: DatumParameterKey.LpTokenPolicyId 48 | }, 49 | { 50 | bytes: DatumParameterKey.LpTokenAssetName 51 | } 52 | ] 53 | }, 54 | { 55 | int: DatumParameterKey.ExecutionFee 56 | }, 57 | { 58 | bytes: DatumParameterKey.SenderPubKeyHash 59 | }, 60 | (field: DefinitionField, foundParameters: DatumParameters) => { 61 | if ('fields' in field) { 62 | if (field.constructor === 1) { 63 | return; 64 | } 65 | 66 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 67 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 68 | } 69 | } 70 | }, 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /src/dex/definitions/teddyswap/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | /** 4 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Pool.hs#L48 5 | */ 6 | export default { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | constructor: 0, 11 | fields: [ 12 | { 13 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 14 | }, 15 | { 16 | bytes: DatumParameterKey.TokenAssetName 17 | } 18 | ] 19 | }, 20 | { 21 | constructor: 0, 22 | fields: [ 23 | { 24 | bytes: DatumParameterKey.PoolAssetAPolicyId 25 | }, 26 | { 27 | bytes: DatumParameterKey.PoolAssetAAssetName 28 | } 29 | ] 30 | }, 31 | { 32 | constructor: 0, 33 | fields: [ 34 | { 35 | bytes: DatumParameterKey.PoolAssetBPolicyId 36 | }, 37 | { 38 | bytes: DatumParameterKey.PoolAssetBAssetName 39 | } 40 | ] 41 | }, 42 | { 43 | constructor: 0, 44 | fields: [ 45 | { 46 | bytes: DatumParameterKey.LpTokenPolicyId 47 | }, 48 | { 49 | bytes: DatumParameterKey.LpTokenAssetName 50 | } 51 | ] 52 | }, 53 | { 54 | int: DatumParameterKey.LpFee 55 | }, 56 | [ 57 | { 58 | bytes: DatumParameterKey.StakeAdminPolicy 59 | } 60 | ], 61 | { 62 | int: DatumParameterKey.LqBound 63 | } 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /src/dex/definitions/teddyswap/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/spectrum-finance/cardano-dex-contracts/blob/master/cardano-dex-contracts-offchain/ErgoDex/Contracts/Proxy/Swap.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | bytes: DatumParameterKey.SwapInTokenPolicyId 15 | }, 16 | { 17 | bytes: DatumParameterKey.SwapInTokenAssetName 18 | } 19 | ], 20 | }, 21 | { 22 | constructor: 0, 23 | fields: [ 24 | { 25 | bytes: DatumParameterKey.SwapOutTokenPolicyId 26 | }, 27 | { 28 | bytes: DatumParameterKey.SwapOutTokenAssetName 29 | } 30 | ], 31 | }, 32 | { 33 | constructor: 0, 34 | fields: [ 35 | { 36 | bytes: DatumParameterKey.TokenPolicyId // Pool NFT 37 | }, 38 | { 39 | bytes: DatumParameterKey.TokenAssetName 40 | } 41 | ], 42 | }, 43 | { 44 | int: DatumParameterKey.LpFee 45 | }, 46 | { 47 | int: DatumParameterKey.LpFeeNumerator // Execution fee numerator 48 | }, 49 | { 50 | int: DatumParameterKey.LpFeeDenominator // Execution fee denominator 51 | }, 52 | { 53 | bytes: DatumParameterKey.SenderPubKeyHash 54 | }, 55 | (field: DefinitionField, foundParameters: DatumParameters) => { 56 | if ('fields' in field) { 57 | if (field.constructor === 1) { 58 | return; 59 | } 60 | 61 | if (field.fields.length > 0 && 'bytes' in field.fields[0]) { 62 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.fields[0].bytes; 63 | } 64 | } 65 | }, 66 | { 67 | int: DatumParameterKey.SwapInAmount 68 | }, 69 | { 70 | int: DatumParameterKey.MinReceive 71 | } 72 | ], 73 | } 74 | -------------------------------------------------------------------------------- /src/dex/definitions/vyfinance/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | bytes: DatumParameterKey.SenderKeyHashes 8 | }, 9 | { 10 | constructor: 0, 11 | fields: [ 12 | { 13 | int: DatumParameterKey.MinReceive 14 | } 15 | ] 16 | } 17 | ] 18 | }; -------------------------------------------------------------------------------- /src/dex/definitions/vyfinance/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | bytes: DatumParameterKey.SenderKeyHashes 8 | }, 9 | { 10 | constructor: 1, 11 | fields: [ 12 | { 13 | constructor: 0, 14 | fields: [ 15 | { 16 | int: DatumParameterKey.MinReceiveA 17 | }, 18 | { 19 | int: DatumParameterKey.MinReceiveB 20 | } 21 | ] 22 | } 23 | ] 24 | } 25 | ] 26 | }; -------------------------------------------------------------------------------- /src/dex/definitions/vyfinance/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | int: DatumParameterKey.PoolAssetABarFee 8 | }, 9 | { 10 | int: DatumParameterKey.PoolAssetBBarFee 11 | }, 12 | { 13 | int: DatumParameterKey.TotalLpTokens 14 | } 15 | ] 16 | }; -------------------------------------------------------------------------------- /src/dex/definitions/vyfinance/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | export default { 4 | constructor: 0, 5 | fields: [ 6 | { 7 | bytes: DatumParameterKey.SenderKeyHashes 8 | }, 9 | { 10 | constructor: DatumParameterKey.Action, 11 | fields: [ 12 | { 13 | int: DatumParameterKey.MinReceive 14 | } 15 | ] 16 | } 17 | ] 18 | }; -------------------------------------------------------------------------------- /src/dex/definitions/wingriders-v2/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/WingRiders/dex-v2-contracts/blob/master/src/DEX/Pool/ConstantProduct.hs 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | bytes: DatumParameterKey.RequestScriptHash 12 | }, 13 | { 14 | bytes: DatumParameterKey.PoolAssetAPolicyId, 15 | }, 16 | { 17 | bytes: DatumParameterKey.PoolAssetAAssetName, 18 | }, 19 | { 20 | bytes: DatumParameterKey.PoolAssetBPolicyId, 21 | }, 22 | { 23 | bytes: DatumParameterKey.PoolAssetBAssetName, 24 | }, 25 | { 26 | int: DatumParameterKey.SwapFee 27 | }, 28 | { 29 | int: DatumParameterKey.ProtocolFee 30 | }, 31 | { 32 | int: DatumParameterKey.ProjectFeeInBasis 33 | }, 34 | { 35 | int: DatumParameterKey.ReserveFeeInBasis 36 | }, 37 | { 38 | int: DatumParameterKey.FeeBasis 39 | }, 40 | { 41 | int: DatumParameterKey.AgentFee 42 | }, 43 | { 44 | int: DatumParameterKey.LastInteraction 45 | }, 46 | { 47 | int: DatumParameterKey.PoolAssetATreasury 48 | }, 49 | { 50 | int: DatumParameterKey.PoolAssetBTreasury 51 | }, 52 | { 53 | int: DatumParameterKey.Unknown 54 | }, 55 | { 56 | int: DatumParameterKey.Unknown 57 | }, 58 | { 59 | int: DatumParameterKey.Unknown 60 | }, 61 | { 62 | int: DatumParameterKey.Unknown 63 | }, 64 | (field: DefinitionField, parameters: DatumParameters) => { 65 | return parameters; 66 | }, 67 | (field: DefinitionField, parameters: DatumParameters) => { 68 | return parameters; 69 | }, 70 | (field: DefinitionField, parameters: DatumParameters) => { 71 | return parameters; 72 | }, 73 | ] 74 | }; 75 | -------------------------------------------------------------------------------- /src/dex/definitions/wingriders/pool-deposit.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.SenderPubKeyHash 18 | } 19 | ] 20 | }, 21 | (field: DefinitionField, foundParameters: DatumParameters) => { 22 | if ('fields' in field) { 23 | if (field.constructor === 1) { 24 | return; 25 | } 26 | 27 | const constr: DefinitionField = field.fields[0]; 28 | 29 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 30 | const field: DefinitionField = constr.fields[0].fields[0]; 31 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 32 | 33 | return; 34 | } 35 | } 36 | 37 | throw new Error("Template definition does not match with 'bytes'"); 38 | } 39 | ] 40 | }, 41 | { 42 | bytes: DatumParameterKey.ReceiverPubKeyHash 43 | }, 44 | { 45 | int: DatumParameterKey.Expiration 46 | }, 47 | { 48 | constructor: 0, 49 | fields: [ 50 | { 51 | constructor: 0, 52 | fields: [ 53 | { 54 | bytes: DatumParameterKey.PoolAssetAPolicyId 55 | }, 56 | { 57 | bytes: DatumParameterKey.PoolAssetAAssetName 58 | } 59 | ] 60 | }, 61 | { 62 | constructor: 0, 63 | fields: [ 64 | { 65 | bytes: DatumParameterKey.PoolAssetBPolicyId 66 | }, 67 | { 68 | bytes: DatumParameterKey.PoolAssetBAssetName 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ] 75 | }, 76 | { 77 | constructor: 1, 78 | fields: [ 79 | { 80 | int: DatumParameterKey.MinReceive 81 | } 82 | ] 83 | } 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /src/dex/definitions/wingriders/pool-withdraw.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | export default { 5 | constructor: 0, 6 | fields: [ 7 | { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | bytes: DatumParameterKey.SenderPubKeyHash 18 | } 19 | ] 20 | }, 21 | (field: DefinitionField, foundParameters: DatumParameters) => { 22 | if ('fields' in field) { 23 | if (field.constructor === 1) { 24 | return; 25 | } 26 | 27 | const constr: DefinitionField = field.fields[0]; 28 | 29 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 30 | const field: DefinitionField = constr.fields[0].fields[0]; 31 | foundParameters[DatumParameterKey.SenderStakingKeyHash] = field.bytes; 32 | 33 | return; 34 | } 35 | } 36 | 37 | throw new Error("Template definition does not match with 'bytes'"); 38 | } 39 | ] 40 | }, 41 | { 42 | bytes: DatumParameterKey.ReceiverPubKeyHash 43 | }, 44 | { 45 | int: DatumParameterKey.Expiration 46 | }, 47 | { 48 | constructor: 0, 49 | fields: [ 50 | { 51 | constructor: 0, 52 | fields: [ 53 | { 54 | bytes: DatumParameterKey.PoolAssetAPolicyId 55 | }, 56 | { 57 | bytes: DatumParameterKey.PoolAssetAAssetName 58 | } 59 | ] 60 | }, 61 | { 62 | constructor: 0, 63 | fields: [ 64 | { 65 | bytes: DatumParameterKey.PoolAssetBPolicyId 66 | }, 67 | { 68 | bytes: DatumParameterKey.PoolAssetBAssetName 69 | } 70 | ] 71 | } 72 | ] 73 | } 74 | ] 75 | }, 76 | { 77 | constructor: 2, 78 | fields: [ 79 | { 80 | int: DatumParameterKey.MinReceiveA 81 | }, 82 | { 83 | int: DatumParameterKey.MinReceiveB 84 | } 85 | ] 86 | } 87 | ] 88 | } 89 | -------------------------------------------------------------------------------- /src/dex/definitions/wingriders/pool.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | 3 | /** 4 | * https://github.com/WingRiders/dex-serializer/blob/main/src/LiquidityPoolDatum.ts 5 | */ 6 | export default { 7 | constructor: 0, 8 | fields: [ 9 | { 10 | bytes: DatumParameterKey.RequestScriptHash 11 | }, 12 | { 13 | constructor: 0, 14 | fields: [ 15 | { 16 | constructor: 0, 17 | fields: [ 18 | { 19 | constructor: 0, 20 | fields: [ 21 | { 22 | bytes: DatumParameterKey.PoolAssetAPolicyId, 23 | }, 24 | { 25 | bytes: DatumParameterKey.PoolAssetAAssetName, 26 | } 27 | ] 28 | }, 29 | { 30 | constructor: 0, 31 | fields: [ 32 | { 33 | bytes: DatumParameterKey.PoolAssetBPolicyId, 34 | }, 35 | { 36 | bytes: DatumParameterKey.PoolAssetBAssetName, 37 | } 38 | ] 39 | } 40 | ] 41 | }, 42 | { 43 | int: DatumParameterKey.LastInteraction, 44 | }, 45 | { 46 | int: DatumParameterKey.PoolAssetATreasury, 47 | }, 48 | { 49 | int: DatumParameterKey.PoolAssetBTreasury, 50 | } 51 | ] 52 | } 53 | ] 54 | }; 55 | -------------------------------------------------------------------------------- /src/dex/definitions/wingriders/swap.ts: -------------------------------------------------------------------------------- 1 | import { DatumParameterKey } from '../../../constants'; 2 | import { DatumParameters, DefinitionField } from '../../../types'; 3 | 4 | /** 5 | * https://github.com/WingRiders/dex-serializer/blob/main/src/RequestDatum.ts 6 | */ 7 | export default { 8 | constructor: 0, 9 | fields: [ 10 | { 11 | constructor: 0, 12 | fields: [ 13 | { 14 | constructor: 0, 15 | fields: [ 16 | { 17 | constructor: 0, 18 | fields: [ 19 | { 20 | bytes: DatumParameterKey.ReceiverPubKeyHash 21 | } 22 | ] 23 | }, 24 | (field: DefinitionField, foundParameters: DatumParameters) => { 25 | if ('fields' in field) { 26 | if (field.constructor === 1) { 27 | return; 28 | } 29 | 30 | const constr: DefinitionField = field.fields[0]; 31 | 32 | if ('fields' in constr && 'fields' in constr.fields[0] && 'bytes' in constr.fields[0].fields[0]) { 33 | const field: DefinitionField = constr.fields[0].fields[0]; 34 | foundParameters[DatumParameterKey.ReceiverStakingKeyHash] = field.bytes; 35 | 36 | return; 37 | } 38 | } 39 | 40 | throw new Error("Template definition does not match with 'bytes'"); 41 | } 42 | ] 43 | }, 44 | { 45 | bytes: DatumParameterKey.SenderPubKeyHash 46 | }, 47 | { 48 | int: DatumParameterKey.Expiration 49 | }, 50 | { 51 | constructor: 0, 52 | fields: [ 53 | { 54 | constructor: 0, 55 | fields: [ 56 | { 57 | bytes: DatumParameterKey.PoolAssetAPolicyId 58 | }, 59 | { 60 | bytes: DatumParameterKey.PoolAssetAAssetName 61 | } 62 | ] 63 | }, 64 | { 65 | constructor: 0, 66 | fields: [ 67 | { 68 | bytes: DatumParameterKey.PoolAssetBPolicyId 69 | }, 70 | { 71 | bytes: DatumParameterKey.PoolAssetBAssetName 72 | } 73 | ] 74 | } 75 | ] 76 | } 77 | ] 78 | }, 79 | { 80 | constructor: 0, 81 | fields: [ 82 | { 83 | constructor: DatumParameterKey.Action, 84 | fields: [] 85 | }, 86 | { 87 | int: DatumParameterKey.MinReceive 88 | } 89 | ] 90 | } 91 | ] 92 | }; 93 | -------------------------------------------------------------------------------- /src/indexer.ts: -------------------------------------------------------------------------------- 1 | import { IndexerApplication } from './IndexerApplication'; 2 | import { logError, logInfo } from './logger'; 3 | import { CacheStorage } from './storage/CacheStorage'; 4 | 5 | const indexerApp: IndexerApplication = new IndexerApplication( 6 | new CacheStorage() 7 | ); 8 | 9 | await indexerApp.start() 10 | .then(() => { 11 | logInfo('IndexerApplication started'); 12 | }) 13 | .catch((reason) => { 14 | logError(`IndexerApplication failed to start : ${reason}`); 15 | }); 16 | -------------------------------------------------------------------------------- /src/indexerServices.ts: -------------------------------------------------------------------------------- 1 | import { WebsocketService } from './services/WebsocketService'; 2 | import { EventService } from './services/EventService'; 3 | import { DatabaseService } from './services/DatabaseService'; 4 | import CONFIG from './config'; 5 | import { ApplicationContext } from './constants'; 6 | import { TokenMetadataService } from './services/TokenMetadataService'; 7 | import { QueueService } from './services/QueueService'; 8 | 9 | const operationWs: WebsocketService = new WebsocketService(CONFIG.OPERATION_WEBSOCKET_PORT); 10 | const eventService: EventService = new EventService(); 11 | const dbService: DatabaseService = new DatabaseService(ApplicationContext.Indexer); 12 | const metadataService: TokenMetadataService = new TokenMetadataService(); 13 | const queue: QueueService = new QueueService(); 14 | 15 | export { 16 | operationWs, 17 | eventService, 18 | dbService, 19 | metadataService, 20 | queue, 21 | } 22 | -------------------------------------------------------------------------------- /src/indexers/BaseIndexer.ts: -------------------------------------------------------------------------------- 1 | import { BlockPraos, Slot } from '@cardano-ogmios/schema'; 2 | 3 | export abstract class BaseIndexer { 4 | 5 | abstract onRollForward(block: BlockPraos): Promise; 6 | 7 | abstract onRollBackward(blockHash: string, slot: Slot): Promise; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/indexers/SyncIndexer.ts: -------------------------------------------------------------------------------- 1 | import { BaseIndexer } from './BaseIndexer'; 2 | import { BlockPraos, Slot } from '@cardano-ogmios/schema'; 3 | import { dbService, eventService, operationWs } from '../indexerServices'; 4 | import { EntityManager } from 'typeorm'; 5 | import { Sync } from '../db/entities/Sync'; 6 | 7 | export class SyncIndexer extends BaseIndexer { 8 | 9 | async onRollForward(block: BlockPraos): Promise { 10 | await dbService.transaction(async (manager: EntityManager): Promise => { 11 | const updatedSync: Sync = Sync.make(block.id, block.slot); 12 | 13 | await manager.upsert( 14 | Sync, 15 | updatedSync, 16 | ['id'] 17 | ); 18 | 19 | eventService.pushEvent({ 20 | type: 'SyncUpdated', 21 | data: updatedSync, 22 | }); 23 | }); 24 | 25 | operationWs.broadcast(Sync.make(block.id, block.slot)); 26 | 27 | return Promise.resolve(); 28 | } 29 | 30 | async onRollBackward(blockHash: string, slot: Slot): Promise { 31 | return await dbService.transaction(async (manager: EntityManager): Promise => { 32 | await manager.upsert( 33 | Sync, 34 | Sync.make(blockHash, slot), 35 | ['id'] 36 | ); 37 | }); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/jobs/BaseJob.ts: -------------------------------------------------------------------------------- 1 | export abstract class BaseJob { 2 | 3 | public uuid: number; 4 | 5 | protected constructor() { 6 | this.uuid = Math.random(); 7 | } 8 | 9 | abstract handle(): Promise; 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/listeners/BaseEventListener.ts: -------------------------------------------------------------------------------- 1 | import { IndexerApplication } from '../IndexerApplication'; 2 | import { IrisEvent } from '../events.types'; 3 | import { IrisEventType } from '../constants'; 4 | 5 | export abstract class BaseEventListener { 6 | 7 | public app: IndexerApplication | undefined; 8 | 9 | public abstract listenFor: IrisEventType[]; 10 | 11 | constructor(app: IndexerApplication | undefined = undefined) { 12 | this.app = app; 13 | } 14 | 15 | abstract onEvent(event: IrisEvent): Promise; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/listeners/PoolStateListener.ts: -------------------------------------------------------------------------------- 1 | import { BaseEventListener } from './BaseEventListener'; 2 | import { IrisEventType } from '../constants'; 3 | import { IrisEvent } from '../events.types'; 4 | 5 | export class PoolStateListener extends BaseEventListener { 6 | 7 | public listenFor: IrisEventType[] = [ 8 | IrisEventType.LiquidityPoolCreated, 9 | ]; 10 | 11 | public onEvent(event: IrisEvent): Promise { 12 | if (! this.app) return Promise.resolve(); 13 | 14 | switch (event.type) { 15 | case IrisEventType.LiquidityPoolCreated: 16 | const storageKey: string = event.data.identifier; 17 | 18 | return this.app.cache.setKey(storageKey, event.data); 19 | default: 20 | return Promise.resolve(); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/logger.ts: -------------------------------------------------------------------------------- 1 | import { createLogger, format, Logger, transports } from 'winston'; 2 | import DailyRotateFile from 'winston-daily-rotate-file'; 3 | import * as fs from 'fs'; 4 | import CONFIG from './config'; 5 | import { ApplicationContext } from './constants'; 6 | 7 | if (! fs.existsSync(CONFIG.LOG_DIR)) { 8 | fs.mkdirSync(CONFIG.LOG_DIR); 9 | } 10 | 11 | const defaultLogger: Logger = createLogger(loggerConfig(ApplicationContext.Indexer)); 12 | const apiLogger: Logger = createLogger(loggerConfig(ApplicationContext.Api)); 13 | 14 | function loggerConfig(context: ApplicationContext) { 15 | return { 16 | transports: [ 17 | new transports.Console(), 18 | new DailyRotateFile({ 19 | level: 'info', 20 | dirname: `${CONFIG.LOG_DIR}/${context}`, 21 | filename: `info-%DATE%.${context}.log`, 22 | datePattern: 'MM-DD-YYYY', 23 | maxFiles: '14d' 24 | }), 25 | new DailyRotateFile({ 26 | level: 'error', 27 | dirname: `${CONFIG.LOG_DIR}/${context}`, 28 | filename: `error-%DATE%.${context}.log`, 29 | datePattern: 'MM-DD-YYYY', 30 | maxFiles: '14d' 31 | }), 32 | ], 33 | format: format.combine( 34 | format.colorize(), 35 | format.timestamp({ format: 'MM-DD HH:mm:ss' }), 36 | format.printf(({ timestamp, level, message }) => { 37 | return `[${timestamp}] ${level}: ${message}` 38 | }), 39 | ), 40 | }; 41 | } 42 | 43 | function logInfo(message: string, context: ApplicationContext = ApplicationContext.Indexer): Logger { 44 | switch (context) { 45 | case ApplicationContext.Indexer: 46 | return defaultLogger.info(message); 47 | case ApplicationContext.Api: 48 | return apiLogger.info(message); 49 | } 50 | 51 | return defaultLogger.info(message); 52 | } 53 | 54 | function logError(message: string, context: ApplicationContext = ApplicationContext.Indexer): Logger { 55 | switch (context) { 56 | case ApplicationContext.Indexer: 57 | return defaultLogger.error(message); 58 | case ApplicationContext.Api: 59 | return apiLogger.error(message); 60 | } 61 | 62 | return defaultLogger.error(message); 63 | } 64 | 65 | export { 66 | logInfo, 67 | logError, 68 | } 69 | -------------------------------------------------------------------------------- /src/services/BaseService.ts: -------------------------------------------------------------------------------- 1 | import { IndexerApplication } from '../IndexerApplication'; 2 | import { ApiApplication } from '../ApiApplication'; 3 | 4 | export abstract class BaseService { 5 | 6 | abstract boot(app: IndexerApplication | ApiApplication): Promise; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/services/EventService.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from './BaseService'; 2 | import { BaseEventListener } from '../listeners/BaseEventListener'; 3 | import { PoolStateListener } from '../listeners/PoolStateListener'; 4 | import { IndexerApplication } from '../IndexerApplication'; 5 | import { IrisEvent } from '../events.types'; 6 | 7 | export class EventService extends BaseService { 8 | 9 | private _listeners: BaseEventListener[] = []; 10 | 11 | public boot(app: IndexerApplication, listeners: BaseEventListener[] = []): Promise { 12 | this._listeners = [ 13 | ...listeners, 14 | new PoolStateListener(app), 15 | ]; 16 | 17 | return Promise.resolve(); 18 | } 19 | 20 | public pushEvent(event: IrisEvent): Promise { 21 | return Promise.all( 22 | this._listeners.map((listener: BaseEventListener) => { 23 | if (listener.listenFor.includes(event.type as any)) { 24 | return listener.onEvent(event) 25 | } 26 | return; 27 | }) 28 | ); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/services/QueueService.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from './BaseService'; 2 | import { BaseJob } from '../jobs/BaseJob'; 3 | import Queue from 'queue-promise'; 4 | 5 | export class QueueService extends BaseService { 6 | 7 | private queue: Queue; 8 | 9 | constructor() { 10 | super(); 11 | 12 | this.queue = new Queue({ 13 | concurrent: 50, 14 | interval: 0, 15 | start: false, 16 | }); 17 | } 18 | 19 | get size(): number { 20 | return this.queue.size; 21 | } 22 | 23 | boot(): Promise { 24 | return Promise.resolve(); 25 | } 26 | 27 | dispatch(job: BaseJob): void { 28 | this.queue.enqueue(() => job.handle()); 29 | } 30 | 31 | async settle(): Promise { 32 | while (this.queue.shouldRun) { 33 | await this.queue.dequeue(); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/services/TokenMetadataService.ts: -------------------------------------------------------------------------------- 1 | import { BaseService } from './BaseService'; 2 | import { TokenMetadata } from '../types'; 3 | import axios from 'axios'; 4 | import CONFIG from '../config'; 5 | 6 | export class TokenMetadataService extends BaseService { 7 | 8 | boot(): Promise { 9 | if (! CONFIG.GITHUB_ACCESS_TOKEN) return Promise.reject('Github access token not set in env.') 10 | 11 | return Promise.resolve(); 12 | } 13 | 14 | fetchAsset(policyId: string, nameHex: string): Promise { 15 | return axios.get(`https://raw.githubusercontent.com/cardano-foundation/cardano-token-registry/master/mappings/${policyId}${nameHex}.json`, { 16 | headers: { 17 | Authorization: `Bearer ${CONFIG.GITHUB_ACCESS_TOKEN}`, 18 | Host: '', // Fails without this set 19 | } 20 | }).then((response: any) => { 21 | return { 22 | policyId: policyId, 23 | nameHex: nameHex, 24 | name: response.data.name?.value ?? '', 25 | decimals: response.data.decimals?.value ?? 0, 26 | ticker: response.data.ticker?.value ?? '', 27 | logo: response.data.logo?.value ?? '', 28 | description: response.data.description?.value ?? '', 29 | } 30 | }); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/storage/BaseCacheStorage.ts: -------------------------------------------------------------------------------- 1 | export abstract class BaseCacheStorage { 2 | 3 | abstract boot(): Promise; 4 | 5 | abstract setKey(key: string, data: any, ttlSecs?: number): Promise; 6 | 7 | abstract getKey(key: string, defaultTo?: any): Promise; 8 | 9 | abstract deleteKey(key: string): Promise; 10 | 11 | abstract flushAll(): Promise; 12 | 13 | abstract keys(): Promise; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/storage/CacheStorage.ts: -------------------------------------------------------------------------------- 1 | import { BaseCacheStorage } from './BaseCacheStorage'; 2 | import NodeCache from 'node-cache'; 3 | 4 | export class CacheStorage extends BaseCacheStorage { 5 | 6 | /** 7 | * https://github.com/node-cache/node-cache 8 | */ 9 | private _cache: NodeCache | undefined; 10 | 11 | public boot(): Promise { 12 | this._cache = new NodeCache({ 13 | checkperiod: 60, 14 | useClones: false, 15 | stdTTL: 0, 16 | }); 17 | 18 | return Promise.resolve(); 19 | } 20 | 21 | public setKey(key: string, data: any, ttlSecs: number = 604_800): Promise { 22 | if (!this._cache) { 23 | throw new Error('CacheStorage not initialized.'); 24 | } 25 | 26 | this._cache.set(key, data, ttlSecs); 27 | 28 | return Promise.resolve(); 29 | } 30 | 31 | public getKey(key: string, defaultTo: any = undefined): Promise { 32 | if (!this._cache) { 33 | throw new Error('CacheStorage not initialized.'); 34 | } 35 | 36 | return Promise.resolve( 37 | this._cache.get(key) ?? defaultTo 38 | ); 39 | } 40 | 41 | public deleteKey(key: string): Promise { 42 | if (!this._cache) { 43 | throw new Error('CacheStorage not initialized.'); 44 | } 45 | 46 | this._cache.del(key); 47 | 48 | return Promise.resolve(); 49 | } 50 | 51 | public flushAll(): Promise { 52 | if (!this._cache) { 53 | throw new Error('CacheStorage not initialized.'); 54 | } 55 | 56 | this._cache.flushAll(); 57 | 58 | return Promise.resolve(); 59 | } 60 | 61 | public keys(): Promise { 62 | if (!this._cache) { 63 | throw new Error('CacheStorage not initialized.'); 64 | } 65 | 66 | return Promise.resolve( 67 | this._cache.keys() 68 | ); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /tests/minswap.test.ts: -------------------------------------------------------------------------------- 1 | import { globals } from './setup'; 2 | import { BaseAmmDexAnalyzer } from '../src/dex/BaseAmmDexAnalyzer'; 3 | import { AmmDexOperation } from '../src/types'; 4 | import { LiquidityPoolSwap } from '../src/db/entities/LiquidityPoolSwap'; 5 | import { LiquidityPoolDeposit } from '../src/db/entities/LiquidityPoolDeposit'; 6 | import { LiquidityPoolWithdraw } from '../src/db/entities/LiquidityPoolWithdraw'; 7 | import { LiquidityPoolState } from '../src/db/entities/LiquidityPoolState'; 8 | import { MinswapAnalyzer } from '../src/dex/MinswapAnalyzer'; 9 | 10 | describe('Minswap', () => { 11 | 12 | const analyzer: BaseAmmDexAnalyzer = new MinswapAnalyzer(globals.app); 13 | 14 | it('Can index swaps', async () => { 15 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.MINSWAP_SWAP_TX); 16 | 17 | expect(operations.length).toEqual(1); 18 | expect(operations[0]).toBeInstanceOf(LiquidityPoolSwap); 19 | expect(operations[0].txHash).toEqual(globals.MINSWAP_SWAP_TX.hash); 20 | }); 21 | 22 | it('Can index deposits', async () => { 23 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.MINSWAP_DEPOSIT_TX); 24 | 25 | expect(operations.length).toEqual(1); 26 | expect(operations[0]).toBeInstanceOf(LiquidityPoolDeposit); 27 | expect(operations[0].txHash).toEqual(globals.MINSWAP_DEPOSIT_TX.hash); 28 | }); 29 | 30 | it('Can index withdraws', async () => { 31 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.MINSWAP_WITHDRAW_TX); 32 | 33 | expect(operations.length).toEqual(1); 34 | expect(operations[0]).toBeInstanceOf(LiquidityPoolWithdraw); 35 | expect(operations[0].txHash).toEqual(globals.MINSWAP_WITHDRAW_TX.hash); 36 | }); 37 | 38 | it('Can index LP states', async () => { 39 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.MINSWAP_LP_STATE_TX); 40 | 41 | expect(operations.length).toEqual(1); 42 | expect(operations[0]).toBeInstanceOf(LiquidityPoolState); 43 | expect(operations[0].txHash).toEqual(globals.MINSWAP_LP_STATE_TX.hash); 44 | }); 45 | 46 | it('Can filter non-related transactions', async () => { 47 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SUNDAESWAP_SWAP_TX); 48 | 49 | expect(operations.length).toEqual(0); 50 | }); 51 | 52 | }); -------------------------------------------------------------------------------- /tests/muesliswap.test.ts: -------------------------------------------------------------------------------- 1 | import { globals } from './setup'; 2 | import { MuesliSwapAnalyzer } from '../src/dex/MuesliSwapAnalyzer'; 3 | import { HybridOperation } from '../src/types'; 4 | import { LiquidityPoolSwap } from '../src/db/entities/LiquidityPoolSwap'; 5 | import { LiquidityPoolState } from '../src/db/entities/LiquidityPoolState'; 6 | import { BaseHybridDexAnalyzer } from '../src/dex/BaseHybridDexAnalyzer'; 7 | 8 | describe('MuesliSwap', () => { 9 | 10 | const analyzer: BaseHybridDexAnalyzer = new MuesliSwapAnalyzer(globals.app); 11 | 12 | it('Can index swaps', async () => { 13 | const operations: HybridOperation[] = await analyzer.analyzeTransaction(globals.MUESLISWAP_SWAP_TX); 14 | 15 | expect(operations.length).toEqual(1); 16 | expect(operations[0]).toBeInstanceOf(LiquidityPoolSwap); 17 | expect(operations[0].txHash).toEqual(globals.MUESLISWAP_SWAP_TX.hash); 18 | }); 19 | 20 | it('Can index LP states', async () => { 21 | const operations: HybridOperation[] = await analyzer.analyzeTransaction(globals.MUESLISWAP_LP_STATE_TX); 22 | 23 | expect(operations.length).toEqual(1); 24 | expect(operations[0]).toBeInstanceOf(LiquidityPoolState); 25 | expect(operations[0].txHash).toEqual(globals.MUESLISWAP_LP_STATE_TX.hash); 26 | }); 27 | 28 | it('Can filter non-related transactions', async () => { 29 | const operations: HybridOperation[] = await analyzer.analyzeTransaction(globals.MINSWAP_SWAP_TX); 30 | 31 | expect(operations.length).toEqual(0); 32 | }); 33 | 34 | }); -------------------------------------------------------------------------------- /tests/spectrum.test.ts: -------------------------------------------------------------------------------- 1 | import { globals } from './setup'; 2 | import { BaseAmmDexAnalyzer } from '../src/dex/BaseAmmDexAnalyzer'; 3 | import { AmmDexOperation } from '../src/types'; 4 | import { LiquidityPoolSwap } from '../src/db/entities/LiquidityPoolSwap'; 5 | import { LiquidityPoolDeposit } from '../src/db/entities/LiquidityPoolDeposit'; 6 | import { LiquidityPoolWithdraw } from '../src/db/entities/LiquidityPoolWithdraw'; 7 | import { LiquidityPoolState } from '../src/db/entities/LiquidityPoolState'; 8 | import { SpectrumAnalyzer } from '../src/dex/SpectrumAnalyzer'; 9 | 10 | describe('Spectrum', () => { 11 | 12 | const analyzer: BaseAmmDexAnalyzer = new SpectrumAnalyzer(globals.app); 13 | 14 | it('Can index swaps', async () => { 15 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SPECTRUM_SWAP_TX); 16 | 17 | expect(operations.length).toEqual(1); 18 | expect(operations[0]).toBeInstanceOf(LiquidityPoolSwap); 19 | expect(operations[0].txHash).toEqual(globals.SPECTRUM_SWAP_TX.hash); 20 | }); 21 | 22 | it('Can index deposits', async () => { 23 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SPECTRUM_DEPOSIT_TX); 24 | 25 | expect(operations.length).toEqual(1); 26 | expect(operations[0]).toBeInstanceOf(LiquidityPoolDeposit); 27 | expect(operations[0].txHash).toEqual(globals.SPECTRUM_DEPOSIT_TX.hash); 28 | }); 29 | 30 | it('Can index withdraws', async () => { 31 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SPECTRUM_WITHDRAW_TX); 32 | 33 | expect(operations.length).toEqual(1); 34 | expect(operations[0]).toBeInstanceOf(LiquidityPoolWithdraw); 35 | expect(operations[0].txHash).toEqual(globals.SPECTRUM_WITHDRAW_TX.hash); 36 | }); 37 | 38 | it('Can index LP states', async () => { 39 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SPECTRUM_LP_STATE_TX); 40 | 41 | expect(operations.length).toEqual(1); 42 | expect(operations[0]).toBeInstanceOf(LiquidityPoolState); 43 | expect(operations[0].txHash).toEqual(globals.SPECTRUM_LP_STATE_TX.hash); 44 | }); 45 | 46 | it('Can filter non-related transactions', async () => { 47 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SUNDAESWAP_SWAP_TX); 48 | 49 | expect(operations.length).toEqual(0); 50 | }); 51 | 52 | }); -------------------------------------------------------------------------------- /tests/sundaeswap.test.ts: -------------------------------------------------------------------------------- 1 | import { globals } from './setup'; 2 | import { BaseAmmDexAnalyzer } from '../src/dex/BaseAmmDexAnalyzer'; 3 | import { SundaeSwapAnalyzer } from '../src/dex/SundaeSwapAnalyzer'; 4 | import { LiquidityPool } from '../src/db/entities/LiquidityPool'; 5 | import { Dex } from '../src/constants'; 6 | import { Asset } from '../src/db/entities/Asset'; 7 | import { AmmDexOperation } from '../src/types'; 8 | import { LiquidityPoolSwap } from '../src/db/entities/LiquidityPoolSwap'; 9 | import { LiquidityPoolDeposit } from '../src/db/entities/LiquidityPoolDeposit'; 10 | import { LiquidityPoolWithdraw } from '../src/db/entities/LiquidityPoolWithdraw'; 11 | import { LiquidityPoolState } from '../src/db/entities/LiquidityPoolState'; 12 | 13 | describe('SundaeSwap', () => { 14 | 15 | const analyzer: BaseAmmDexAnalyzer = new SundaeSwapAnalyzer(globals.app); 16 | 17 | beforeEach(() => { 18 | globals.app.cache.setKey('00', LiquidityPool.make( 19 | Dex.SundaeSwap, 20 | '04', 21 | '', 22 | Asset.fromId('7de52b397c138e44fb6e61aaaeb26219a8059b1749b7c3bd87bd9488.524245525259'), 23 | Asset.fromId('7de52b397c138e44fb6e61aaaeb26219a8059b1749b7c3bd87bd9488.534245525259'), 24 | 1234, 25 | )); 26 | }); 27 | 28 | it('Can index swaps', async () => { 29 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SUNDAESWAP_SWAP_TX); 30 | 31 | expect(operations.length).toEqual(1); 32 | expect(operations[0]).toBeInstanceOf(LiquidityPoolSwap); 33 | expect(operations[0].txHash).toEqual(globals.SUNDAESWAP_SWAP_TX.hash); 34 | }); 35 | 36 | it('Can index deposits', async () => { 37 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SUNDAESWAP_DEPOSIT_TX); 38 | 39 | expect(operations.length).toEqual(1); 40 | expect(operations[0]).toBeInstanceOf(LiquidityPoolDeposit); 41 | expect(operations[0].txHash).toEqual(globals.SUNDAESWAP_DEPOSIT_TX.hash); 42 | }); 43 | 44 | it('Can index withdraws', async () => { 45 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SUNDAESWAP_WITHDRAW_TX); 46 | 47 | expect(operations.length).toEqual(1); 48 | expect(operations[0]).toBeInstanceOf(LiquidityPoolWithdraw); 49 | expect(operations[0].txHash).toEqual(globals.SUNDAESWAP_WITHDRAW_TX.hash); 50 | }); 51 | 52 | it('Can index LP states', async () => { 53 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SUNDAESWAP_LP_STATE_TX); 54 | 55 | expect(operations.length).toEqual(1); 56 | expect(operations[0]).toBeInstanceOf(LiquidityPoolState); 57 | expect(operations[0].txHash).toEqual(globals.SUNDAESWAP_LP_STATE_TX.hash); 58 | }); 59 | 60 | it('Can filter non-related transactions', async () => { 61 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.MINSWAP_SWAP_TX); 62 | 63 | expect(operations.length).toEqual(0); 64 | }); 65 | 66 | }); -------------------------------------------------------------------------------- /tests/teddyswap.test.ts: -------------------------------------------------------------------------------- 1 | import { globals } from './setup'; 2 | import { BaseAmmDexAnalyzer } from '../src/dex/BaseAmmDexAnalyzer'; 3 | import { AmmDexOperation } from '../src/types'; 4 | import { LiquidityPoolSwap } from '../src/db/entities/LiquidityPoolSwap'; 5 | import { LiquidityPoolDeposit } from '../src/db/entities/LiquidityPoolDeposit'; 6 | import { LiquidityPoolWithdraw } from '../src/db/entities/LiquidityPoolWithdraw'; 7 | import { LiquidityPoolState } from '../src/db/entities/LiquidityPoolState'; 8 | import { TeddySwapAnalyzer } from '../src/dex/TeddySwapAnalyzer'; 9 | 10 | describe('TeddySwap', () => { 11 | 12 | const analyzer: BaseAmmDexAnalyzer = new TeddySwapAnalyzer(globals.app); 13 | 14 | it('Can index swaps', async () => { 15 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.TEDDYSWAP_SWAP_TX); 16 | 17 | expect(operations.length).toEqual(1); 18 | expect(operations[0]).toBeInstanceOf(LiquidityPoolSwap); 19 | expect(operations[0].txHash).toEqual(globals.TEDDYSWAP_SWAP_TX.hash); 20 | }); 21 | 22 | it('Can index deposits', async () => { 23 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.TEDDYSWAP_DEPOSIT_TX); 24 | 25 | expect(operations.length).toEqual(1); 26 | expect(operations[0]).toBeInstanceOf(LiquidityPoolDeposit); 27 | expect(operations[0].txHash).toEqual(globals.TEDDYSWAP_DEPOSIT_TX.hash); 28 | }); 29 | 30 | it('Can index withdraws', async () => { 31 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.TEDDYSWAP_WITHDRAW_TX); 32 | 33 | expect(operations.length).toEqual(1); 34 | expect(operations[0]).toBeInstanceOf(LiquidityPoolWithdraw); 35 | expect(operations[0].txHash).toEqual(globals.TEDDYSWAP_WITHDRAW_TX.hash); 36 | }); 37 | 38 | it('Can index LP states', async () => { 39 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.TEDDYSWAP_LP_STATE_TX); 40 | 41 | expect(operations.length).toEqual(1); 42 | expect(operations[0]).toBeInstanceOf(LiquidityPoolState); 43 | expect(operations[0].txHash).toEqual(globals.TEDDYSWAP_LP_STATE_TX.hash); 44 | }); 45 | 46 | it('Can filter non-related transactions', async () => { 47 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.SUNDAESWAP_SWAP_TX); 48 | 49 | expect(operations.length).toEqual(0); 50 | }); 51 | 52 | }); -------------------------------------------------------------------------------- /tests/wingriders.test.ts: -------------------------------------------------------------------------------- 1 | import { globals } from './setup'; 2 | import { BaseAmmDexAnalyzer } from '../src/dex/BaseAmmDexAnalyzer'; 3 | import { WingRidersAnalyzer } from '../src/dex/WingRidersAnalyzer'; 4 | import { AmmDexOperation } from '../src/types'; 5 | import { LiquidityPoolSwap } from '../src/db/entities/LiquidityPoolSwap'; 6 | import { LiquidityPoolDeposit } from '../src/db/entities/LiquidityPoolDeposit'; 7 | import { LiquidityPoolWithdraw } from '../src/db/entities/LiquidityPoolWithdraw'; 8 | import { LiquidityPoolState } from '../src/db/entities/LiquidityPoolState'; 9 | 10 | describe('Wingriders', () => { 11 | 12 | const analyzer: BaseAmmDexAnalyzer = new WingRidersAnalyzer(globals.app); 13 | 14 | it('Can index swaps', async () => { 15 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.WINGRIDERS_SWAP_TX); 16 | 17 | expect(operations.length).toEqual(1); 18 | expect(operations[0]).toBeInstanceOf(LiquidityPoolSwap); 19 | expect(operations[0].txHash).toEqual(globals.WINGRIDERS_SWAP_TX.hash); 20 | }); 21 | 22 | it('Can index deposits', async () => { 23 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.WINGRIDERS_DEPOSIT_TX); 24 | 25 | expect(operations.length).toEqual(1); 26 | expect(operations[0]).toBeInstanceOf(LiquidityPoolDeposit); 27 | expect(operations[0].txHash).toEqual(globals.WINGRIDERS_DEPOSIT_TX.hash); 28 | }); 29 | 30 | it('Can index withdraws', async () => { 31 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.WINGRIDERS_WITHDRAW_TX); 32 | 33 | expect(operations.length).toEqual(1); 34 | expect(operations[0]).toBeInstanceOf(LiquidityPoolWithdraw); 35 | expect(operations[0].txHash).toEqual(globals.WINGRIDERS_WITHDRAW_TX.hash); 36 | }); 37 | 38 | it('Can index LP states', async () => { 39 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.WINGRIDERS_LP_STATE_TX); 40 | 41 | expect(operations.length).toEqual(1); 42 | expect(operations[0]).toBeInstanceOf(LiquidityPoolState); 43 | expect(operations[0].txHash).toEqual(globals.WINGRIDERS_LP_STATE_TX.hash); 44 | }); 45 | 46 | it('Can filter non-related transactions', async () => { 47 | const operations: AmmDexOperation[] = await analyzer.analyzeTransaction(globals.MINSWAP_SWAP_TX); 48 | 49 | expect(operations.length).toEqual(0); 50 | }); 51 | 52 | }); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "es2022", 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "declaration": true, 8 | "outDir": "dist", 9 | "strict": true, 10 | "noImplicitAny": true, 11 | "strictNullChecks": true, 12 | "strictFunctionTypes": true, 13 | "strictBindCallApply": true, 14 | "strictPropertyInitialization": false, 15 | "noImplicitThis": true, 16 | "alwaysStrict": false, 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "noImplicitReturns": true, 20 | "noFallthroughCasesInSwitch": false, 21 | "esModuleInterop": true, 22 | "skipLibCheck": true, 23 | "forceConsistentCasingInFileNames": true, 24 | "resolveJsonModule": true, 25 | "emitDecoratorMetadata": true, 26 | "experimentalDecorators": true 27 | }, 28 | "include": ["./src/**/*"], 29 | "exclude": ["node_modules", "tests"] 30 | } 31 | --------------------------------------------------------------------------------