Skip to content

Commit 5fdbf52

Browse files
snreynoldsNoahZinsmeisterlint-action
authored
Initial trade and route tests (Uniswap#6)
* some initial route and trade tests * more tests * adding tests for min/maxAmount, executionPrice, and priceImpact * make cast a bit better * Fix code style issues with Prettier Co-authored-by: Noah Zinsmeister <[email protected]> Co-authored-by: Lint Action <[email protected]>
1 parent d7d7973 commit 5fdbf52

File tree

4 files changed

+1193
-5
lines changed

4 files changed

+1193
-5
lines changed

src/entities/route.test.ts

+240
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
import { Ether, Token, WETH9, CurrencyAmount } from '@uniswap/sdk-core'
2+
import { Route as V3RouteSDK, Pool, FeeAmount, TickMath, encodeSqrtRatioX96 } from '@uniswap/v3-sdk'
3+
import { RouteV3 } from './route'
4+
import { Protocol } from './protocol'
5+
import { Route as V2RouteSDK, Pair } from '@uniswap/v2-sdk'
6+
import { RouteV2 } from './route'
7+
8+
describe('RouteV3', () => {
9+
const ETHER = Ether.onChain(1)
10+
const token0 = new Token(1, '0x0000000000000000000000000000000000000001', 18, 't0')
11+
const token1 = new Token(1, '0x0000000000000000000000000000000000000002', 18, 't1')
12+
const token2 = new Token(1, '0x0000000000000000000000000000000000000003', 18, 't2')
13+
const weth = WETH9[1]
14+
15+
const pool_0_1 = new Pool(token0, token1, FeeAmount.MEDIUM, encodeSqrtRatioX96(1, 1), 0, 0, [])
16+
const pool_0_weth = new Pool(token0, weth, FeeAmount.MEDIUM, encodeSqrtRatioX96(1, 1), 0, 0, [])
17+
const pool_1_weth = new Pool(token1, weth, FeeAmount.MEDIUM, encodeSqrtRatioX96(1, 1), 0, 0, [])
18+
19+
describe('path', () => {
20+
it('wraps original v3 route object and successfully constructs a path from the tokens', () => {
21+
const routeOriginal = new V3RouteSDK([pool_0_1], token0, token1)
22+
const route = new RouteV3(routeOriginal)
23+
expect(route.pools).toEqual([pool_0_1])
24+
expect(route.tokenPath).toEqual([token0, token1])
25+
expect(route.input).toEqual(token0)
26+
expect(route.output).toEqual(token1)
27+
expect(route.chainId).toEqual(1)
28+
})
29+
})
30+
31+
it('successfully assigns the protocol', () => {
32+
const routeOriginal = new V3RouteSDK([pool_0_1], token0, token1)
33+
const route = new RouteV3(routeOriginal)
34+
expect(route.protocol).toEqual(Protocol.V3)
35+
})
36+
37+
it('inherits parameters from extended route class', () => {
38+
const routeOriginal = new V3RouteSDK([pool_0_1], token0, token1)
39+
const route = new RouteV3(routeOriginal)
40+
expect(route.pools).toEqual(routeOriginal.pools)
41+
expect(route.path).toEqual(routeOriginal.tokenPath)
42+
expect(route.input).toEqual(routeOriginal.input)
43+
expect(route.output).toEqual(routeOriginal.output)
44+
expect(route.midPrice).toEqual(routeOriginal.midPrice)
45+
expect(route.chainId).toEqual(routeOriginal.chainId)
46+
})
47+
48+
it('can have a token as both input and output', () => {
49+
const routeOriginal = new V3RouteSDK([pool_0_weth, pool_0_1, pool_1_weth], weth, weth)
50+
const route = new RouteV3(routeOriginal)
51+
expect(route.pools).toEqual([pool_0_weth, pool_0_1, pool_1_weth])
52+
expect(route.input).toEqual(weth)
53+
expect(route.output).toEqual(weth)
54+
})
55+
56+
it('supports ether input', () => {
57+
const routeOriginal = new V3RouteSDK([pool_0_weth], ETHER, token0)
58+
const route = new RouteV3(routeOriginal)
59+
expect(route.pools).toEqual([pool_0_weth])
60+
expect(route.input).toEqual(ETHER)
61+
expect(route.output).toEqual(token0)
62+
})
63+
64+
it('supports ether output', () => {
65+
const routeOriginal = new V3RouteSDK([pool_0_weth], token0, ETHER)
66+
const route = new RouteV3(routeOriginal)
67+
expect(route.pools).toEqual([pool_0_weth])
68+
expect(route.input).toEqual(token0)
69+
expect(route.output).toEqual(ETHER)
70+
})
71+
72+
describe('#midPrice', () => {
73+
const pool_0_1 = new Pool(
74+
token0,
75+
token1,
76+
FeeAmount.MEDIUM,
77+
encodeSqrtRatioX96(1, 5),
78+
0,
79+
TickMath.getTickAtSqrtRatio(encodeSqrtRatioX96(1, 5)),
80+
[]
81+
)
82+
const pool_1_2 = new Pool(
83+
token1,
84+
token2,
85+
FeeAmount.MEDIUM,
86+
encodeSqrtRatioX96(15, 30),
87+
0,
88+
TickMath.getTickAtSqrtRatio(encodeSqrtRatioX96(15, 30)),
89+
[]
90+
)
91+
const pool_0_weth = new Pool(
92+
token0,
93+
weth,
94+
FeeAmount.MEDIUM,
95+
encodeSqrtRatioX96(3, 1),
96+
0,
97+
TickMath.getTickAtSqrtRatio(encodeSqrtRatioX96(3, 1)),
98+
[]
99+
)
100+
const pool_1_weth = new Pool(
101+
token1,
102+
weth,
103+
FeeAmount.MEDIUM,
104+
encodeSqrtRatioX96(1, 7),
105+
0,
106+
TickMath.getTickAtSqrtRatio(encodeSqrtRatioX96(1, 7)),
107+
[]
108+
)
109+
110+
it('correct for 0 -> 1', () => {
111+
const routeOriginal = new V3RouteSDK([pool_0_1], token0, token1)
112+
const price = new RouteV3(routeOriginal).midPrice
113+
expect(price.toFixed(4)).toEqual('0.2000')
114+
expect(price.baseCurrency.equals(token0)).toEqual(true)
115+
expect(price.quoteCurrency.equals(token1)).toEqual(true)
116+
})
117+
118+
it('is cached', () => {
119+
const routeOriginal = new V3RouteSDK([pool_0_1], token0, token1)
120+
const route = new RouteV3(routeOriginal)
121+
expect(route.midPrice).toStrictEqual(route.midPrice)
122+
})
123+
124+
it('correct for 1 -> 0', () => {
125+
const routeOriginal = new V3RouteSDK([pool_0_1], token1, token0)
126+
const price = new RouteV3(routeOriginal).midPrice
127+
expect(price.toFixed(4)).toEqual('5.0000')
128+
expect(price.baseCurrency.equals(token1)).toEqual(true)
129+
expect(price.quoteCurrency.equals(token0)).toEqual(true)
130+
})
131+
132+
it('correct for 0 -> 1 -> 2', () => {
133+
const routeOriginal = new V3RouteSDK([pool_0_1, pool_1_2], token0, token2)
134+
const price = new RouteV3(routeOriginal).midPrice
135+
expect(price.toFixed(4)).toEqual('0.1000')
136+
expect(price.baseCurrency.equals(token0)).toEqual(true)
137+
expect(price.quoteCurrency.equals(token2)).toEqual(true)
138+
})
139+
140+
it('correct for 2 -> 1 -> 0', () => {
141+
const routeOriginal = new V3RouteSDK([pool_1_2, pool_0_1], token2, token0)
142+
const price = new RouteV3(routeOriginal).midPrice
143+
expect(price.toFixed(4)).toEqual('10.0000')
144+
expect(price.baseCurrency.equals(token2)).toEqual(true)
145+
expect(price.quoteCurrency.equals(token0)).toEqual(true)
146+
})
147+
148+
it('correct for ether -> 0', () => {
149+
const routeOriginal = new V3RouteSDK([pool_0_weth], ETHER, token0)
150+
const price = new RouteV3(routeOriginal).midPrice
151+
expect(price.toFixed(4)).toEqual('0.3333')
152+
expect(price.baseCurrency.equals(ETHER)).toEqual(true)
153+
expect(price.quoteCurrency.equals(token0)).toEqual(true)
154+
})
155+
156+
it('correct for 1 -> weth', () => {
157+
const price = new V3RouteSDK([pool_1_weth], token1, weth).midPrice
158+
expect(price.toFixed(4)).toEqual('0.1429')
159+
expect(price.baseCurrency.equals(token1)).toEqual(true)
160+
expect(price.quoteCurrency.equals(weth)).toEqual(true)
161+
})
162+
163+
it('correct for ether -> 0 -> 1 -> weth', () => {
164+
const routeOriginal = new V3RouteSDK([pool_0_weth, pool_0_1, pool_1_weth], ETHER, weth)
165+
const price = new RouteV3(routeOriginal).midPrice
166+
expect(price.toSignificant(4)).toEqual('0.009524')
167+
expect(price.baseCurrency.equals(ETHER)).toEqual(true)
168+
expect(price.quoteCurrency.equals(weth)).toEqual(true)
169+
})
170+
171+
it('correct for weth -> 0 -> 1 -> ether', () => {
172+
const routeOriginal = new V3RouteSDK([pool_0_weth, pool_0_1, pool_1_weth], weth, ETHER)
173+
const price = new RouteV3(routeOriginal).midPrice
174+
expect(price.toSignificant(4)).toEqual('0.009524')
175+
expect(price.baseCurrency.equals(weth)).toEqual(true)
176+
expect(price.quoteCurrency.equals(ETHER)).toEqual(true)
177+
})
178+
})
179+
})
180+
181+
describe('RouteV2', () => {
182+
const ETHER = Ether.onChain(1)
183+
const token0 = new Token(1, '0x0000000000000000000000000000000000000001', 18, 't0')
184+
const token1 = new Token(1, '0x0000000000000000000000000000000000000002', 18, 't1')
185+
const weth = WETH9[1]
186+
const pair_0_1 = new Pair(CurrencyAmount.fromRawAmount(token0, '100'), CurrencyAmount.fromRawAmount(token1, '200'))
187+
const pair_0_weth = new Pair(CurrencyAmount.fromRawAmount(token0, '100'), CurrencyAmount.fromRawAmount(weth, '100'))
188+
const pair_1_weth = new Pair(CurrencyAmount.fromRawAmount(token1, '175'), CurrencyAmount.fromRawAmount(weth, '100'))
189+
190+
it('successfully assigns the protocol', () => {
191+
const routeOriginal = new V2RouteSDK([pair_0_1], token0, token1)
192+
const route = new RouteV2(routeOriginal)
193+
expect(route.protocol).toEqual(Protocol.V2)
194+
})
195+
196+
it('inherits parameters from extended route class', () => {
197+
const routeOriginal = new V2RouteSDK([pair_0_1], token0, token1)
198+
const route = new RouteV2(routeOriginal)
199+
expect(route.pools).toEqual(routeOriginal.pairs)
200+
expect(route.path).toEqual(routeOriginal.path)
201+
expect(route.input).toEqual(routeOriginal.input)
202+
expect(route.output).toEqual(routeOriginal.output)
203+
expect(route.midPrice).toEqual(routeOriginal.midPrice)
204+
expect(route.chainId).toEqual(routeOriginal.chainId)
205+
})
206+
207+
it('constructs a path from the tokens', () => {
208+
const routeOriginal = new V2RouteSDK([pair_0_1], token0, token1)
209+
const route = new RouteV2(routeOriginal)
210+
expect(route.pairs).toEqual([pair_0_1])
211+
expect(route.path).toEqual([token0, token1])
212+
expect(route.input).toEqual(token0)
213+
expect(route.output).toEqual(token1)
214+
expect(route.chainId).toEqual(1)
215+
})
216+
217+
it('can have a token as both input and output', () => {
218+
const routeOriginal = new V2RouteSDK([pair_0_weth, pair_0_1, pair_1_weth], weth, weth)
219+
const route = new RouteV2(routeOriginal)
220+
expect(route.pairs).toEqual([pair_0_weth, pair_0_1, pair_1_weth])
221+
expect(route.input).toEqual(weth)
222+
expect(route.output).toEqual(weth)
223+
})
224+
225+
it('supports ether input', () => {
226+
const routeOriginal = new V2RouteSDK([pair_0_weth], ETHER, token0)
227+
const route = new RouteV2(routeOriginal)
228+
expect(route.pairs).toEqual([pair_0_weth])
229+
expect(route.input).toEqual(ETHER)
230+
expect(route.output).toEqual(token0)
231+
})
232+
233+
it('supports ether output', () => {
234+
const routeOriginal = new V2RouteSDK([pair_0_weth], token0, ETHER)
235+
const route = new RouteV2(routeOriginal)
236+
expect(route.pairs).toEqual([pair_0_weth])
237+
expect(route.input).toEqual(token0)
238+
expect(route.output).toEqual(ETHER)
239+
})
240+
})

src/entities/route.ts

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export interface IRoute<TInput extends Currency, TOutput extends Currency, TPool
99
pools: TPool[]
1010
path: Token[]
1111
midPrice: Price<TInput, TOutput>
12+
input: TInput
13+
output: TOutput
1214
}
1315

1416
// V2 route wrapper

0 commit comments

Comments
 (0)