From 2cc19a33f35d572c3c439493c8a7d34fef036a57 Mon Sep 17 00:00:00 2001 From: Aleksandr Kraiz Date: Wed, 31 Aug 2022 16:14:46 +0400 Subject: [PATCH] Added parseExchangeTradeTransaction --- README.md | 31 ++++++ src/utils/index.ts | 1 + src/utils/parseExchangeTradeTransaction.ts | 118 +++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 src/utils/parseExchangeTradeTransaction.ts diff --git a/README.md b/README.md index 0fed614..c75705f 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Orion’s SDK is free to use and does not require an API key or registration. Re - [Price Feed Websocket Stream](#price-feed-websocket-stream) - [About our fetching system](#about-our-fetching-system) - [Using contracts](#using-contracts) +- [Utils](#utils) + - [Parsing trade transactions](#parsing-trade-transactions) ## Install @@ -548,3 +550,32 @@ const { candles, timeStart, timeEnd } = await simpleFetch( ## Using contracts Use package [@orionprotocol/contracts](https://github.com/orionprotocol/contracts) + +## Utils + +### Parsing trade transactions + +```ts +import { utils } from "@orionprotocol/sdk"; + +// Examples: +// fillThroughOrionPool: https://bscscan.com/tx/0xe311fb927b938e1e484b7660b5c4bd0aa9c97c86f6e1f681d6867dabc8a702fe +// swapThroughOrionPool: https://bscscan.com/tx/0xb9c93851f605b8b5a906dbc9363eae0aa6635ce41ffb6bf540d954f9138bf58c +// fillOrders: https://bscscan.com/tx/0x860b8820ece1a5af11b2459b6bd1a025e7cdc86a1d7e1e3d73558db6e72974d4 + +const data = utils.parseExchangeTradeTransaction({ + data: "0x4c36fc72000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000004a817c80000000000000000000000000000000000000000000000000000000000019595c700000000000000000000000000000000000000000000000000000000000002a000000000000000000000000050abeb3e61167365d0a7dd7b3301a8ae27016d760000000000000000000000002d23c313feac4810d9d014f840741363fccba675000000000000000000000000e4ca1f75eca6214393fce1c1b316c237664eaa8e00000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000e4ca1f75eca6214393fce1c1b316c237664eaa8e00000000000000000000000000000000000000000000000000000004a817c8000000000000000000000000000000000000000000000000000000000006df56a00000000000000000000000000000000000000000000000000000000003f7efc600000000000000000000000000000000000000000000000000000182dff605d000000000000000000000000000000000000000000000000000000182e2465cb60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000000411b7b9908456b6d0b97e411b3585de8ed2c7c1db9a39d2f5f81fc8ed765f0575d29cd9ebd0533e3eeb819d70971bf7bd705c52871c7a00ba67c738040a69895911c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000e52ccf7b6ce4817449f2e6fa7efd7b567803e4b4000000000000000000000000e4ca1f75eca6214393fce1c1b316c237664eaa8e00000000000000000000000055d398326f99059ff775485246999027b3197955", +}); + +switch (data.type) { + case "fillOrders": + console.log(data.args.orders.buyOrder); + break; + case "fillThroughOrionPool": + console.log(data.args.order); + break; + case "swapThroughOrionPool": + console.log(data.args.amount_spend); + break; +} +``` diff --git a/src/utils/index.ts b/src/utils/index.ts index 18e214d..c91babf 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -10,6 +10,7 @@ export { default as normalizeNumber } from './normalizeNumber'; export { default as getSwapPair } from './getSwapPair'; export { default as getSwapSide } from './getSwapSide'; export { default as isNetworkCodeInEnvironment } from './isNetworkCodeInEnvironment'; +export { default as parseExchangeTradeTransaction } from './parseExchangeTradeTransaction'; // export { default as HttpError } from './httpError'; diff --git a/src/utils/parseExchangeTradeTransaction.ts b/src/utils/parseExchangeTradeTransaction.ts new file mode 100644 index 0000000..fdd6255 --- /dev/null +++ b/src/utils/parseExchangeTradeTransaction.ts @@ -0,0 +1,118 @@ +import { Exchange__factory } from '@orionprotocol/contracts'; +import { ethers } from 'ethers'; +import { z } from 'zod'; + +const swapThroughOrionPoolSchema = z.object({ + name: z.literal('swapThroughOrionPool'), + args: z.tuple([ + z.instanceof(ethers.BigNumber), // amount_spend + z.instanceof(ethers.BigNumber), // amount_receive + z.string().refine(ethers.utils.isAddress).array().nonempty(), // path + z.boolean(), // is_exact_spend + ]), +}).transform((data) => ({ + name: data.name, + args: { + amount_spend: data.args[0], + amount_receive: data.args[1], + path: data.args[2], + is_exact_spend: data.args[3], + }, +})); + +const buyOrderSchema = z.tuple([ // buy order + z.string().refine(ethers.utils.isAddress), // senderAddress + z.string().refine(ethers.utils.isAddress), // matcherAddress + z.string().refine(ethers.utils.isAddress), // baseAsset + z.string().refine(ethers.utils.isAddress), // quoteAsset + z.string().refine(ethers.utils.isAddress), // matcherFeeAsset + z.instanceof(ethers.BigNumber), // amount + z.instanceof(ethers.BigNumber), // price + z.instanceof(ethers.BigNumber), // matcherFee + z.instanceof(ethers.BigNumber), // nonce + z.instanceof(ethers.BigNumber), // expiration + z.literal(1), // buySide + z.boolean(), // isPersonalSign + z.string().refine(ethers.utils.isHexString), // signature +]); +const sellOrderSchema = z.tuple([ // sell orer + z.string().refine(ethers.utils.isAddress), // senderAddress + z.string().refine(ethers.utils.isAddress), // matcherAddress + z.string().refine(ethers.utils.isAddress), // baseAsset + z.string().refine(ethers.utils.isAddress), // quoteAsset + z.string().refine(ethers.utils.isAddress), // matcherFeeAsset + z.instanceof(ethers.BigNumber), // amount + z.instanceof(ethers.BigNumber), // price + z.instanceof(ethers.BigNumber), // matcherFee + z.instanceof(ethers.BigNumber), // nonce + z.instanceof(ethers.BigNumber), // expiration + z.literal(0), // buySide + z.boolean(), // isPersonalSign + z.string().refine(ethers.utils.isHexString), // signature +]); + +const toOrder = | z.infer>(data: T) => ({ + senderAddress: data[0], + matcherAddress: data[1], + baseAsset: data[2], + quoteAsset: data[3], + matcherFeeAsset: data[4], + amount: data[5], + price: data[6], + matcherFee: data[7], + nonce: data[8], + expiration: data[9], + buySide: data[10], + isPersonalSign: data[11], + signature: data[12], +}); + +const fillThroughOrionPoolSchema = z.object({ + name: z.literal('fillThroughOrionPool'), + args: z.tuple([ + sellOrderSchema, + z.instanceof(ethers.BigNumber), // filled amount + z.instanceof(ethers.BigNumber), // blockchainFee + z.string().refine(ethers.utils.isAddress).array().nonempty(), // path + ]), +}).transform((data) => ({ + name: data.name, + args: { + order: toOrder(data.args[0]), + filledAmount: data.args[1], + blockchainFee: data.args[2], + path: data.args[3], + }, +})); + +const fillOrdersSchema = z.object({ + name: z.literal('fillOrders'), + args: z.tuple([ + buyOrderSchema, + sellOrderSchema, + z.instanceof(ethers.BigNumber), // filledPrice + z.instanceof(ethers.BigNumber), // filledAmount + ]), +}).transform((data) => ({ + name: data.name, + args: { + orders: { + buyOrder: toOrder(data.args[0]), + sellOrder: toOrder(data.args[1]), + }, + filledPrice: data.args[2], + filledAmount: data.args[3], + }, +})); + +export default function parseExchangeTradeTransaction(tx: { data: string, value?: ethers.BigNumberish }) { + const exchangeContractInterface = Exchange__factory.createInterface(); + const txDescription = exchangeContractInterface.parseTransaction(tx); + const schema = z.union([ + fillOrdersSchema, + swapThroughOrionPoolSchema, + fillThroughOrionPoolSchema, + ]); + const data = schema.parse(txDescription); + return data; +}