Skip to content

Commit

Permalink
fix(swap): handle minimum egress amount (#767)
Browse files Browse the repository at this point in the history
  • Loading branch information
acdibble committed May 29, 2024
1 parent bef3deb commit f145322
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 15 deletions.
61 changes: 49 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ which it is deprecated.
- `SwapSDK.prototype.executeSwap` allows to not wait for transaction inclusion
by passing `{ wait: 0 }` as `txOpts` param now. The method will return the
transaction hash of the submitted transaction.
- Liquidity fees have been moved from the `includedFees` property on the
`getQuote` response, into a new `poolInfo` property, which is an array of the
pools the swap passes through, along with the estimated fee and fee asset.

### Fixed

Expand All @@ -42,6 +45,40 @@ which it is deprecated.
- `SwapSDK.prototype.requestDepositAddress` supports an optional `brokerCommissionBps`
and `affiliateBrokers` option. The new options are only available when initializing
the SDK with a brokerUrl and will be applied only to the requested deposit channel.
- Support for Arbitrum tokens have been added.
- Arbitrum ETH and USDC have been added to the `ChainAssetMap` type:

```diff
type ChainAssetMap<T> = {
Bitcoin: {
BTC: T;
};
Ethereum: {
ETH: T;
USDC: T;
FLIP: T;
USDT: T;
};
Polkadot: {
DOT: T;
};
+ Arbitrum: {
+ ETH: T;
+ USDC: T
+ };
}
```

- Arbitrum has also been added to our `ChainMap` type:

```diff
type ChainMap<T> = {
Bitcoin: T;
Ethereum: T;
Polkadot: T;
+ Arbitrum: T;
}
```

## 1.3.0

Expand All @@ -64,18 +101,18 @@ which it is deprecated.

```diff
type ChainAssetMap<T> = {
Bitcoin: {
BTC: T;
};
Ethereum: {
ETH: T;
USDC: T;
FLIP: T;
+ USDT: T;
};
Polkadot: {
DOT: T;
};
Bitcoin: {
BTC: T;
};
Ethereum: {
ETH: T;
USDC: T;
FLIP: T;
+ USDT: T;
};
Polkadot: {
DOT: T;
};
}
```

Expand Down
30 changes: 28 additions & 2 deletions packages/swap/src/routes/__tests__/quote.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ describe('server', () => {
network_fee: buildFee('Usdc', 2000000).bigint,
ingress_fee: buildFee('Usdc', 2000000).bigint,
intermediary: null,
output: BigInt(0),
output: 0n,
} as CfSwapRateV2);

const params = new URLSearchParams({
Expand All @@ -278,7 +278,33 @@ describe('server', () => {

expect(status).toBe(400);
expect(body).toMatchObject({
message: 'egress amount (0) is lower than minimum egress amount (1)',
message: 'swap output amount is lower than the egress fee (50000)',
});
expect(sendSpy).toHaveBeenCalledTimes(1);
});

it('rejects when the egress amount is smaller than the minimum egress amount', async () => {
const sendSpy = jest.spyOn(WsClient.prototype, 'sendRequest').mockResolvedValueOnce({
egress_fee: buildFee('Eth', 25000).bigint,
network_fee: buildFee('Usdc', 2000000).bigint,
ingress_fee: buildFee('Usdc', 2000000).bigint,
intermediary: null,
output: 599n,
} as CfSwapRateV2);

const params = new URLSearchParams({
srcChain: 'Ethereum',
srcAsset: 'ETH',
destChain: 'Bitcoin',
destAsset: 'BTC',
amount: (100e6).toString(),
});

const { body, status } = await request(server).get(`/quote?${params.toString()}`);

expect(status).toBe(400);
expect(body).toMatchObject({
message: 'egress amount (599) is lower than minimum egress amount (600)',
});
expect(sendSpy).toHaveBeenCalledTimes(1);
});
Expand Down
9 changes: 8 additions & 1 deletion packages/swap/src/utils/getPoolQuote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getPipAmountFromAmount } from '@/shared/functions';
import { QuoteQueryResponse } from '@/shared/schemas';
import { estimateSwapDuration } from '@/swap/utils/swap';
import { buildFee, getPoolFees } from './fees';
import { getMinimumEgressAmount } from './rpc';
import { getEgressFee, getMinimumEgressAmount } from './rpc';
import ServiceError from './ServiceError';
import { LimitOrders, getSwapRateV2 } from './statechain';
import { InternalAsset, Pool } from '../client';
Expand Down Expand Up @@ -60,6 +60,13 @@ export default async function getPoolQuote({
throw ServiceError.badRequest('swap amount is lower than ingress fee');
}

const rpcEgressFee = await getEgressFee(destAsset);
throw ServiceError.badRequest(
`swap output amount is lower than the egress fee (${rpcEgressFee})`,
);
}

if (quote.outputAmount < minimumEgressAmount) {
throw ServiceError.badRequest(
`egress amount (${quote.outputAmount}) is lower than minimum egress amount (${minimumEgressAmount})`,
);
Expand Down

0 comments on commit f145322

Please sign in to comment.