-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathkeepMarketPriceOrder.ts
191 lines (174 loc) · 6.05 KB
/
keepMarketPriceOrder.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import { ethers, BigNumber, Wallet } from 'ethers'
import dotenv from'dotenv'
import axios from 'axios'
import crypto from 'crypto'
import BN from 'bignumber.js'
import { _TypedDataEncoder } from 'ethers/lib/utils'
dotenv.config()
const chainId = 5
const providerUrl = process.env.JSON_RPC_PROVIDER
const makerPrivateKey = process.env.TEST_MAKER_PRIVATE_KEY
const provider = new ethers.providers.JsonRpcProvider(providerUrl)
const maker = new ethers.Wallet(makerPrivateKey)
console.log(maker)
const limitOrderContractAddress = `0xe2E5e33aEc661241b3853a4460F7AabA65e950c3`
const usdtAddress = `0xa93Ef9215b907c19e739E2214e1AA5412a0401B5`
const wethAddress = `0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6`
const newOrderAPI = `https://api.imdev.works/v5/limit-order/limitorder`
const limitOrderListAPI = `https://api.imdev.works/v5/limit-order/limitorder?chainId=5&status=pending,partialfilled&maker=${maker.address}`
const binancePriceAPI = `https://api.binance.com/api/v3/ticker/bookTicker?symbol=ETHUSDT`
export enum SignatureType {
Illegal = '00', // 0x00, default value
Invalid = '01', // 0x01
EIP712 = '02', // 0x02
EthSign = '03', // 0x03
WalletBytes = '04', // 0x04 standard 1271 wallet type
WalletBytes32 = '05', // 0x05 standard 1271 wallet type
Wallet = '06', // 0x06 0x wallet type for signature compatibility
NSignatureTypes = '07', // 0x07, number of signature types. Always leave at end.
}
const getLimitOrderHash = (chainId: number, order): string => {
const domain = {
name: 'Tokenlon',
version: 'v5',
chainId: chainId,
verifyingContract: limitOrderContractAddress,
}
const types = {
Order: [
{ name: 'makerToken', type: 'address' },
{ name: 'takerToken', type: 'address' },
{ name: 'makerTokenAmount', type: 'uint256' },
{ name: 'takerTokenAmount', type: 'uint256' },
{ name: 'maker', type: 'address' },
{ name: 'taker', type: 'address' },
{ name: 'salt', type: 'uint256' },
{ name: 'expiry', type: 'uint64' },
],
}
const value = {
makerToken: order.makerToken,
takerToken: order.takerToken,
makerTokenAmount: order.makerTokenAmount,
takerTokenAmount: order.takerTokenAmount,
maker: order.maker,
taker: order.taker,
salt: order.salt ? order.salt : generatePseudoRandomSalt(),
expiry: order.expiry,
}
return _TypedDataEncoder.hash(domain, types, value)
}
export const generatePseudoRandomSalt = () => {
return BigNumber.from(crypto.randomBytes(32)).toString()
}
const signLimitOrder = async (signer: Wallet, chainId: number, order) => {
console.log(`LIMIT_ORDER[chainId] ${limitOrderContractAddress}`)
const domain = {
name: "Tokenlon",
version: "v5",
chainId: chainId,
verifyingContract: limitOrderContractAddress,
}
const types = {
Order: [
{ name: "makerToken", type: "address" },
{ name: "takerToken", type: "address" },
{ name: "makerTokenAmount", type: "uint256" },
{ name: "takerTokenAmount", type: "uint256" },
{ name: "maker", type: "address" },
{ name: "taker", type: "address" },
{ name: "salt", type: "uint256" },
{ name: "expiry", type: "uint64" },
],
}
const signatureTypedData = await signer._signTypedData(domain, types, order)
const paddedNonce = "00".repeat(32)
const composedSig = signatureTypedData + paddedNonce + SignatureType.EIP712
return composedSig
}
export const makerSign = async (maker: Wallet, limitOrderRequest): Promise<any> => {
limitOrderRequest.taker = limitOrderRequest.taker ? limitOrderRequest.taker : ethers.constants.AddressZero
limitOrderRequest.salt = limitOrderRequest.salt ? limitOrderRequest.salt : generatePseudoRandomSalt()
const orderHash = getLimitOrderHash(chainId, limitOrderRequest)
const makerSig = await signLimitOrder(maker, chainId, limitOrderRequest)
const limitOrder = {
...limitOrderRequest,
chainId,
orderHash: orderHash,
makerSig: makerSig,
status: 'Pending'
}
return limitOrder
}
const placeNewOrder = async () => {
// new order
const priceResp = await axios.get(binancePriceAPI)
const prices = priceResp.data
const bidPrice = prices.bidPrice
const usd = 5
const etherAmount = new BN(usd).div(bidPrice).toFixed(8)
console.log(`etherAmount: ${etherAmount}`)
const newOrder = {
maker: maker.address,
taker: ethers.constants.AddressZero,
makerToken: usdtAddress,
takerToken: wethAddress,
makerTokenAmount: ethers.utils.parseUnits(usd.toString(), 6).toString(),
takerTokenAmount: ethers.utils.parseEther(etherAmount).toString(),
expiry: Math.floor(Date.now() / 1000) + 86400,
salt: generatePseudoRandomSalt()
}
const signedOrder = await makerSign(maker, newOrder)
console.log(signedOrder)
const newOrderResult = await axios.post(newOrderAPI, signedOrder)
const newLimitOrder = newOrderResult.data
console.log(newLimitOrder)
console.log(`new order: ${newLimitOrder.orderHash}`)
}
const cancelAndPlaceNewOrder = async () => {
const resp = await axios.get(limitOrderListAPI)
const orders = resp.data
console.log(orders)
const remainOrders = orders.filter(order => {
return new BN(order.remainQuota).isGreaterThan(0)
})
if (remainOrders.length > 0) {
// cancel all orders
const orderHashes = remainOrders.map(order => {
return order.orderHash
})
const message = orderHashes.join(",")
const cancelSig = await maker.signMessage(message)
const resp = await axios.put(newOrderAPI, {
chainId: chainId,
orderHashes: orderHashes,
cancelSig: cancelSig
})
const result = resp.data
console.log(result)
console.log(`cancelled all orders`)
await placeNewOrder()
} else {
await placeNewOrder()
}
}
const main = async () => {
try {
await cancelAndPlaceNewOrder()
} catch (e) {
console.error(e)
}
setInterval(async () => {
let inProgress = false
if (!inProgress) {
inProgress = true
try {
await cancelAndPlaceNewOrder()
} catch (e) {
console.error(e)
}
inProgress = false
}
}, 60000)
}
main()