Skip to content

Commit

Permalink
Merge pull request #1459 from bancorprotocol/fix/edit-budget
Browse files Browse the repository at this point in the history
Fix distribution budget on edit
  • Loading branch information
GrandSchtroumpf authored Sep 4, 2024
2 parents 119bec6 + c668f4b commit 417ebe3
Show file tree
Hide file tree
Showing 22 changed files with 259 additions and 23 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"dependencies": {
"@babel/core": "^7.0.0-0",
"@bancor/carbon-sdk": "^0.0.97-DEV",
"@bancor/carbon-sdk": "0.0.99-DEV",
"@cloudflare/workers-types": "^4.20230717.0",
"@ethersproject/abi": "^5.0.0",
"@ethersproject/bytes": "^5.0.0",
Expand Down Expand Up @@ -131,4 +131,4 @@
"devDependencies": {
"@types/d3": "^7.4.3"
}
}
}
30 changes: 21 additions & 9 deletions src/components/strategies/edit/EditStrategyForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { EditStrategyOverlapTokens } from './EditStrategyOverlapTokens';
import { Button } from 'components/common/button';
import { useNavigate, useRouter } from '@tanstack/react-router';
import { cn } from 'utils/helpers';
import { QueryKey, useQueryClient, useUpdateStrategyQuery } from 'libs/queries';
import {
QueryKey,
Strategy,
useQueryClient,
useUpdateStrategyQuery,
} from 'libs/queries';
import { getStatusTextByTxStatus } from '../utils';
import { isZero } from '../common/utils';
import { carbonEvents } from 'services/events';
Expand All @@ -27,6 +32,7 @@ import { useDeleteStrategy } from '../useDeleteStrategy';
import style from 'components/strategies/common/form.module.css';
import config from 'config';
import { hasNoBudget } from '../overlapping/utils';
import { StrategyUpdate } from '@bancor/carbon-sdk';

