This repository has been archived by the owner on Apr 25, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathrouter.ts
146 lines (136 loc) · 5.06 KB
/
router.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import { Token, Currency, CurrencyAmount, Percent, TradeType, validateAndParseAddress } from '@uniswap/sdk-core'
import { Trade } from './entities'
import invariant from 'tiny-invariant'
/**
* Options for producing the arguments to send call to the router.
*/
export interface TradeOptions {
/**
* How much the execution price is allowed to move unfavorably from the trade execution price.
*/
allowedSlippage: Percent
/**
* How long the swap is valid until it expires, in seconds.
* This will be used to produce a `deadline` parameter which is computed from when the swap call parameters
* are generated.
*/
ttl: number
/**
* The account that should receive the output of the swap.
*/
recipient: string
/**
* Whether any of the tokens in the path are fee on transfer tokens, which should be handled with special methods
*/
feeOnTransfer?: boolean
}
export interface TradeOptionsDeadline extends Omit<TradeOptions, 'ttl'> {
/**
* When the transaction expires.
* This is an atlernate to specifying the ttl, for when you do not want to use local time.
*/
deadline: number
}
/**
* The parameters to use in the call to the Uniswap V2 Router to execute a trade.
*/
export interface SwapParameters {
/**
* The method to call on the Uniswap V2 Router.
*/
methodName: string
/**
* The arguments to pass to the method, all hex encoded.
*/
args: (string | string[])[]
/**
* The amount of wei to send in hex.
*/
value: string
}
function toHex(currencyAmount: CurrencyAmount<Currency>) {
return `0x${currencyAmount.quotient.toString(16)}`
}
const ZERO_HEX = '0x0'
/**
* Represents the Uniswap V2 Router, and has static methods for helping execute trades.
*/
export abstract class Router {
/**
* Cannot be constructed.
*/
private constructor() {}
/**
* Produces the on-chain method name to call and the hex encoded parameters to pass as arguments for a given trade.
* @param trade to produce call parameters for
* @param options options for the call parameters
*/
public static swapCallParameters(
trade: Trade<Currency, Currency, TradeType>,
options: TradeOptions | TradeOptionsDeadline
): SwapParameters {
const etherIn = trade.inputAmount.currency.isNative
const etherOut = trade.outputAmount.currency.isNative
// the router does not support both ether in and out
invariant(!(etherIn && etherOut), 'ETHER_IN_OUT')
invariant(!('ttl' in options) || options.ttl > 0, 'TTL')
const to: string = validateAndParseAddress(options.recipient)
const amountIn: string = toHex(trade.maximumAmountIn(options.allowedSlippage))
const amountOut: string = toHex(trade.minimumAmountOut(options.allowedSlippage))
const path: string[] = trade.route.path.map((token: Token) => token.address)
const deadline =
'ttl' in options
? `0x${(Math.floor(new Date().getTime() / 1000) + options.ttl).toString(16)}`
: `0x${options.deadline.toString(16)}`
const useFeeOnTransfer = Boolean(options.feeOnTransfer)
let methodName: string
let args: (string | string[])[]
let value: string
switch (trade.tradeType) {
case TradeType.EXACT_INPUT:
if (etherIn) {
methodName = useFeeOnTransfer ? 'swapExactETHForTokensSupportingFeeOnTransferTokens' : 'swapExactETHForTokens'
// (uint amountOutMin, address[] calldata path, address to, uint deadline)
args = [amountOut, path, to, deadline]
value = amountIn
} else if (etherOut) {
methodName = useFeeOnTransfer ? 'swapExactTokensForETHSupportingFeeOnTransferTokens' : 'swapExactTokensForETH'
// (uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
args = [amountIn, amountOut, path, to, deadline]
value = ZERO_HEX
} else {
methodName = useFeeOnTransfer
? 'swapExactTokensForTokensSupportingFeeOnTransferTokens'
: 'swapExactTokensForTokens'
// (uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
args = [amountIn, amountOut, path, to, deadline]
value = ZERO_HEX
}
break
case TradeType.EXACT_OUTPUT:
invariant(!useFeeOnTransfer, 'EXACT_OUT_FOT')
if (etherIn) {
methodName = 'swapETHForExactTokens'
// (uint amountOut, address[] calldata path, address to, uint deadline)
args = [amountOut, path, to, deadline]
value = amountIn
} else if (etherOut) {
methodName = 'swapTokensForExactETH'
// (uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
args = [amountOut, amountIn, path, to, deadline]
value = ZERO_HEX
} else {
methodName = 'swapTokensForExactTokens'
// (uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
args = [amountOut, amountIn, path, to, deadline]
value = ZERO_HEX
}
break
}
return {
methodName,
args,
value
}
}
}