Skip to content

Commit

Permalink
feat: Added UniSwap Autoroutes to dashboard (#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
valiafetisov authored Oct 19, 2022
1 parent 1fff788 commit bf702c4
Show file tree
Hide file tree
Showing 8 changed files with 866 additions and 85 deletions.
826 changes: 742 additions & 84 deletions core/package-lock.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"dependencies": {
"@nomiclabs/hardhat-ethers": "^2.1.0",
"@uniswap/sdk": "^3.0.3",
"@uniswap/smart-order-router": "^2.10.0",
"bignumber.js": "^9.0.1",
"date-fns": "^2.28.0",
"deep-equal-in-any-order": "^2.0.0",
Expand All @@ -41,6 +42,8 @@
"devDependencies": {
"@ava/typescript": "^1.1.1",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@types/async-retry": "^1.4.5",
"@types/bunyan": "^1.8.8",
"@types/deep-equal-in-any-order": "^1.0.1",
"@types/memoizee": "^0.4.7",
"@types/mocha": "^9.1.1",
Expand Down
74 changes: 74 additions & 0 deletions core/src/calleeFunctions/helpers/uniswapAutoRouter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { AlphaRouter } from '@uniswap/smart-order-router';
import { Token, Percent, TradeType, CurrencyAmount } from '@uniswap/sdk-core';
import BigNumber from '../../bignumber';
import getProvider from '../../provider';
import { getDecimalChainIdByNetworkType } from '../../network';
import { getTokenAddressByNetworkAndSymbol, getTokenDecimalsBySymbol } from '../../tokens';
import { getCollateralConfigBySymbol } from '../../constants/COLLATERALS';

const getUniswapTokenBySymbol = async function (network: string, symbol: string): Promise<Token> {
const tokenAddress = await getTokenAddressByNetworkAndSymbol(network, symbol);
const tokenDecimals = getTokenDecimalsBySymbol(symbol);
const decimalChainId = getDecimalChainIdByNetworkType(network);
return new Token(decimalChainId, tokenAddress, tokenDecimals, symbol);
};

export const getUniswapAutoRoute = async function (
network: string,
collateralSymbol: string,
inputAmount: string | number = 1,
walletAddress?: string
) {
const collateralConfig = getCollateralConfigBySymbol(collateralSymbol);
const provider = await getProvider(network);
const router = new AlphaRouter({ chainId: 1, provider });
const inputToken = await getUniswapTokenBySymbol(network, collateralConfig.symbol);
const outputToken = await getUniswapTokenBySymbol(network, 'DAI');

const inputAmountInteger = new BigNumber(inputAmount).shiftedBy(collateralConfig.decimals).toFixed(0);
const inputAmountWithCurrency = CurrencyAmount.fromRawAmount(inputToken, inputAmountInteger);

// get auto route
const route = await router.route(
inputAmountWithCurrency,
outputToken,
TradeType.EXACT_INPUT,
{
recipient: walletAddress || '0x000000000000000000000000000000000000dEaD', // use given address or "dead" address as fallback
slippageTolerance: new Percent(10, 100),
deadline: Math.floor(Date.now() / 1000 + 1800),
},
{
maxSplits: 0,
}
);
if (!route) {
throw new Error(`Could not get auto route for collateral "${collateralSymbol}".`);
}
return route;
};

export const fetchAutoRouteInformation = async function (
network: string,
collateralSymbol: string,
inputAmount: string | number = 1,
walletAddress?: string
) {
try {
const token = await getUniswapTokenBySymbol(network, collateralSymbol);
const autoRouteData = await getUniswapAutoRoute(network, collateralSymbol, inputAmount, walletAddress);
const routes = autoRouteData.route[0].tokenPath.map(p => p.symbol);

return {
totalPrice: new BigNumber(autoRouteData.quote.toFixed(token.decimals)),
routes,
errorMessage: undefined,
};
} catch (error: any) {
return {
totalPrice: undefined,
routes: undefined,
errorMessage: error.toString(),
};
}
};
3 changes: 3 additions & 0 deletions core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export declare interface CollateralRow extends CollateralConfig, Partial<MakerPa
marketUnitPrice?: BigNumber | string;
tokenAddress?: string;
tokenAddressError?: string;
autoRouteQuote?: BigNumber;
autoRouteExchanges?: string[];
autoRouteError?: string;
}

export declare interface AuctionTransaction extends Auction, TransactionFees {
Expand Down
35 changes: 35 additions & 0 deletions frontend/components/dashboard/CollateralTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,31 @@
</Popover>
</div>
</div>
<div
slot="autoRouteQuote"
slot-scope="autoRouteQuote, record"
class="Element"
:class="{ Loading: isLoading(record) }"
>
<FormatCurrency v-if="!record.autoRouteError && autoRouteQuote" :value="autoRouteQuote" currency="DAI" />
<div v-else-if="record.autoRouteError">
<Popover placement="topLeft" :content="record.autoRouteError" trigger="hover">
<p class="inline-block w-48 text-red-500 truncate">
<span>{{ record.autoRouteError }}</span>
</p>
</Popover>
</div>
</div>
<div
slot="autoRouteExchanges"
slot-scope="autoRouteExchanges, record"
class="Element"
:class="{ Loading: isLoading(record) }"
>
<div v-if="autoRouteExchanges">
{{ autoRouteExchanges.join(', ') }}
</div>
</div>
<div
slot="secondsBetweenPriceDrops"
slot-scope="secondsBetweenPriceDrops, record"
Expand Down Expand Up @@ -132,6 +157,16 @@ export default Vue.extend({
dataIndex: 'marketUnitPrice',
scopedSlots: { customRender: 'marketUnitPrice' },
},
{
title: 'UniV3 Auto Route Quote',
dataIndex: 'autoRouteQuote',
scopedSlots: { customRender: 'autoRouteQuote' },
},
{
title: 'UniV3 Auto Route Exchanges',
dataIndex: 'autoRouteExchanges',
scopedSlots: { customRender: 'autoRouteExchanges' },
},
{
title: 'Step',
dataIndex: 'secondsBetweenPriceDrops',
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/dashboard/DashboardAuctionsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
auction price and the price for the collateral on another marketplace.
</TextBlock>
</div>
<div class="Block max-w-screen-lg">
<div class="Block max-w-screen-xl">
<CollateralTable :collaterals="collaterals" class="overflow-x-auto" />
</div>
<div class="Block space-y-4 md:space-y-8 max-w-screen-sm">
Expand Down
2 changes: 2 additions & 0 deletions frontend/helpers/generateFakeCollateral.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const generateFakeCollaterals = function () {
secondsBetweenPriceDrops: faker.datatype.number(120),
priceDropRatio: new BigNumber(faker.datatype.number({ min: 0.5, max: 1, precision: 0.0001 })),
tokenAddress: faker.finance.ethereumAddress(),
autoRouteQuote: new BigNumber(faker.finance.amount()),
autoRouteExchanges: [faker.lorem.word(), faker.lorem.word()],
});
}
return collaterals;
Expand Down
6 changes: 6 additions & 0 deletions frontend/store/collaterals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { getMarketPrice } from 'auctions-core/src/calleeFunctions';
import { fetchCalcParametersByCollateralType } from 'auctions-core/src/params';
import { getTokenAddressByNetworkAndSymbol } from 'auctions-core/src/tokens';
import { isCollateralTypeSupported } from 'auctions-core/src/addresses';
import { fetchAutoRouteInformation } from 'auctions-core/src/calleeFunctions/helpers/uniswapAutoRouter';

interface State {
collaterals: CollateralRow[];
Expand Down Expand Up @@ -98,12 +99,17 @@ export const actions = {
priceDropRatio: error.toString(),
};
});
const autoRouteData = await fetchAutoRouteInformation(network, collateral.symbol);

const updated = {
ilk: collateral.ilk,
marketUnitPrice,
secondsBetweenPriceDrops: calcParameters.secondsBetweenPriceDrops,
priceDropRatio: calcParameters.priceDropRatio,
tokenAddress,
autoRouteQuote: autoRouteData.totalPrice,
autoRouteExchanges: autoRouteData.routes,
autoRouteError: autoRouteData.errorMessage,
};
commit('updateCollateral', updated);
}
Expand Down

0 comments on commit bf702c4

Please sign in to comment.