diff --git a/Makefile b/Makefile index 812f7d4..d2905b9 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ test: --require jsdom-global/register \ --require ts-node/register 'tests/**/*.test.ts' \ --require tsconfig-paths/register \ - --timeout 10000 \ + --timeout 30000 \ --exit .PHONY: lint diff --git a/package.json b/package.json index 93d2171..7068fd5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@polymarket/clob-client", "description": "Typescript client for Polymarket's CLOB", - "version": "1.1.17", + "version": "1.1.18", "contributors": [ { "name": "Jonathan Amenechi", diff --git a/src/order-builder/helpers.ts b/src/order-builder/helpers.ts index f61c679..1bfac4c 100644 --- a/src/order-builder/helpers.ts +++ b/src/order-builder/helpers.ts @@ -33,26 +33,16 @@ export const buildOrder = async ( return cTFExchangeOrderBuilder.buildSignedOrder(orderData); }; -/** - * Translate simple user order to args used to generate Orders - */ -export const buildOrderCreationArgs = async ( - signer: string, - maker: string, - signatureType: SignatureType, - userOrder: UserOrder, -): Promise => { - let makerAmount: string; - let takerAmount: string; - - let side: UtilsSide; - - if (userOrder.side === Side.BUY) { - side = UtilsSide.BUY; - +export const getOrderAmounts = ( + side: Side, + size: number, + price: number, +): { side: UtilsSide; rawMakerAmt: number; rawTakerAmt: number } => { + const rawPrice = roundNormal(price, 2); + + if (side === Side.BUY) { // force 2 decimals places - const rawTakerAmt = roundDown(userOrder.size, 2); - const rawPrice = roundNormal(userOrder.price, 2); // prob can just round this normal + const rawTakerAmt = roundDown(size, 2); let rawMakerAmt = rawTakerAmt * rawPrice; if (decimalPlaces(rawMakerAmt) > 4) { @@ -62,13 +52,13 @@ export const buildOrderCreationArgs = async ( } } - makerAmount = parseUnits(rawMakerAmt.toString(), COLLATERAL_TOKEN_DECIMALS).toString(); - takerAmount = parseUnits(rawTakerAmt.toString(), CONDITIONAL_TOKEN_DECIMALS).toString(); + return { + side: UtilsSide.BUY, + rawMakerAmt, + rawTakerAmt, + }; } else { - side = UtilsSide.SELL; - - const rawMakerAmt = roundDown(userOrder.size, 2); - const rawPrice = roundNormal(userOrder.price, 2); + const rawMakerAmt = roundDown(size, 2); let rawTakerAmt = rawMakerAmt * rawPrice; if (decimalPlaces(rawTakerAmt) > 4) { @@ -78,9 +68,31 @@ export const buildOrderCreationArgs = async ( } } - makerAmount = parseUnits(rawMakerAmt.toString(), CONDITIONAL_TOKEN_DECIMALS).toString(); - takerAmount = parseUnits(rawTakerAmt.toString(), COLLATERAL_TOKEN_DECIMALS).toString(); + return { + side: UtilsSide.SELL, + rawMakerAmt, + rawTakerAmt, + }; } +}; + +/** + * Translate simple user order to args used to generate Orders + */ +export const buildOrderCreationArgs = async ( + signer: string, + maker: string, + signatureType: SignatureType, + userOrder: UserOrder, +): Promise => { + const { side, rawMakerAmt, rawTakerAmt } = getOrderAmounts( + userOrder.side, + userOrder.size, + userOrder.price, + ); + + const makerAmount = parseUnits(rawMakerAmt.toString(), COLLATERAL_TOKEN_DECIMALS).toString(); + const takerAmount = parseUnits(rawTakerAmt.toString(), CONDITIONAL_TOKEN_DECIMALS).toString(); let taker; if (typeof userOrder.taker !== "undefined" && userOrder.taker) { @@ -140,18 +152,13 @@ export const createOrder = async ( return buildOrder(eoaSigner, clobContracts.Exchange, chainId, orderData); }; -/** - * Translate simple user market order to args used to generate Orders - */ -export const buildMarketBuyOrderCreationArgs = async ( - signer: string, - maker: string, - signatureType: SignatureType, - userMarketOrder: UserMarketOrder, -): Promise => { +export const getMarketBuyOrderRawAmounts = ( + amount: number, + price: number, +): { rawMakerAmt: number; rawTakerAmt: number } => { // force 2 decimals places - const rawMakerAmt = roundDown(userMarketOrder.amount, 2); - const rawPrice = roundDown(userMarketOrder.price || 1, 2); + const rawMakerAmt = roundDown(amount, 2); + const rawPrice = roundDown(price, 2); let rawTakerAmt = rawMakerAmt / rawPrice; if (decimalPlaces(rawTakerAmt) > 4) { @@ -161,6 +168,26 @@ export const buildMarketBuyOrderCreationArgs = async ( } } + return { + rawMakerAmt, + rawTakerAmt, + }; +}; + +/** + * Translate simple user market order to args used to generate Orders + */ +export const buildMarketBuyOrderCreationArgs = async ( + signer: string, + maker: string, + signatureType: SignatureType, + userMarketOrder: UserMarketOrder, +): Promise => { + const { rawMakerAmt, rawTakerAmt } = getMarketBuyOrderRawAmounts( + userMarketOrder.amount, + userMarketOrder.price || 1, + ); + const makerAmount = parseUnits(rawMakerAmt.toString(), COLLATERAL_TOKEN_DECIMALS).toString(); const takerAmount = parseUnits(rawTakerAmt.toString(), CONDITIONAL_TOKEN_DECIMALS).toString(); diff --git a/src/utilities.ts b/src/utilities.ts index 808fe05..85f796e 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -45,6 +45,11 @@ export const decimalPlaces = (num: number): number => { if (Number.isInteger(num)) { return 0; } + const arr = num.toString().split("."); + if (arr.length <= 1) { + return 0; + } + return arr[1].length; }; diff --git a/tests/order-builder/helpers.test.ts b/tests/order-builder/helpers.test.ts index d09274e..4c1ef4c 100644 --- a/tests/order-builder/helpers.test.ts +++ b/tests/order-builder/helpers.test.ts @@ -7,6 +7,8 @@ import { createOrder, buildMarketBuyOrderCreationArgs, createMarketBuyOrder, + getOrderAmounts, + getMarketBuyOrderRawAmounts, } from "../../src/order-builder/helpers"; import { OrderData, @@ -16,7 +18,7 @@ import { getContracts, } from "@polymarket/order-utils"; import { Wallet } from "@ethersproject/wallet"; -import { roundDown } from "../../src/utilities"; +import { decimalPlaces, roundDown } from "../../src/utilities"; describe("helpers", () => { const chainId = Chain.MUMBAI; @@ -147,6 +149,44 @@ describe("helpers", () => { }); }); + describe("getOrderAmounts", async () => { + it("buy", async () => { + const delta = 0.01; + let size = 0.01; + + for (; size <= 100; ) { + let price = 0.01; + for (; price <= 1; ) { + const { rawMakerAmt, rawTakerAmt } = getOrderAmounts(Side.BUY, size, price); + + expect(decimalPlaces(rawMakerAmt)).to.lte(4); + expect(decimalPlaces(rawTakerAmt)).to.lte(2); + + price += delta; + } + size += delta; + } + }); + + it("sell", async () => { + const delta = 0.01; + let size = 0.01; + + for (; size <= 100; ) { + let price = 0.01; + for (; price <= 1; ) { + const { rawMakerAmt, rawTakerAmt } = getOrderAmounts(Side.SELL, size, price); + + expect(decimalPlaces(rawMakerAmt)).to.lte(2); + expect(decimalPlaces(rawTakerAmt)).to.lte(4); + + price += delta; + } + size += delta; + } + }); + }); + describe("buildOrderCreationArgs", () => { it("buy order", async () => { const order: UserOrder = { @@ -463,6 +503,26 @@ describe("helpers", () => { }); }); + describe("getMarketBuyOrderRawAmounts", async () => { + it("market buy", async () => { + const delta = 0.01; + let size = 0.01; + + for (; size <= 100; ) { + let price = 0.01; + for (; price <= 1; ) { + const { rawMakerAmt, rawTakerAmt } = getMarketBuyOrderRawAmounts(size, price); + + expect(decimalPlaces(rawMakerAmt)).to.lte(2); + expect(decimalPlaces(rawTakerAmt)).to.lte(4); + + price += delta; + } + size += delta; + } + }); + }); + describe("buildMarketBuyOrderCreationArgs", () => { it("market buy order", async () => { const order: UserMarketOrder = { diff --git a/tests/utilities.test.ts b/tests/utilities.test.ts index c3468ee..4636f03 100644 --- a/tests/utilities.test.ts +++ b/tests/utilities.test.ts @@ -514,5 +514,6 @@ describe("utilities", () => { it("decimalPlaces", () => { expect(decimalPlaces(949.9970999999999)).to.equal(13); + expect(decimalPlaces(949)).to.equal(0); }); });