h-agent-swap 3.0.7 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/abi/TokenMarket.json +3 -36
- package/src/abi/Treasury.json +520 -0
- package/src/agent-swap.js +73 -16
- package/src/index.js +5 -1
- package/src/treasury.js +362 -0
package/src/agent-swap.js
CHANGED
|
@@ -5,14 +5,16 @@ let { abi, bytecode } = require("./abi/TokenMarket.json")
|
|
|
5
5
|
let { plus, reduce, multiplication, division, saveNum, charCompare,longHandle,toSmall } = require("h-token-staking/src/utils")
|
|
6
6
|
const ERC20 = require("h-token-staking/src/ERC20")
|
|
7
7
|
let SwapLP = require("./swap-pair")
|
|
8
|
+
let SwapFactory = require("./swap-factory")
|
|
8
9
|
|
|
9
10
|
class AgentSwap extends HI {
|
|
10
|
-
constructor({ provider, account, rpcUrl, privateKey, contract,lp = "" }) {
|
|
11
|
+
constructor({ provider, account, rpcUrl, privateKey, contract,lp = "",factory = "" }) {
|
|
11
12
|
super({ provider, account, rpcUrl, privateKey, contract, abi })
|
|
12
13
|
this.mainToken = "0x0000000000000000000000000000000000000000"
|
|
13
14
|
this.maxVal = "999000000000000000000000000000000000000000000000000"
|
|
14
15
|
this.WETH = ""
|
|
15
16
|
this.ROUTER = ""
|
|
17
|
+
this.FACTORY = factory
|
|
16
18
|
this.pointMax = "100000000"
|
|
17
19
|
|
|
18
20
|
this.point = 0.01
|
|
@@ -391,6 +393,14 @@ ${JSON.stringify(data,null,2)}`)
|
|
|
391
393
|
|
|
392
394
|
|
|
393
395
|
|
|
396
|
+
async whitelist(address) {
|
|
397
|
+
let result = await this.SC.methods.whitelist(address).call()
|
|
398
|
+
return result
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
|
|
394
404
|
async setTwapPeriod(period) {
|
|
395
405
|
|
|
396
406
|
let params = [
|
|
@@ -474,7 +484,7 @@ ${JSON.stringify(data,null,2)}`)
|
|
|
474
484
|
}else {
|
|
475
485
|
amount = await OToken.toAmount(amount)
|
|
476
486
|
}
|
|
477
|
-
|
|
487
|
+
|
|
478
488
|
let result = await this.SC.methods.computeAmount(amount,path,side,point).call()
|
|
479
489
|
if(format) {
|
|
480
490
|
if(side == 0) {
|
|
@@ -544,7 +554,7 @@ ${JSON.stringify(data,null,2)}`)
|
|
|
544
554
|
|
|
545
555
|
|
|
546
556
|
|
|
547
|
-
async tradeConfig({ amount,path,side = 0,point = 1000
|
|
557
|
+
async tradeConfig({ amount,path,side = 0,point = 1000}) {
|
|
548
558
|
if(path.length != 2) {
|
|
549
559
|
throw "仅支持单一交易对计算"
|
|
550
560
|
}
|
|
@@ -570,20 +580,16 @@ ${JSON.stringify(data,null,2)}`)
|
|
|
570
580
|
})
|
|
571
581
|
console.log("扣除费用后金额:",amount)
|
|
572
582
|
|
|
573
|
-
|
|
574
|
-
let IToken = new HERC20({ ...this.network, contract: inToken })
|
|
575
583
|
let OToken = new HERC20({ ...this.network, contract: outToken })
|
|
576
584
|
let outAmount;
|
|
577
|
-
|
|
578
|
-
let
|
|
585
|
+
|
|
586
|
+
let outputAmount = 0;
|
|
579
587
|
if(side == 0) {
|
|
580
|
-
inAmount = amount
|
|
581
588
|
outAmount = await this.computeAmount({ amount,path,side,point })
|
|
582
|
-
|
|
583
|
-
console.log("预计输出金额:",
|
|
589
|
+
outputAmount = await OToken.fromAmount(outAmount)
|
|
590
|
+
console.log("预计输出金额:",outputAmount)
|
|
584
591
|
}
|
|
585
|
-
|
|
586
|
-
let outputAmount = await OToken.fromAmount(outAmount)
|
|
592
|
+
|
|
587
593
|
|
|
588
594
|
return outputAmount
|
|
589
595
|
}
|
|
@@ -657,8 +663,28 @@ ${JSON.stringify(data,null,2)}`)
|
|
|
657
663
|
}
|
|
658
664
|
|
|
659
665
|
|
|
660
|
-
async
|
|
666
|
+
async swapRate({ path,point = 1000 }) {
|
|
661
667
|
await this.weth()
|
|
668
|
+
let outToken = path[path.length - 1]
|
|
669
|
+
let OToken = new HERC20({ ...this.network, contract: outToken })
|
|
670
|
+
let outAmount = await this.computeAmount({ amount:1,path,side:0,point })
|
|
671
|
+
|
|
672
|
+
let amountOut = await OToken.fromAmount(outAmount)
|
|
673
|
+
console.log("汇率:",amountOut)
|
|
674
|
+
return amountOut
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
async swapToken({ amount,outAmountMin = 0,path,side = 0,point = 1000, deadline = 0 }) {
|
|
679
|
+
await this.weth()
|
|
680
|
+
|
|
681
|
+
if (path.length < 2) {
|
|
682
|
+
throw "path长度错误"
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
|
|
662
688
|
let inToken = path[0]
|
|
663
689
|
let outToken = path[path.length - 1]
|
|
664
690
|
let inAmount = 0
|
|
@@ -677,17 +703,48 @@ ${JSON.stringify(data,null,2)}`)
|
|
|
677
703
|
ethAmount = inAmount
|
|
678
704
|
}
|
|
679
705
|
|
|
680
|
-
|
|
706
|
+
if(outAmountMin == 0) {
|
|
707
|
+
outAmountMin = await this.tradeConfig({ amount,path,side,point})
|
|
708
|
+
console.log("最小接受数量:",outAmountMin)
|
|
709
|
+
outAmountMin = await OToken.toAmount(outAmountMin)
|
|
710
|
+
}else {
|
|
711
|
+
console.log("最小接受数量:",outAmountMin)
|
|
712
|
+
outAmountMin = await OToken.toAmount(outAmountMin)
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
|
|
716
|
+
// 检查最大交换比例
|
|
717
|
+
// let factory = new SwapFactory({ ...this.network, contract: this.FACTORY })
|
|
718
|
+
// let lpAddress = await factory.getPair({ token0: path[0], token1: path[1] })
|
|
719
|
+
// let lp = new SwapLP({ ...this.network, contract:lpAddress })
|
|
720
|
+
// let resultReserves = await lp.getReserves()
|
|
721
|
+
// let maxSwapRatioBps = await this.getMaxSwapRatioBps()
|
|
722
|
+
// if(resultReserves.token0.toLocaleLowerCase() == path[0].toLocaleLowerCase()) {
|
|
723
|
+
// let maxSwap = multiplication(resultReserves._reserve0,maxSwapRatioBps)
|
|
724
|
+
// console.log("池子储量:",await IToken.fromAmount(resultReserves._reserve0),"最大交换量:",await IToken.fromAmount(maxSwap))
|
|
725
|
+
// if(Number(inAmount) > Number(maxSwap)) {
|
|
726
|
+
// throw `单次交换数量不能超过池子${multiplication(maxSwapRatioBps,100)}%`
|
|
727
|
+
// }
|
|
728
|
+
// }else if(resultReserves.token1.toLocaleLowerCase() == path[0].toLocaleLowerCase()) {
|
|
729
|
+
// let maxSwap = multiplication(resultReserves._reserve1,maxSwapRatioBps)
|
|
730
|
+
// console.log("池子储量:",await IToken.fromAmount(resultReserves._reserve1),"最大交换量:",await IToken.fromAmount(maxSwap))
|
|
731
|
+
// if(Number(inAmount) > Number(maxSwap)) {
|
|
732
|
+
// throw `单次交换数量不能超过池子${multiplication(maxSwapRatioBps,100)}%`
|
|
733
|
+
// }
|
|
734
|
+
// }
|
|
735
|
+
|
|
736
|
+
// 批准
|
|
681
737
|
let amountIn = await IToken.fromAmount(inAmount)
|
|
682
738
|
await IToken.tradeApprove(this.contract,amountIn)
|
|
683
739
|
|
|
684
|
-
|
|
740
|
+
// 到期时间
|
|
685
741
|
let now = new Date().getTime()
|
|
686
742
|
now = parseInt(division(now, 1000))
|
|
687
743
|
deadline = deadline ? deadline : plus(multiplication(60, 30), now)
|
|
688
744
|
|
|
745
|
+
|
|
689
746
|
let parma_list = [
|
|
690
|
-
path,inAmount, deadline,point
|
|
747
|
+
path,inAmount,outAmountMin, deadline,point
|
|
691
748
|
]
|
|
692
749
|
console.log(parma_list)
|
|
693
750
|
let parmas = await this.buildTx("swapToken", parma_list, ethAmount)
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,8 @@ let SwapRouter = require("./swap-router")
|
|
|
5
5
|
let SwapLP = require("./swap-pair")
|
|
6
6
|
let Poker = require("./poker")
|
|
7
7
|
let BERC20 = require("./BERC20")
|
|
8
|
+
let Treasury = require("./treasury")
|
|
9
|
+
|
|
8
10
|
if (window) {
|
|
9
11
|
window.AgentSwap = AgentSwap
|
|
10
12
|
window.SwapFactory = SwapFactory
|
|
@@ -12,6 +14,7 @@ if (window) {
|
|
|
12
14
|
window.SwapLP = SwapLP
|
|
13
15
|
window.Poker = Poker
|
|
14
16
|
window.BERC20 = BERC20
|
|
17
|
+
window.Treasury = Treasury
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
module.exports = {
|
|
@@ -20,5 +23,6 @@ module.exports = {
|
|
|
20
23
|
SwapRouter,
|
|
21
24
|
SwapLP,
|
|
22
25
|
Poker,
|
|
23
|
-
BERC20
|
|
26
|
+
BERC20,
|
|
27
|
+
Treasury
|
|
24
28
|
}
|
package/src/treasury.js
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
let { HI, HERC20 } = require("h-token-staking")
|
|
2
|
+
|
|
3
|
+
let { abi, bytecode } = require("./abi/Treasury.json")
|
|
4
|
+
|
|
5
|
+
let { plus, reduce, multiplication, division, saveNum, charCompare, longHandle, toSmall } = require("h-token-staking/src/utils")
|
|
6
|
+
const ERC20 = require("h-token-staking/src/ERC20")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Treasury extends HI {
|
|
10
|
+
constructor({ provider, account, rpcUrl, privateKey, contract, factory = "" }) {
|
|
11
|
+
super({ provider, account, rpcUrl, privateKey, contract, abi })
|
|
12
|
+
this.mainToken = "0x0000000000000000000000000000000000000000"
|
|
13
|
+
this.maxVal = "999000000000000000000000000000000000000000000000000"
|
|
14
|
+
this.WETH = ""
|
|
15
|
+
this.ROUTER = ""
|
|
16
|
+
this.FACTORY = factory
|
|
17
|
+
this.pointMax = "100000000"
|
|
18
|
+
|
|
19
|
+
this.point = 0.01
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async transfer({ to, amount, contract }) {
|
|
23
|
+
let tokenItem = new ERC20({ ...this.network, contract })
|
|
24
|
+
let user = this.web3.eth.defaultAccount
|
|
25
|
+
let balance = await this.balanceOf({
|
|
26
|
+
token: contract,
|
|
27
|
+
address: user
|
|
28
|
+
})
|
|
29
|
+
if (parseFloat(balance) < parseFloat(amount)) {
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
let result = await tokenItem.transfer(to, amount)
|
|
33
|
+
return result
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
pointOffset({ point, amount, isplus = true }) {
|
|
37
|
+
let result
|
|
38
|
+
if (isplus) {
|
|
39
|
+
result = division(multiplication(amount, plus(this.pointMax, point)), this.pointMax)
|
|
40
|
+
} else {
|
|
41
|
+
result = division(multiplication(amount, reduce(this.pointMax, point)), this.pointMax)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return result
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
pointHandle(amount, isplus = true) {
|
|
48
|
+
let rate = 1
|
|
49
|
+
if (isplus) {
|
|
50
|
+
rate = plus(1, this.point)
|
|
51
|
+
} else {
|
|
52
|
+
rate = reduce(1, this.point)
|
|
53
|
+
}
|
|
54
|
+
amount = multiplication(amount, rate)
|
|
55
|
+
amount = saveNum(amount, 0)
|
|
56
|
+
return amount
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async deploy({ route }) {
|
|
60
|
+
try {
|
|
61
|
+
let from = this.web3.eth.defaultAccount
|
|
62
|
+
|
|
63
|
+
let gasPrice = await this.GasPrice()
|
|
64
|
+
let result = await this.SC.deploy({
|
|
65
|
+
data: bytecode,
|
|
66
|
+
arguments: [route]
|
|
67
|
+
}).send({ from, gasPrice });
|
|
68
|
+
this.SC = result
|
|
69
|
+
return result
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.log(err)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async isOwner() {
|
|
76
|
+
let owner = await this.SC.methods.owner().call()
|
|
77
|
+
|
|
78
|
+
let isOwner = charCompare(owner, this.web3.eth.defaultAccount)
|
|
79
|
+
return isOwner
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async manage(method, param = []) {
|
|
83
|
+
let isOwner = await this.isOwner()
|
|
84
|
+
if (isOwner) {
|
|
85
|
+
let parmas = await this.buildTx(method, param)
|
|
86
|
+
let result = parmas && await this.broadTx(parmas)
|
|
87
|
+
return result
|
|
88
|
+
} else {
|
|
89
|
+
console.log("非合约所有者调用")
|
|
90
|
+
}
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async updateFee({ tokenIn, tokenOut, rate, isOutToken }) {
|
|
95
|
+
let result = await this.manage("updateFee", [tokenIn, tokenOut, rate, isOutToken])
|
|
96
|
+
return result
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async tokenSend({ token, amount, recipient }) {
|
|
100
|
+
let inToken = new HERC20({ ...this.network, contract: token })
|
|
101
|
+
amount = await inToken.toAmount(amount)
|
|
102
|
+
|
|
103
|
+
let result = await this.manage("tokenSend", [inToken.contract, recipient, amount])
|
|
104
|
+
return result
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async setting(route) {
|
|
108
|
+
let result = await this.manage("setting", [route])
|
|
109
|
+
return result
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async sync({ tokenIn, tokenOut }) {
|
|
113
|
+
|
|
114
|
+
let params = [
|
|
115
|
+
tokenIn,
|
|
116
|
+
tokenOut,
|
|
117
|
+
]
|
|
118
|
+
let result = await this.manage("sync", params)
|
|
119
|
+
return result
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async updateWhite({ address, onoff }) {
|
|
123
|
+
|
|
124
|
+
let params = [
|
|
125
|
+
address,
|
|
126
|
+
onoff
|
|
127
|
+
]
|
|
128
|
+
let result = await this.manage("updateWhite", params)
|
|
129
|
+
return result
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async setMaxAllowedOffset(percent) {
|
|
133
|
+
percent = multiplication(division(percent, 100), this.pointMax)
|
|
134
|
+
let params = [
|
|
135
|
+
percent
|
|
136
|
+
]
|
|
137
|
+
let result = await this.manage("setMaxAllowedOffset", params)
|
|
138
|
+
return result
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async getMaxAllowedOffset() {
|
|
142
|
+
let result = await this.SC.methods.maxAllowedOffset().call()
|
|
143
|
+
|
|
144
|
+
return division(result, this.pointMax)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async setMaxSwapRatioBps(percent) {
|
|
148
|
+
percent = multiplication(division(percent, 100), this.pointMax)
|
|
149
|
+
let params = [
|
|
150
|
+
percent
|
|
151
|
+
]
|
|
152
|
+
let result = await this.manage("setMaxSwapRatioBps", params)
|
|
153
|
+
return result
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async getMaxSwapRatioBps() {
|
|
157
|
+
let result = await this.SC.methods.maxSwapRatioBps().call()
|
|
158
|
+
|
|
159
|
+
return division(result, this.pointMax)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async setTwapPeriod(period) {
|
|
163
|
+
|
|
164
|
+
let params = [
|
|
165
|
+
period
|
|
166
|
+
]
|
|
167
|
+
let result = await this.manage("setTwapPeriod", params)
|
|
168
|
+
return result
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async getTwapPeriod() {
|
|
172
|
+
let result = await this.SC.methods.twapPeriod().call()
|
|
173
|
+
|
|
174
|
+
return result
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async route() {
|
|
178
|
+
if (!this.ROUTER) {
|
|
179
|
+
let result = await this.SC.methods.route().call()
|
|
180
|
+
this.ROUTER = result
|
|
181
|
+
}
|
|
182
|
+
return this.ROUTER
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async weth() {
|
|
186
|
+
if (!this.WETH) {
|
|
187
|
+
let result = await this.SC.methods.weth().call()
|
|
188
|
+
this.WETH = result
|
|
189
|
+
}
|
|
190
|
+
return this.WETH
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async approve({ token, amount }) {
|
|
194
|
+
let symbol = new HERC20({ ...this.network, contract: token })
|
|
195
|
+
let result = await symbol.tradeApprove(this.contract, amount)
|
|
196
|
+
return result
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async balanceOf({ token, address }) {
|
|
200
|
+
let symbol = new HERC20({ ...this.network, contract: token })
|
|
201
|
+
let result = await symbol.balanceOf(address)
|
|
202
|
+
result = await symbol.fromAmount(result)
|
|
203
|
+
return result
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async computeAmount({ amount, path, side = 0, point = 1000, format = false }) {
|
|
207
|
+
let inToken = path[0]
|
|
208
|
+
let outToken = path[path.length - 1]
|
|
209
|
+
let IToken = new HERC20({ ...this.network, contract: inToken })
|
|
210
|
+
let OToken = new HERC20({ ...this.network, contract: outToken })
|
|
211
|
+
if (side == 0) {
|
|
212
|
+
amount = await IToken.toAmount(amount)
|
|
213
|
+
} else {
|
|
214
|
+
amount = await OToken.toAmount(amount)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let result = await this.SC.methods.computeAmount(amount, path, side, point).call()
|
|
218
|
+
if (format) {
|
|
219
|
+
if (side == 0) {
|
|
220
|
+
result = await OToken.fromAmount(result)
|
|
221
|
+
} else {
|
|
222
|
+
result = await IToken.fromAmount(result)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return result
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async swapRate({ path, point = 1000 }) {
|
|
229
|
+
await this.weth()
|
|
230
|
+
let outToken = path[path.length - 1]
|
|
231
|
+
let OToken = new HERC20({ ...this.network, contract: outToken })
|
|
232
|
+
let outAmount = await this.computeAmount({ amount: 1, path, side: 0, point })
|
|
233
|
+
let amountOut = await OToken.fromAmount(outAmount)
|
|
234
|
+
console.log("汇率:", amountOut)
|
|
235
|
+
return amountOut
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async swap({ amount, outAmountMin = 0, path, side = 0, point = 1000, deadline = 0 }) {
|
|
239
|
+
await this.weth()
|
|
240
|
+
if (path.length < 2) {
|
|
241
|
+
throw "path长度错误"
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
let inToken = path[0]
|
|
245
|
+
let outToken = path[path.length - 1]
|
|
246
|
+
let inAmount = 0
|
|
247
|
+
let outAmount = 0
|
|
248
|
+
let ethAmount = 0
|
|
249
|
+
let IToken = new HERC20({ ...this.network, contract: inToken })
|
|
250
|
+
let OToken = new HERC20({ ...this.network, contract: outToken })
|
|
251
|
+
if (side == 0) {
|
|
252
|
+
inAmount = await IToken.toAmount(amount)
|
|
253
|
+
outAmount = await this.computeAmount({ amount, path, side, point })
|
|
254
|
+
} else {
|
|
255
|
+
outAmount = await OToken.toAmount(amount)
|
|
256
|
+
inAmount = await this.computeAmount({ amount, path, side, point })
|
|
257
|
+
}
|
|
258
|
+
if (charCompare(this.WETH, inToken)) {
|
|
259
|
+
ethAmount = inAmount
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
outAmountMin = await this.computeAmount({ amount: amount, path, side: 0, point })
|
|
263
|
+
console.log("最小接受数量:", await OToken.fromAmount(outAmountMin))
|
|
264
|
+
|
|
265
|
+
// 批准
|
|
266
|
+
let amountIn = await IToken.fromAmount(inAmount)
|
|
267
|
+
let balance = await this.balanceOf({
|
|
268
|
+
token: inToken,
|
|
269
|
+
address: this.contract
|
|
270
|
+
})
|
|
271
|
+
if (parseFloat(balance) < parseFloat(amountIn)) {
|
|
272
|
+
throw "合约内余额不足,请先充值"
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// 到期时间
|
|
276
|
+
let now = new Date().getTime()
|
|
277
|
+
now = parseInt(division(now, 1000))
|
|
278
|
+
deadline = deadline ? deadline : plus(multiplication(60, 30), now)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
let parma_list = [
|
|
282
|
+
path, inAmount, outAmountMin, deadline, point
|
|
283
|
+
]
|
|
284
|
+
console.log(parma_list)
|
|
285
|
+
let parmas = await this.buildTx("swap", parma_list, ethAmount)
|
|
286
|
+
let result = parmas && await this.broadTx(parmas)
|
|
287
|
+
return result
|
|
288
|
+
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
async whitelist(address) {
|
|
293
|
+
let result = await this.SC.methods.whitelist(address).call()
|
|
294
|
+
return result
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* 计算使池子价格变动所需投入的代币数量
|
|
299
|
+
*
|
|
300
|
+
* @param {number} R0 - 代币A的当前储备量
|
|
301
|
+
* @param {number} R1 - 代币B的当前储备量
|
|
302
|
+
* @param {number} changePct - 价格变动百分比(正数表示上涨,负数表示下跌,如 2.5 表示 +2.5%,-1.2 表示 -1.2%)
|
|
303
|
+
* @returns {Object} { inputAmount, token }
|
|
304
|
+
* - inputAmount: 需要投入的数量(用户实际支付,含手续费)
|
|
305
|
+
* - token: 'R0' 或 'R1',表示应投入哪种代币
|
|
306
|
+
*/
|
|
307
|
+
calculateInputForPriceChange(R0, R1, changePct) {
|
|
308
|
+
const feeRate = 0.0025; // 0.25%
|
|
309
|
+
const effectiveRate = 1 - feeRate; // 0.9975
|
|
310
|
+
|
|
311
|
+
const currentPrice = R1 / R0;
|
|
312
|
+
const targetPrice = currentPrice * (1 + changePct / 100);
|
|
313
|
+
|
|
314
|
+
if (targetPrice <= 0) {
|
|
315
|
+
throw new Error("目标价格必须大于 0");
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const k = R0 * R1; // 恒定乘积
|
|
319
|
+
|
|
320
|
+
if (changePct > 0) {
|
|
321
|
+
// 价格上涨:需用 B 换 A → 投入 R1(代币B)
|
|
322
|
+
// 新状态满足: R1' / R0' = targetPrice, 且 R0' * R1' = k
|
|
323
|
+
const R1_prime = Math.sqrt(k * targetPrice);
|
|
324
|
+
const deltaR1_effective = R1_prime - R1; // 进入池子的 B(已扣手续费)
|
|
325
|
+
if (deltaR1_effective <= 0) {
|
|
326
|
+
throw new Error("价格上涨需增加 R1,但计算结果非正");
|
|
327
|
+
}
|
|
328
|
+
const inputR1 = deltaR1_effective / effectiveRate; // 用户实际需支付的 B
|
|
329
|
+
return {
|
|
330
|
+
inputAmount: inputR1,
|
|
331
|
+
token: 'R1', // 投入代币B
|
|
332
|
+
newPrice: targetPrice
|
|
333
|
+
};
|
|
334
|
+
} else if (changePct < 0) {
|
|
335
|
+
// 价格下跌:需用 A 换 B → 投入 R0(代币A)
|
|
336
|
+
const R0_prime = Math.sqrt(k / targetPrice);
|
|
337
|
+
const deltaR0_effective = R0_prime - R0; // 进入池子的 A(已扣手续费)
|
|
338
|
+
if (deltaR0_effective <= 0) {
|
|
339
|
+
throw new Error("价格下跌需增加 R0,但计算结果非正");
|
|
340
|
+
}
|
|
341
|
+
const inputR0 = deltaR0_effective / effectiveRate; // 用户实际需支付的 A
|
|
342
|
+
return {
|
|
343
|
+
inputAmount: inputR0,
|
|
344
|
+
token: 'R0', // 投入代币A
|
|
345
|
+
newPrice: targetPrice
|
|
346
|
+
};
|
|
347
|
+
} else {
|
|
348
|
+
return {
|
|
349
|
+
inputAmount: 0,
|
|
350
|
+
token: null,
|
|
351
|
+
newPrice: currentPrice
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
module.exports = Treasury
|