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/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
- console.log(amount,path,side,point)
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, target = "" }) {
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
- let inAmount;
578
- let inputAmount;
585
+
586
+ let outputAmount = 0;
579
587
  if(side == 0) {
580
- inAmount = amount
581
588
  outAmount = await this.computeAmount({ amount,path,side,point })
582
- inputAmount = await IToken.toAmount(amount)
583
- console.log("预计输出金额:",outAmount)
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 swapToken({ amount,path,side = 0,point = 1000, deadline = 0 }) {
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
  }
@@ -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