Skip to content

Commit

Permalink
Merge pull request paraswap#260 from paraswap/feat/BACK-815
Browse files Browse the repository at this point in the history
Feat/back 815
  • Loading branch information
Louis-Amas authored Jan 3, 2023
2 parents b166753 + 6339b18 commit b3fdf17
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@paraswap/dex-lib",
"version": "2.9.36",
"version": "2.9.39",
"main": "build/index.js",
"types": "build/index.d.ts",
"repository": "https://github.com/paraswap/paraswap-dex-lib",
Expand Down
5 changes: 4 additions & 1 deletion src/dex/generic-rfq/fetch-mm-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { RequestConfig } from '../../dex-helper/irequest-wrapper';
import Fetcher from '../../lib/fetcher/fetcher';
import { getLogger } from '../../lib/log4js';
import { MultiWrapper } from '../../lib/multi-wrapper';
import { authHttp } from './security';
import { genericRFQAuthHttp } from './security';
import {
BlackListResponse,
FetcherParams,
Expand Down Expand Up @@ -48,6 +48,9 @@ const multiWrapper = new MultiWrapper(
);

const url = getEnv('GENERIC_RFQ_URL');
const path = getEnv('GENERIC_RFQ_PATH_TO_OVERRIDE');

const authHttp = genericRFQAuthHttp(path);

const secret = {
secretKey: atob(getEnv('GENERIC_RFQ_SECRET_KEY')),
Expand Down
125 changes: 119 additions & 6 deletions src/dex/generic-rfq/generic-rfq-e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ const buildConfigForGenericRFQ = (): RFQConfig => {
domain: 'paraswap',
};

const pathToRemove = getEnv('GENERIC_RFQ_PATH_TO_OVERRIDE');

return {
maker: getEnv('GENERIC_RFQ_MAKER_ADDRESS'),
tokensConfig: {
Expand Down Expand Up @@ -173,6 +175,7 @@ const buildConfigForGenericRFQ = (): RFQConfig => {
intervalMs: 1000 * 60 * 60 * 10,
dataTTLS: 1000 * 60 * 60 * 11,
},
pathToRemove,
};
};

Expand All @@ -181,15 +184,51 @@ describe('GenericRFQ YOUR_NAME E2E Mainnet', () => {

const network = Network.MAINNET;
const smartTokens = SmartTokens[network];

const srcToken = smartTokens.USDC;
const destToken = smartTokens.WBTC;

const config = generateConfig(network);

config.rfqConfigs[dexKey] = buildConfigForGenericRFQ();

describe('GenericRFQ', () => {
describe('GenericRFQ B/Q BUY', () => {
const srcToken = smartTokens.USDC;
const destToken = smartTokens.WBTC;

srcToken.addBalance(testAccount.address, MAX_UINT);
srcToken.addAllowance(
testAccount.address,
config.augustusRFQAddress,
MAX_UINT,
);

destToken.addBalance(testAccount.address, MAX_UINT);
destToken.addAllowance(
testAccount.address,
config.augustusRFQAddress,
MAX_UINT,
);

describe('Simpleswap', () => {
it('BUY USDC -> WBTC', async () => {
await newTestE2E({
config,
srcToken,
destToken,
senderAddress: GENERIC_ADDR1,
thirdPartyAddress: testAccount.address,
_amount: '1000000',
swapSide: SwapSide.BUY,
dexKey: dexKey,
contractMethod: ContractMethod.simpleBuy,
network: network,
sleepMs: 5000,
});
});
});
});

describe('GenericRFQ Q/B BUY', () => {
const srcToken = smartTokens.WBTC;
const destToken = smartTokens.USDC;

srcToken.addBalance(testAccount.address, MAX_UINT);
srcToken.addAllowance(
testAccount.address,
Expand All @@ -205,7 +244,7 @@ describe('GenericRFQ YOUR_NAME E2E Mainnet', () => {
);

describe('Simpleswap', () => {
it.only('BUY USDC -> WBTC', async () => {
it('BUY WBTC -> USDC', async () => {
await newTestE2E({
config,
srcToken,
Expand All @@ -222,4 +261,78 @@ describe('GenericRFQ YOUR_NAME E2E Mainnet', () => {
});
});
});

describe('GenericRFQ B/Q SELL', () => {
const srcToken = smartTokens.USDC;
const destToken = smartTokens.WBTC;

srcToken.addBalance(testAccount.address, MAX_UINT);
srcToken.addAllowance(
testAccount.address,
config.augustusRFQAddress,
MAX_UINT,
);

destToken.addBalance(testAccount.address, MAX_UINT);
destToken.addAllowance(
testAccount.address,
config.augustusRFQAddress,
MAX_UINT,
);

describe('Simpleswap', () => {
it('SELL USDC -> WBTC', async () => {
await newTestE2E({
config,
srcToken,
destToken,
senderAddress: GENERIC_ADDR1,
thirdPartyAddress: testAccount.address,
_amount: '1000000',
swapSide: SwapSide.SELL,
dexKey: dexKey,
contractMethod: ContractMethod.simpleSwap,
network: network,
sleepMs: 5000,
});
});
});
});

describe('GenericRFQ Q/B SELL', () => {
const srcToken = smartTokens.WBTC;
const destToken = smartTokens.USDC;

srcToken.addBalance(testAccount.address, MAX_UINT);
srcToken.addAllowance(
testAccount.address,
config.augustusRFQAddress,
MAX_UINT,
);

destToken.addBalance(testAccount.address, MAX_UINT);
destToken.addAllowance(
testAccount.address,
config.augustusRFQAddress,
MAX_UINT,
);

describe('Simpleswap', () => {
it('SELL WBTC -> USDC', async () => {
await newTestE2E({
config,
srcToken,
destToken,
senderAddress: GENERIC_ADDR1,
thirdPartyAddress: testAccount.address,
_amount: '10000',
swapSide: SwapSide.SELL,
dexKey: dexKey,
contractMethod: ContractMethod.simpleSwap,
network: network,
sleepMs: 5000,
});
});
});
});
});
60 changes: 59 additions & 1 deletion src/dex/generic-rfq/generic-rfq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import { BN_0, BN_1, getBigNumberPow } from '../../bignumber-constants';
import { ParaSwapLimitOrdersData } from '../paraswap-limit-orders/types';
import { ONE_ORDER_GASCOST } from '../paraswap-limit-orders/constant';
import { RateFetcher } from './rate-fetcher';
import { PriceAndAmountBigNumber, RFQConfig } from './types';
import {
PriceAndAmountBigNumber,
RFQConfig,
SlippageCheckError,
} from './types';
import { OptimalSwapExchange } from '@paraswap/core';
import { BI_MAX_UINT256 } from '../../bigint-constants';

Expand All @@ -25,6 +29,7 @@ export const overOrder = (amount: string, bps: number) =>
((BigInt(amount) * (BPS_MAX_VALUE + BigInt(bps))) / BPS_MAX_VALUE).toString();

export class GenericRFQ extends ParaSwapLimitOrders {
readonly isStatePollingDex = true;
private rateFetcher: RateFetcher;

public static dexKeysWithNetwork: { key: string; networks: Network[] }[] = [];
Expand Down Expand Up @@ -200,6 +205,50 @@ export class GenericRFQ extends ParaSwapLimitOrders {
const expiryAsBigInt = BigInt(order.order.expiry);
const minDeadline = expiryAsBigInt > 0 ? expiryAsBigInt : BI_MAX_UINT256;

const makerAssetAmount = BigInt(order.order.makerAmount);
const takerAssetAmount = BigInt(order.order.takerAmount);

const srcAmount = BigInt(optimalSwapExchange.srcAmount);
const destAmount = BigInt(optimalSwapExchange.destAmount);

const slippageFactor = options.slippageFactor;

if (side === SwapSide.SELL) {
const makerAssetAmountFilled =
takerAssetAmount > srcAmount
? (makerAssetAmount * srcAmount) / takerAssetAmount
: makerAssetAmount;

if (
makerAssetAmountFilled <
BigInt(
new BigNumber(destAmount.toString()).times(slippageFactor).toFixed(0),
)
) {
const message = `${this.dexKey}: too much slippage on quote ${side} makerAssetAmountFilled ${makerAssetAmountFilled} / destAmount ${destAmount} < ${slippageFactor}`;
this.logger.warn(message);
throw new SlippageCheckError(message);
}
} else {
if (makerAssetAmount < destAmount) {
// Won't receive enough assets
const message = `${this.dexKey}: too much slippage on quote ${side} makerAssetAmount ${makerAssetAmount} < destAmount ${destAmount}`;
this.logger.warn(message);
throw new SlippageCheckError(message);
} else {
if (
takerAssetAmount >
BigInt(slippageFactor.times(srcAmount.toString()).toFixed(0))
) {
const message = `${
this.dexKey
}: too much slippage on quote ${side} takerAssetAmount ${takerAssetAmount} / srcAmount ${srcAmount} > ${slippageFactor.toFixed()}`;
this.logger.warn(message);
throw new SlippageCheckError(message);
}
}
}

return [
{
...optimalSwapExchange,
Expand Down Expand Up @@ -232,4 +281,13 @@ export class GenericRFQ extends ParaSwapLimitOrders {
async isBlacklisted(userAddress: string): Promise<boolean> {
return this.rateFetcher.isBlackListed(userAddress);
}

async setBlacklist(userAddress: string): Promise<boolean> {
await this.dexHelper.cache.hset(
this.rateFetcher.blackListCacheKey,
userAddress.toLowerCase(),
'true',
);
return true;
}
}
23 changes: 16 additions & 7 deletions src/dex/generic-rfq/rate-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Fetcher from '../../lib/fetcher/fetcher';

import { Logger, Address, Token } from '../../types';
import { OrderInfo } from '../paraswap-limit-orders/types';
import { authHttp } from './security';
import {
BlackListResponse,
PairMap,
Expand All @@ -18,6 +17,7 @@ import {
RFQConfig,
RFQFirmRateResponse,
RFQPayload,
RFQSecret,
TokensResponse,
TokenWithInfo,
} from './types';
Expand All @@ -30,6 +30,9 @@ import {
tokensResponseValidator,
validateAndCast,
} from './validators';
import { genericRFQAuthHttp } from './security';

const GET_FIRM_RATE_TIMEOUT_MS = 2000;

export const reversePrice = (price: PriceAndAmountBigNumber) =>
[
Expand All @@ -49,14 +52,19 @@ export class RateFetcher {

private firmRateAuth?: (options: RequestConfig) => void;

private blackListCacheKey: string;
public blackListCacheKey: string;

private authHttp: (
secet: RFQSecret,
) => (options: RequestConfig) => RequestConfig;

constructor(
private dexHelper: IDexHelper,
private config: RFQConfig,
private dexKey: string,
private logger: Logger,
) {
this.authHttp = genericRFQAuthHttp(config.pathToRemove);
this.tokensFetcher = new Fetcher<TokensResponse>(
dexHelper.httpRequest,
{
Expand All @@ -68,7 +76,7 @@ export class RateFetcher {
tokensResponseValidator,
);
},
authenticate: authHttp(config.tokensConfig.secret),
authenticate: this.authHttp(config.tokensConfig.secret),
},
handler: this.handleTokensResponse.bind(this),
},
Expand All @@ -84,7 +92,7 @@ export class RateFetcher {
caster: (data: unknown) => {
return validateAndCast<PairsResponse>(data, pairsResponseValidator);
},
authenticate: authHttp(config.pairsConfig.secret),
authenticate: this.authHttp(config.pairsConfig.secret),
},
handler: this.handlePairsResponse.bind(this),
},
Expand All @@ -100,7 +108,7 @@ export class RateFetcher {
caster: (data: unknown) => {
return validateAndCast<RatesResponse>(data, pricesResponse);
},
authenticate: authHttp(config.rateConfig.secret),
authenticate: this.authHttp(config.rateConfig.secret),
},
handler: this.handleRatesResponse.bind(this),
},
Expand All @@ -120,7 +128,7 @@ export class RateFetcher {
blacklistResponseValidator,
);
},
authenticate: authHttp(config.rateConfig.secret),
authenticate: this.authHttp(config.rateConfig.secret),
},
handler: this.handleBlackListResponse.bind(this),
},
Expand All @@ -131,7 +139,7 @@ export class RateFetcher {

this.blackListCacheKey = `${this.dexHelper.config.data.network}_${this.dexKey}_blacklist`;
if (this.config.firmRateConfig.secret) {
this.firmRateAuth = authHttp(this.config.firmRateConfig.secret);
this.firmRateAuth = this.authHttp(this.config.firmRateConfig.secret);
}
}

Expand Down Expand Up @@ -367,6 +375,7 @@ export class RateFetcher {
let payload = {
data: _payload,
...this.config.firmRateConfig,
timeout: GET_FIRM_RATE_TIMEOUT_MS,
};

if (this.firmRateAuth) {
Expand Down
Loading

0 comments on commit b3fdf17

Please sign in to comment.