Skip to content

Commit

Permalink
Merge pull request #14 from uniswap-integration/feature/gas-included-…
Browse files Browse the repository at this point in the history
…in-quotes

Gas estimates are included in quotes if enabled
  • Loading branch information
joshstevens19 committed Aug 4, 2021
2 parents d21368f + 853c304 commit 43310c9
Show file tree
Hide file tree
Showing 25 changed files with 2,061 additions and 1,769 deletions.
69 changes: 69 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Please note this is not owned or maintained by uniswap and is a open source pack
<br/>
🚀 Exposes all the route paths it tried so you can see every detail in how it worked out the best price
<br/>
🚀 Factor in the cost of the transaction into the quotes with 1 config change
<br/>
🚀 Easy subscriptions to get alerted when the price moves or the trade expires
<br/>
🚀 The transaction is generated for you, just fill it with the gas details and send it on its way
Expand Down Expand Up @@ -106,21 +108,28 @@ export interface UniswapPairContextForProviderUrl
```
```ts
export interface GasSettings {
getGasPrice: () => Promise<number>;
}

export class UniswapPairSettings {
slippage: number;
deadlineMinutes: number;
disableMultihops: boolean;
uniswapVersions: UniswapVersion[] = [UniswapVersion.v2, UniswapVersion.v3];
gasSettings?: GasSettings = undefined;

constructor(settings?: {
slippage?: number | undefined;
deadlineMinutes?: number | undefined;
disableMultihops?: boolean | undefined;
uniswapVersions?: UniswapVersion[] | undefined;
gasSettings?: GasSettings | undefined;
}) {
this.slippage = settings?.slippage || 0.005;
this.deadlineMinutes = settings?.deadlineMinutes || 20;
this.disableMultihops = settings?.disableMultihops || false;
this.gasSettings = settings?.gasSettings;

if (
Array.isArray(settings?.uniswapVersions) &&
Expand Down Expand Up @@ -390,11 +399,19 @@ export interface TradeContext {
// this will be ordered from the best expected convert quote to worse [0] = best
allTriedRoutesQuotes: {
expectedConvertQuote: string;
expectedConvertQuoteOrTokenAmountInMaxWithSlippage: string;
transaction: Transaction;
// if you have enabled to factor in the transaction cost in the quotes
// then this is the gas price in gwei we used to estimate the transactions
// it only be defined by the ones it decided to pick depending on the hops abouts
gasPriceEstimatedBy: string | undefined;
tradeExpires: number;
routePathArrayTokenMap: Token[];
routeText: string;
routePathArray: string[];
uniswapVersion: UniswapVersion;
liquidityProviderFee: number;
quoteDirection: TradeDirection;
}[];
// if the allowance approved for moving tokens is below the amount sending to the
// uniswap router this will be false if not true
Expand Down Expand Up @@ -438,6 +455,9 @@ export interface TradeContext {
data: string;
value: string;
};
// if you have enabled to factor in the transaction cost in the quotes
// then this is the gas price in gwei we used to estimate the transactions
gasPriceEstimatedBy: string | undefined;
// this is a stream which emits if the quote has changed, this will emit
// not matter what you should listen to this for the source of truth
// for a reactive dApp. If you dont listen to this the user could end up
Expand Down Expand Up @@ -724,6 +744,55 @@ const executeTrade = async (web3: Web3, trade: TradeContext) => {
web3TradeExample();
```
#### Including gas fees in the trade response
The library has the ability to work out the best trade including gas fees. As expected this does add around about 700MS onto the response time due to the need to have to query `eth_estimateGas` an the top 3 quotes to work out the best result. How it works is:
- It gets the best expected trade quotes as it normally does
- IF you do not have enough balance or enough allowance it will not estimate gas because it be a always failing transaction and the node will throw an error.
- ALSO IF the token your swapping does not have a fiat price in coin gecko then again it ignores the below as it can not do the math without a base currency.
- IF you have enough balance and allowance then finds the best 3 of the different hop options:
- best direct trade aka `ETH/TOKEN > TOKEN_YOU_WANT`
- best trade which jumps 2 hops aka `ETH/TOKEN > TOKEN > TOKEN_YOU_WANT`
- beat trade which jumps 3 hops aka `ETH/TOKEN > TOKEN > OTHER_TOKEN > TOKEN_YOU_WANT`
- It then `eth_estimateGas` those 3 transactions and takes off the tx fee from the expected quote
- It then returns the trade which is the highest left amount, meaning it has taken into consideration gas within the quote
Do not worry if you want to use this feature but worried that first time customers before they approve ability for uniswap to move the tokens will not be able to benefit from this, as soon as you have approved uniswap to be able to move tokens on their behalf a new trade will be emitted within the `quoteChanged$` stream so you can still get all the benefit on first time swaps.
The beauty of this is its very easy to setup just pass in a `gasSettings` object including a `getGasPrice` async function (IT MUST BE A PROMISE) which returns the gas price in `Gwei` which you want to use for the working out. This must be a string number aka `30` = `30 Gwei` it does not handle passing in hex strings. This can be dynamic aka we call this everytime we go and work out the trades, so if you want this to hit an API or etherscan or return a fixed gas price, its completely up to you.
```ts
import {
ChainId,
TradeContext,
UniswapPair,
UniswapPairSettings,
} from 'simple-uniswap-sdk';
const uniswapPair = new UniswapPair({
// the contract address of the token you want to convert FROM
fromTokenContractAddress: '0x419D0d8BdD9aF5e606Ae2232ed285Aff190E711b',
// the contract address of the token you want to convert TO
toTokenContractAddress: '0x1985365e9f78359a9B6AD760e32412f4a445E862',
// the ethereum address of the user using this part of the dApp
ethereumAddress: '0xB1E6079212888f0bE0cf55874B2EB9d7a5e02cD9',
// you can pass in the provider url as well if you want
// providerUrl: YOUR_PROVIDER_URL,
// OR if you want to inject your own ethereum provider (no need for chainId if so)
// ethereumProvider: YOUR_WEB3_ETHERS_OR_CUSTOM_ETHEREUM_PROVIDER,
chainId: ChainId.RINKEBY,
settings: new UniswapPairSettings({
gasSettings: {
getGasPrice: async () => {
return 'GWEI_GAS_PRICE';
},
},
}),
});
```
That's it now you get trades which bring you back the best trades minus the tx cost.
#### ERC20 > ERC20 Output example
```ts
Expand Down
Loading

0 comments on commit 43310c9

Please sign in to comment.