interface EditOrders {
buy: BaseOrder;
Expand Down Expand Up @@ -58,6 +64,19 @@ const submitText: Record<EditTypes, string> = {

const spenderAddress = config.addresses.carbon.carbonController;

const getFieldsToUpdate = (orders: EditOrders, strategy: Strategy) => {
const { buy, sell } = orders;
const { order0, order1 } = strategy;
const fieldsToUpdate: Partial<StrategyUpdate> = {};
if (buy.min !== order0.startRate) fieldsToUpdate.buyPriceLow = buy.min;
if (buy.max !== order0.endRate) fieldsToUpdate.buyPriceHigh = buy.max;
if (buy.budget !== order0.balance) fieldsToUpdate.buyBudget = buy.budget;
if (sell.min !== order1.startRate) fieldsToUpdate.sellPriceLow = sell.min;
if (sell.max !== order1.endRate) fieldsToUpdate.sellPriceHigh = sell.max;
if (sell.budget !== order1.balance) fieldsToUpdate.sellBudget = sell.budget;
return fieldsToUpdate as StrategyUpdate;
};

export const EditStrategyForm: FC<Props> = (props) => {
const {
orders,
Expand Down Expand Up @@ -127,14 +146,7 @@ export const EditStrategyForm: FC<Props> = (props) => {
{
id: strategy.id,
encoded: strategy.encoded,
fieldsToUpdate: {
buyPriceLow: orders.buy.min,
buyPriceHigh: orders.buy.max,
buyBudget: orders.buy.budget,
sellPriceLow: orders.sell.min,
sellPriceHigh: orders.sell.max,
sellBudget: orders.sell.budget,
},
fieldsToUpdate: getFieldsToUpdate(orders, strategy),
buyMarginalPrice: orders.buy.marginalPrice,
sellMarginalPrice: orders.sell.marginalPrice,
},
Expand Down
111 changes: 111 additions & 0 deletions src/libs/testing-library/drivers/EditStrategyDriver.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import {
Screen,
waitForElementToBeRemoved,
within,
} from '@testing-library/dom';

export class EditStrategyDriver {
constructor(private screen: Screen) {}

async findForm() {
return this.screen.findByTestId('edit-form');
}

async findDisposableForm() {
const form = await this.findForm();
return {
element: form,
min: () => within(form).getByTestId('input-min'),
max: () => within(form).getByTestId('input-max'),
price: () => within(form).getByTestId('input-price'),
tabSell: () => within(form).getByTestId('tab-sell'),
tabBuy: () => within(form).getByTestId('tab-buy'),
limit: () => within(form).getByTestId('tab-limit'),
range: () => within(form).getByTestId('tab-range'),
budget: () => within(form).getByTestId('input-budget'),
marketPriceIndicators: () =>
within(form).queryAllByTestId('market-price-indication'),
approveWarnings: () => within(form).queryByTestId('approve-warnings'),
submit: () => within(form).getByTestId('edit-submit'),
};
}

async findRecurringForm() {
const form = await this.findForm();
const buySection = within(form).getByTestId('buy-section');
const sellSection = within(form).getByTestId('sell-section');
return {
element: form,
buy: {
min: () => within(buySection).getByTestId('input-min'),
max: () => within(buySection).getByTestId('input-max'),
price: () => within(buySection).getByTestId('input-price'),
limit: () => within(buySection).getByTestId('tab-limit'),
range: () => within(buySection).getByTestId('tab-range'),
budget: () => within(buySection).getByTestId('input-budget'),
marketPriceIndicators: () =>
within(buySection).queryAllByTestId('market-price-indication'),
},
sell: {
min: () => within(sellSection).getByTestId('input-min'),
max: () => within(sellSection).getByTestId('input-max'),
price: () => within(sellSection).getByTestId('input-price'),
limit: () => within(sellSection).getByTestId('tab-limit'),
range: () => within(sellSection).getByTestId('tab-range'),
budget: () => within(sellSection).getByTestId('input-budget'),
marketPriceIndicators: () =>
within(sellSection).queryAllByTestId('market-price-indication'),
},
approveWarnings: () => within(form).queryByTestId('approve-warnings'),
submit: () => within(form).getByTestId('edit-submit'),
};
}

async findOverlappingForm() {
const form = await this.findForm();
return {
element: form,
min: () => within(form).getByTestId('input-min'),
max: () => within(form).getByTestId('input-max'),
spread: {
input: () => within(form).getByTestId('spread-input'),
default: () => within(form).getByTestId('spread-0.05'),
option: (value: string) => within(form).getByTestId(`spread-${value}`),
},
anchorRequired: () => within(form).queryByTestId('require-anchor'),
anchor: (anchor: 'buy' | 'sell') =>
within(form).getByTestId(`anchor-${anchor}`),
budget: () => within(form).getByTestId('input-budget'),
marketPriceIndicators: () =>
within(form).queryAllByTestId('market-price-indication'),
approveWarnings: () => within(form).queryByTestId('approve-warnings'),
submit: () => within(form).getByTestId('edit-submit'),
};
}

async findUserPriceForm() {
return this.screen.findByTestId('user-price-form');
}

async findEditMarketPrice() {
return this.screen.findByTestId('edit-market-price');
}

async findUserPriceInput() {
const priceForm = await this.findUserPriceForm();
return {
editPrice: () => within(priceForm).getByTestId('input-price'),
approveWarning: () =>
within(priceForm).getByTestId('approve-price-warnings'),
confirm: () => within(priceForm).getByTestId('set-overlapping-price'),
};
}

waitForLoading(parent: HTMLElement) {
const loadings = parent.querySelectorAll('.loading-message');
const waitForAll = Array.from(loadings).map((loading) => {
return waitForElementToBeRemoved(() => loading);
});
return Promise.all(waitForAll);
}
}
9 changes: 2 additions & 7 deletions src/libs/testing-library/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,8 @@ vitest.mock('store/useTokensStore.ts', async (importOriginal) => {
vitest.mock('libs/sdk/index.ts', () => {
return {
carbonSDK: {
createBuySellStrategy: () => {
return {
to: '',
from: '',
nonce: 1,
};
},
createBuySellStrategy: () => ({ to: '', from: '', nonce: 1 }),
updateStrategy: () => ({ to: '', from: '', nonce: 1 }),
},
};
});
Expand Down
12 changes: 11 additions & 1 deletion src/libs/testing-library/utils/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ const encodeParams = (
.join('&');
};

const replaceParams = (url: string, params: Record<string, string>) => {
if (!Object.keys(params).length) return url;
const pattern = Object.keys(params)
.map((key) => `\\$${key}`)
.join('|');
const regex = new RegExp(pattern, 'g');
return url.replace(regex, (match) => params[match.replace('$', '')]);
};

/**
* Asynchronously created and loads a custom router with the specified component and optional base path and search parameters.
*
Expand All @@ -38,10 +47,11 @@ export const loadRouter = async ({
component,
basePath = '/',
search = {},
params = {},
}: RouterRenderParams) => {
const rootRoute = new RootRoute();
const subPath = encodeParams(search);
const path = `${basePath}?${subPath}`;
const path = `${replaceParams(basePath, params)}?${subPath}`;

const componentRoute = new Route({
getParentRoute: () => rootRoute,
Expand Down
1 change: 1 addition & 0 deletions src/libs/testing-library/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export type RouterRenderParams = {
component: () => JSX.Element;
basePath?: string;
search?: Record<string, string | number | symbol>;
params?: Record<string, string>;
};
107 changes: 107 additions & 0 deletions src/pages/strategies/edit/budget/recurring.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { describe, test, expect, beforeAll, afterAll } from 'vitest';
import {
MockServer,
marketRateHandler,
renderWithRouter,
screen,
tokenList,
userEvent,
} from 'libs/testing-library';
import { EditStrategyDriver } from 'libs/testing-library/drivers/EditStrategyDriver';
import { EditBudgetRecurringPage } from './recurring';
import { EditStrategyProvider } from 'components/strategies/edit/EditStrategyContext';
import { Strategy } from 'libs/queries';
import { SafeDecimal } from 'libs/safedecimal';
import { carbonSDK } from 'libs/sdk';
import { spyOn } from '@vitest/spy';
import { EditStrategyLayout } from 'components/strategies/edit/EditStrategyLayout';

const basePath = '/strategies/edit/$strategyId/budget/recurring';

const marketRates: Record<string, Record<string, number>> = {
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': { USD: 1 }, // USDC
'0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee': { USD: 2.5 }, // ETH
};

const mockServer = new MockServer([marketRateHandler(marketRates)]);

beforeAll(() => mockServer.start());
afterAll(() => mockServer.close());

interface Props {
strategy: Strategy;
type: 'deposit' | 'withdraw';
}

const WrappedRecurring = ({ strategy, type }: Props) => {
return (
<EditStrategyProvider strategy={strategy}>
<EditStrategyLayout editType={type}>
<EditBudgetRecurringPage />
</EditStrategyLayout>
</EditStrategyProvider>
);
};

describe('Create recurring page', () => {
test('should only send to the SDK what has been changed', async () => {
const baseToken = tokenList.ETH;
const quoteToken = tokenList.USDC;

const strategy: Strategy = {
id: '1',
idDisplay: '1',
base: baseToken,
quote: quoteToken,
order0: {
balance: '1',
startRate: '1',
endRate: '2',
marginalRate: '1.5',
},
order1: {
balance: '1',
startRate: '3',
endRate: '4',
marginalRate: '3.5',
},
status: 'active',
encoded: {} as any,
roi: new SafeDecimal('1'),
};

const search = {
editType: 'deposit',
buyBudget: '2',
};

const url = `/strategies/edit/${strategy.id}/budget/recurring`;
const { router } = await renderWithRouter({
component: () => <WrappedRecurring strategy={strategy} type="deposit" />,
basePath,
search,
params: { strategyId: strategy.id },
});
const user = userEvent.setup();

// Check search params
expect(router.state.location.pathname).toBe(url);
expect(router.state.location.search).toStrictEqual(search);

const recurringDriver = new EditStrategyDriver(screen);
const form = await recurringDriver.findRecurringForm();

// Check form
expect(form.buy.budget()).toHaveValue(search.buyBudget);
expect(form.sell.budget()).toHaveValue('');
const spy = spyOn(carbonSDK, 'updateStrategy');
await user.click(form.submit());
expect(spy).toHaveBeenCalledWith(
strategy.id,
strategy.encoded,
{ buyBudget: '3' },
undefined,
undefined
);
});
});
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1555,10 +1555,10 @@
"@babel/helper-validator-identifier" "^7.24.7"
to-fast-properties "^2.0.0"

"@bancor/carbon-sdk@^0.0.97-DEV":
version "0.0.97-DEV"
resolved "https://registry.yarnpkg.com/@bancor/carbon-sdk/-/carbon-sdk-0.0.97-DEV.tgz#d8cedfd5436779a880623031a6661bc74e0e5f30"
integrity sha512-1N/p7u3gdlV1F/BcD+nDWN2ao8JwekOPlVvmW2j5dEuNqDEDMWiUxbO6t18pnGr57mYF+vqt+R48h/d6HYRhKA==
"@bancor/carbon-sdk@0.0.99-DEV":
version "0.0.99-DEV"
resolved "https://registry.yarnpkg.com/@bancor/carbon-sdk/-/carbon-sdk-0.0.99-DEV.tgz#ebbc1f5969a0eca9363b0217f25d140290299156"
integrity sha512-DrevN/ahoDqyLc8IwUC6CiGOZn7BQXz42uBc7rU0aWc3mVhp8TR9WMJi3oVDS8DaYvRIcMv5U0sa6gK5IbbgGQ==
dependencies:
"@ethersproject/abi" "^5.7.0"
"@ethersproject/bignumber" "^5.7.0"
Expand Down

0 comments on commit 417ebe3

Please sign in to comment.