Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add swapToRatio endpoint #8

Merged
merged 21 commits into from
Nov 3, 2021
Merged

Add swapToRatio endpoint #8

merged 21 commits into from
Nov 3, 2021

Conversation

ewilz
Copy link
Member

@ewilz ewilz commented Oct 8, 2021

This PR includes some npm package updates to match smart-order-router sdk versions. I'm thinking to push those first in their own PR to separate out those updates from this work.

Todo:

  • DRY
  • Separate out sdk package updates into separate PR


const SUPPORTED_CHAINS: ChainId[] = [ ChainId.MAINNET, ChainId.RINKEBY ];

const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assuming it's the same list, this could be import DEFAULT_TOKEN_LIST from '@uniswap/default-token-list'; so it's more future-proof

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine with this since the list is never really updated

import { StaticGasPriceProvider } from '../router-entities/static-gas-price-provider';
import { QuoteToRatioQueryParams } from './schema/quote-to-ratio-schema';

const SUPPORTED_CHAINS: ChainId[] = [ ChainId.MAINNET, ChainId.RINKEBY ];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this intentially supporting a different set of chains than the quoter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so a lot of my PR right now is copy-paste, to get the endpoint working, then I will DRY all the shared code. I'm a bit fire-hosed right now, but a lot of this is actually @willpote 's code, so he might be able to answer these questions better.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quote endpoint on the API also only supports mainnet and rinkeby right now. We have a task to do arbitrary network support that will come soon

const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org';

export type ContainerDependencies = {
provider: ethers.providers.JsonRpcProvider;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does the provider need to be a jsonrpc as opposed to baseprovider?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does since we are using the EIP1559 gas provider that uses eth_feehistory

package.json Outdated
@@ -76,7 +76,7 @@
"@types/qs": "^6.9.7",
"@types/stats-lite": "^2.2.0",
"@uniswap/sdk-core": "^3.0.1",
"@uniswap/smart-order-router": "1.44.1",
"@uniswap/smart-order-router": "1.46.3",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should probably be ^1.46.3 so dependencies can be resolved better next time there's a conflict

tsconfig.json Outdated
@@ -12,7 +12,7 @@
"strictNullChecks": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": true /* Report errors on unused locals. */,
"noUnusedLocals": false /* Report errors on unused locals. */,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: don't merge this

Comment on lines 285 to 288
log.info('event information', {
event
})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need these logs?

import { StaticGasPriceProvider } from '../router-entities/static-gas-price-provider';
import { QuoteToRatioQueryParams } from './schema/quote-to-ratio-schema';

const SUPPORTED_CHAINS: ChainId[] = [ ChainId.MAINNET, ChainId.RINKEBY ];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quote endpoint on the API also only supports mainnet and rinkeby right now. We have a task to do arbitrary network support that will come soon

const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org';

export type ContainerDependencies = {
provider: ethers.providers.JsonRpcProvider;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does since we are using the EIP1559 gas provider that uses eth_feehistory


const SUPPORTED_CHAINS: ChainId[] = [ ChainId.MAINNET, ChainId.RINKEBY ];

const DEFAULT_TOKEN_LIST = 'https://gateway.ipfs.io/ipns/tokens.uniswap.org';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine with this since the list is never really updated

Comment on lines 33 to 35
deadline: '360',
errorTolerance: 1,
maxIterations: 6,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indenting looks dodgy

jest.config.js Outdated Show resolved Hide resolved
@@ -0,0 +1,66 @@
import { AlphaRouterConfig } from '@uniswap/smart-order-router';
Copy link
Member Author

@ewilz ewilz Nov 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm open to ideas on where to put the two shared items below

@ewilz ewilz marked this pull request as ready for review November 2, 2021 20:38
successfully outsourced a few types to a shared injector

create injectorSOR

get rid of unused dependencies

DRYing handlers
jest.config.js Outdated Show resolved Hide resolved
token0.wrapped,
token1.wrapped,
feeAmount
) as unknown as Pool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The casting shouldn't be needed, any idea whats going on?

log.error(
`Could not find pool.`
);
return { statusCode: 400, errorCode: 'Could not find pool.' };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error code should be something like POOL_NOT_FOUND. You can use detail field for 'Could not find pool'

pool,
tickLower,
tickUpper,
liquidity: 1,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does setting liquidity to 1 effect anything?

In any case, feels like we should probably use: https://github.com/Uniswap/v3-sdk/blob/main/src/entities/position.ts#L312-L392

to get the correct liquidity value

Copy link
Member Author

@ewilz ewilz Nov 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm...it's weird because liquidity plays absolutely no role in any calculation. we define a position to get the bounds, in many cases this will be a hypothetical position with no liquidity yet (which we would then go to create with the swap and add amounts which we don't know yet.

Comment on lines 180 to 205
log.info(
{
token0: token0.symbol,
token1: token1.symbol,
routingConfig: routingConfig,
},
`Swap to ratio - token0: ${
token0.symbol
}, token0Balance: ${
token0Balance
}, token1: ${
token1.symbol
}. token1Balance: ${
token1Balance
}, Chain: ${chainId}`
);

log.info({
token0Balance,
token1Balance,
position,
maxIterations,
errorTolerance: errorToleranceFraction.toFixed(4),
swapParams,
routingConfig,
}, 'more useful logs')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you merge these? Best to minimize number of logs

numerator: Joi.string(),
denominator: Joi.string(),
}).required(),
postSwapTargetPool: Joi.any().required(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing validation

import { QuoteToRatioQueryParams } from './schema/quote-to-ratio-schema';
import { ContainerInjected, InjectorSOR, RequestInjected } from '../injector-sor';

export class QuoteToRatioHandlerInjector extends InjectorSOR<ISwapToRatio<any, any>, QuoteToRatioQueryParams> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point I think it makes sense to tie down our types to specific implementations i.e. ISwapToRatio<RoutingConfig, SwapAndAddConfig>

This way we can get type checking in this file


export class QuoteToRatioHandler extends APIGLambdaHandler<
ContainerInjected,
RequestInjected<ISwapToRatio<any, any>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above


export class QuoteHandler extends APIGLambdaHandler<
ContainerInjected,
RequestInjected,
RequestInjected<IRouter<any>>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

return new Fraction(JSBI.BigInt(fraction.numerator), JSBI.BigInt(fraction.denominator))
}

describe('quote-to-ratio', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get some 4xx failure case tests?

Good to test some of the basic validation cases just to check that validation is hooked up (e.g. incorrect address returns 4xx etc.), as well as cases where we don't find a swap? (maybe we can set maxIterations to 0 or 1? or maybe passing in token0Balance = 0 and token1Balance = 0?)

Also what happens if I want to do a range order, but I already have 100% of the token required and 0 of the token not required? Do we still recommend a swap? Do we return 200 or 4xx in that case?

@ewilz ewilz merged commit 8dec90a into main Nov 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants