Skip to content

Commit

Permalink
Merge pull request #113 from bancorprotocol/feature/prices
Browse files Browse the repository at this point in the history
  • Loading branch information
zavelevsky authored Dec 6, 2023
2 parents 37bae46 + 9a47ba4 commit 4d3129d
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

strategy:
matrix:
node-version: [18.x]
node-version: [20.x]

steps:
- uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.13.0
20
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@bancor/carbon-sdk",
"type": "module",
"source": "src/index.ts",
"version": "0.0.89-DEV",
"version": "0.0.90-DEV",
"description": "The SDK is a READ-ONLY tool, intended to facilitate working with Carbon contracts. It's a convenient wrapper around our matching algorithm, allowing programs and users get a ready to use transaction data that will allow them to manage strategies and fulfill trades",
"main": "dist/index.js",
"module": "dist/index.js",
Expand All @@ -17,6 +17,9 @@
"files": [
"dist/"
],
"engines": {
"node": ">=20"
},
"typesVersions": {
"*": {
"contracts-api": [
Expand Down
47 changes: 39 additions & 8 deletions src/strategy-management/Toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -700,17 +700,38 @@ export class Toolkit {
);
}

/**
* Calculate the overlapping strategy prices. Returns it with correct decimals
*
* @param {string} quoteToken - The address of the quote token.
* @param {string} buyPriceLow - The minimum buy price for the strategy, in in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} sellPriceHigh - The maximum sell price for the strategy, in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} marketPrice - The market price, in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} spreadPercentage - The spread percentage, e.g. for 10%, enter `10`.
* @return {Promise<{
* buyPriceLow: string;
* buyPriceHigh: string;
* buyPriceMarginal: string;
* sellPriceLow: string;
* sellPriceHigh: string;
* sellPriceMarginal: string;
* marketPrice: string;
* }>} The calculated overlapping strategy prices.
*/
public async calculateOverlappingStrategyPrices(
quoteToken: string,
buyPriceLow: string,
sellPriceHigh: string,
marketPrice: string,
spreadPercentage: string
): Promise<{
buyPriceLow: string;
buyPriceHigh: string;
buyPriceMarginal: string;
sellPriceLow: string;
sellPriceHigh: string;
sellPriceMarginal: string;
marketPrice: string;
}> {
logger.debug('calculateOverlappingStrategyPrices called', arguments);

Expand All @@ -725,16 +746,19 @@ export class Toolkit {
);

const result = {
buyPriceLow: trimDecimal(buyPriceLow, quoteDecimals),
buyPriceHigh: trimDecimal(prices.buyPriceHigh.toString(), quoteDecimals),
buyPriceMarginal: trimDecimal(
prices.buyPriceMarginal.toString(),
quoteDecimals
),
sellPriceLow: trimDecimal(prices.sellPriceLow.toString(), quoteDecimals),
sellPriceHigh: trimDecimal(sellPriceHigh, quoteDecimals),
sellPriceMarginal: trimDecimal(
prices.sellPriceMarginal.toString(),
quoteDecimals
),
marketPrice: trimDecimal(marketPrice, quoteDecimals),
};

logger.debug('calculateOverlappingStrategyPrices info:', {
Expand Down Expand Up @@ -841,9 +865,11 @@ export class Toolkit {
* @param {string} baseToken - The address of the base token for the strategy.
* @param {string} quoteToken - The address of the quote token for the strategy.
* @param {string} buyPriceLow - The minimum buy price for the strategy, in in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} buyPriceMarginal - The marginal buy price for the strategy, in in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} buyPriceHigh - The maximum buy price for the strategy, in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} buyBudget - The maximum budget for buying tokens in the strategy, in `quoteToken`, as a string.
* @param {string} sellPriceLow - The minimum sell price for the strategy, in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} sellPriceMarginal - The marginal sell price for the strategy, in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} sellPriceHigh - The maximum sell price for the strategy, in `quoteToken` per 1 `baseToken`, as a string.
* @param {string} sellBudget - The maximum budget for selling tokens in the strategy, in `baseToken`, as a string.
* @param {Overrides} [overrides] - Optional overrides for the transaction, such as gas price or nonce.
Expand All @@ -864,8 +890,10 @@ export class Toolkit {
* '0x6B175474E89094C44Da98b954EedeAC495271d0F',
* '0.1',
* '0.2',
* '0.2',
* '1',
* '0.5',
* '0.5',
* '0.6',
* '2'
* );
Expand Down Expand Up @@ -919,15 +947,18 @@ export class Toolkit {
}

/**
* Creates an unsigned transaction to update an on chain strategy.
* This function takes various optional parameters to update different aspects of the strategy and returns a promise that resolves to a PopulatedTransaction object.
*
* @param strategyId
* @param encoded
* @param param2
* @param {MarginalPriceOptions | string} marginalPrice - The marginal price parameter.
* Can either be a value from the `MarginalPriceOptions` enum, or a "BigNumberish" string value for advanced users -
* who wish to set the marginal price themselves.
* @param overrides
* @returns
* @param {string} strategyId - The unique identifier of the strategy to be updated.
* @param {EncodedStrategyBNStr} encoded - The encoded strategy string, representing the current state of the strategy in the contracts.
* @param {StrategyUpdate} strategyUpdate - An object containing optional fields to update in the strategy, including buy and sell price limits and budgets.
* @param {MarginalPriceOptions | string} [buyPriceMarginal] - Optional parameter that can be used to instruct the SDK what to do with the marginal price - or pass a value to use.
* If unsure leave this undefined.
* @param {MarginalPriceOptions | string} [sellPriceMarginal] - Optional parameter that can be used to instruct the SDK what to do with the marginal price - or pass a value to use.
* If unsure leave this undefined.
* @param {PayableOverrides} [overrides] - Optional Ethereum transaction overrides.
* @returns {Promise<PopulatedTransaction>} A promise that resolves to a PopulatedTransaction object.
*/
public async updateStrategy(
strategyId: string,
Expand Down
10 changes: 5 additions & 5 deletions src/utils/numerics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ export const mulDiv = (x: BigNumber, y: BigNumber, z: BigNumber) =>
y.eq(z) ? x : x.mul(y).div(z);

export function trimDecimal(input: string, precision: number): string {
const decimalIdx = input.indexOf('.');
if (decimalIdx !== -1) {
return input.slice(0, decimalIdx + precision + 1);
}
return input;
// Use Decimal for precise arithmetic
const result = new Decimal(input).toFixed(precision, Decimal.ROUND_DOWN);

// Remove trailing zeros and decimal point if necessary
return result.replace(/(\.\d*?[1-9])0+$|\.0*$/, '$1');
}

// A take on parseUnits that supports floating point
Expand Down
23 changes: 23 additions & 0 deletions tests/numerics.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { expect } from 'chai';
import { trimDecimal } from '../src/utils/numerics';

describe('numerics', () => {
describe('trimDecimal', () => {
const testCases: [string, number, string][] = [
['1', 10, '1'],
['0.01', 10, '0.01'],
['1000', 10, '1000'],
['0', 10, '0'],
['0.00001', 2, '0'],
['0.1234', 2, '0.12'],
['-1.2345', 2, '-1.23'],
['1.999', 0, '1'],
['12345678901234567891.23456789123456789123456789', 18, '12345678901234567891.234567891234567891'],
];
testCases.forEach(([amount, precision, expectedResult]) => {
it(`should trim decimal ${amount} with precision ${precision} and get ${expectedResult}`, () => {
expect(trimDecimal(amount, precision)).to.equal(expectedResult);
});
});
});
});
5 changes: 4 additions & 1 deletion tests/toolkit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,19 @@ describe('Toolkit', () => {
const toolkit = new Toolkit(apiMock, cacheMock, decimalFetcher);
const result = await toolkit.calculateOverlappingStrategyPrices(
'quoteToken',
'1500',
'1500.0000000000000000001',
'2000',
'1845',
'1'
);
expect(result).to.deep.equal({
buyPriceLow: '1500',
buyPriceHigh: '1980.198019801980198019',
buyPriceMarginal: '1835.843615937429955302',
sellPriceLow: '1515',
sellPriceHigh: '2000',
sellPriceMarginal: '1854.202052096804254855',
marketPrice: '1845',
});
});
it('should calculate strategy sell budget', async () => {
Expand Down

0 comments on commit 4d3129d

Please sign in to comment.