实现usdt兑换trx未接入机器人

pull/520/head
dorion 2024-04-22 01:26:07 +08:00
parent adad055a9d
commit c57db92167
24 changed files with 1502 additions and 14 deletions

View File

@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.entity.MonitorAddressInfo;
import com.ruoyi.common.core.domain.entity.TenantInfo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.IMonitorAddressInfoService;
import com.ruoyi.system.service.ITenantInfoService;
@ -75,8 +76,8 @@ public class TenantInfoController extends BaseController
@GetMapping("/add")
public String add(ModelMap mmap)
{
List<MonitorAddressInfo> monitorAddressAccountList = monitorAddressInfoService.selectAllValidMonitorAddressAccount();
String trx2Energy = DictUtils.getDictValue("sys_busi_type", "TRX兑能量");
List<MonitorAddressInfo> monitorAddressAccountList = monitorAddressInfoService.selectAllValidMonitorAddressAccount(trx2Energy);
mmap.put("monitorAddressInfoList", monitorAddressAccountList);
return prefix + "/add";
}
@ -102,8 +103,8 @@ public class TenantInfoController extends BaseController
{
TenantInfo tenantInfo = tenantInfoService.selectTenantInfoByIdTenantInfo(idTenantInfo);
mmap.put("tenantInfo", tenantInfo);
List<MonitorAddressInfo> monitorAddressInfoList = monitorAddressInfoService.selectAllValidMonitorAddressAccount();
String trx2Energy = DictUtils.getDictValue("sys_busi_type", "TRX兑能量");
List<MonitorAddressInfo> monitorAddressInfoList = monitorAddressInfoService.selectAllValidMonitorAddressAccount(trx2Energy);
mmap.put("monitorAddressInfoList", monitorAddressInfoList);
return prefix + "/edit";
}

View File

@ -0,0 +1,123 @@
package com.ruoyi.web.controller.exchange;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.UsdtExchangeInfo;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.IUsdtExchangeInfoService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* USDTController
*
* @author dorion
* @date 2024-04-19
*/
@Controller
@RequestMapping("/exchange/usdt")
public class UsdtExchangeInfoController extends BaseController
{
private String prefix = "exchange/usdt";
@Autowired
private IUsdtExchangeInfoService usdtExchangeInfoService;
@RequiresPermissions("exchange:usdt:view")
@GetMapping()
public String usdt()
{
return prefix + "/usdt";
}
/**
* USDT
*/
@RequiresPermissions("exchange:usdt:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(UsdtExchangeInfo usdtExchangeInfo)
{
startPage();
List<UsdtExchangeInfo> list = usdtExchangeInfoService.selectUsdtExchangeInfoList(usdtExchangeInfo);
return getDataTable(list);
}
/**
* USDT
*/
@RequiresPermissions("exchange:usdt:export")
@Log(title = "USDT交易明细", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(UsdtExchangeInfo usdtExchangeInfo)
{
List<UsdtExchangeInfo> list = usdtExchangeInfoService.selectUsdtExchangeInfoList(usdtExchangeInfo);
ExcelUtil<UsdtExchangeInfo> util = new ExcelUtil<UsdtExchangeInfo>(UsdtExchangeInfo.class);
return util.exportExcel(list, "USDT交易明细数据");
}
/**
* USDT
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* USDT
*/
@RequiresPermissions("exchange:usdt:add")
@Log(title = "USDT交易明细", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(UsdtExchangeInfo usdtExchangeInfo) throws Exception {
return toAjax(usdtExchangeInfoService.insertUsdtExchangeInfo(usdtExchangeInfo));
}
/**
* USDT
*/
@RequiresPermissions("exchange:usdt:edit")
@GetMapping("/edit/{idUsdtExchangeInfo}")
public String edit(@PathVariable("idUsdtExchangeInfo") Long idUsdtExchangeInfo, ModelMap mmap)
{
UsdtExchangeInfo usdtExchangeInfo = usdtExchangeInfoService.selectUsdtExchangeInfoByIdUsdtExchangeInfo(idUsdtExchangeInfo);
mmap.put("usdtExchangeInfo", usdtExchangeInfo);
return prefix + "/edit";
}
/**
* USDT
*/
@RequiresPermissions("exchange:usdt:edit")
@Log(title = "USDT交易明细", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(UsdtExchangeInfo usdtExchangeInfo)
{
return toAjax(usdtExchangeInfoService.updateUsdtExchangeInfo(usdtExchangeInfo));
}
/**
* USDT
*/
@RequiresPermissions("exchange:usdt:remove")
@Log(title = "USDT交易明细", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(usdtExchangeInfoService.deleteUsdtExchangeInfoByIdUsdtExchangeInfos(ids));
}
}

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增USDT交易明细')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-usdt-add">
<div class="form-group">
<label class="col-sm-3 control-label">转入地址:</label>
<div class="col-sm-8">
<input name="fromAddress" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入金额USDT</label>
<div class="col-sm-8">
<input name="usdtAmount" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "exchange/usdt"
$("#form-usdt-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-usdt-add').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,118 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改USDT交易明细')" />
<th:block th:include="include :: datetimepicker-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-usdt-edit" th:object="${usdtExchangeInfo}">
<input name="idUsdtExchangeInfo" th:field="*{idUsdtExchangeInfo}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">转入地址:</label>
<div class="col-sm-8">
<input name="fromAddress" th:field="*{fromAddress}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转出地址:</label>
<div class="col-sm-8">
<input name="toAddress" th:field="*{toAddress}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">交易订单:</label>
<div class="col-sm-8">
<input name="usdtTxId" th:field="*{usdtTxId}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转入金额:</label>
<div class="col-sm-8">
<input name="usdtAmount" th:field="*{usdtAmount}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">转出金额:</label>
<div class="col-sm-8">
<input name="trxAmount" th:field="*{trxAmount}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">兑换费率:</label>
<div class="col-sm-8">
<input name="exchangeRate" th:field="*{exchangeRate}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">TRX订单</label>
<div class="col-sm-8">
<input name="trxTxId" th:field="*{trxTxId}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">原始费率:</label>
<div class="col-sm-8">
<input name="orginalExchangeRate" th:field="*{orginalExchangeRate}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="fcd" th:value="${#dates.format(usdtExchangeInfo.fcd, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">创建用户:</label>
<div class="col-sm-8">
<input name="fcu" th:field="*{fcu}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">更新时间:</label>
<div class="col-sm-8">
<div class="input-group date">
<input name="lcd" th:value="${#dates.format(usdtExchangeInfo.lcd, 'yyyy-MM-dd')}" class="form-control" placeholder="yyyy-MM-dd" type="text">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">更新用户:</label>
<div class="col-sm-8">
<input name="lcu" th:field="*{lcu}" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: datetimepicker-js" />
<script th:inline="javascript">
var prefix = ctx + "exchange/usdt";
$("#form-usdt-edit").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-usdt-edit').serialize());
}
}
$("input[name='fcd']").datetimepicker({
format: "yyyy-mm-dd",
minView: "month",
autoclose: true
});
$("input[name='lcd']").datetimepicker({
format: "yyyy-mm-dd",
minView: "month",
autoclose: true
});
</script>
</body>
</html>

View File

@ -0,0 +1,144 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('USDT交易明细列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>交易地址:</label>
<input type="text" name="fromAddress"/>
</li>
<li>
<label>转入地址:</label>
<input type="text" name="toAddress"/>
</li>
<li>
<label>交易订单:</label>
<input type="text" name="usdtTxId"/>
</li>
<li>
<label>创建时间:</label>
<input type="text" class="time-input" placeholder="请选择创建时间" name="fcd"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="exchange:usdt:add">
<i class="fa fa-plus"></i> 添加
</a>
<!-- <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="exchange:usdt:edit">
<i class="fa fa-edit"></i> 修改
</a>-->
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="exchange:usdt:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="exchange:usdt:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('exchange:usdt:edit')}]];
var removeFlag = [[${@permission.hasPermi('exchange:usdt:remove')}]];
var prefix = ctx + "exchange/usdt";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "USDT交易明细",
columns: [{
checkbox: true
},
{
field: 'idUsdtExchangeInfo',
title: '主键',
visible: false
},
{
field: 'fromAddress',
title: '转入地址'
},
{
field: 'toAddress',
title: '转出地址'
},
{
field: 'usdtTxId',
title: '交易订单'
},
{
field: 'usdtAmount',
title: '转入金额'
},
{
field: 'trxAmount',
title: '转出金额'
},
{
field: 'exchangeRate',
title: '兑换费率'
},
{
field: 'trxTxId',
title: 'TRX订单'
},
{
field: 'orginalExchangeRate',
title: '原始费率'
},
{
field: 'fcd',
title: '创建时间'
},
{
field: 'fcu',
title: '创建用户'
},
{
field: 'lcd',
title: '更新时间'
},
{
field: 'lcu',
title: '更新用户'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
/* actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.idUsdtExchangeInfo + '\')"><i class="fa fa-edit"></i>编辑</a> ');*/
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.idUsdtExchangeInfo + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
</script>
</body>
</html>

View File

@ -0,0 +1,83 @@
package com.ruoyi.common.core.domain.entity;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.Date;
/**
* USDT usdt_exchange_info
*
* @author dorion
* @date 2024-04-19
*/
@Accessors(chain = true)
@Data
public class UsdtExchangeInfo extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private Long idUsdtExchangeInfo;
/** 转入地址 */
@Excel(name = "交易地址")
private String fromAddress;
/** 转出地址 */
@Excel(name = "转入地址")
private String toAddress;
/** 出账地址 */
@Excel(name = "出账地址")
private String accountAddress;
/** 交易订单 */
@Excel(name = "交易订单")
private String usdtTxId;
/** 转入金额 */
@Excel(name = "转入金额")
private BigDecimal usdtAmount;
/** 转出金额 */
@Excel(name = "转出金额")
private BigDecimal trxAmount;
/** 兑换费率 */
@Excel(name = "兑换费率")
private BigDecimal exchangeRate;
/** TRX订单 */
@Excel(name = "TRX订单")
private String trxTxId;
/** 原始费率 */
@Excel(name = "原始费率")
private BigDecimal orginalExchangeRate;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date fcd;
/** 创建用户 */
@Excel(name = "创建用户")
private String fcu;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd")
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date lcd;
/** 更新用户 */
@Excel(name = "更新用户")
private String lcu;
}

View File

@ -3,6 +3,7 @@ package com.ruoyi.quartz.task;
import com.ruoyi.common.core.domain.entity.AccountAddressInfo;
import com.ruoyi.common.core.domain.entity.MonitorAddressInfo;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.system.domain.MonitorAddressAccount;
import com.ruoyi.system.service.IAccountAddressInfoService;
import com.ruoyi.system.service.IMonitorAddressInfoService;
@ -32,7 +33,8 @@ public class MonitorTrxTransferTask {
.monitorType("TRX")
.build();
List<MonitorAddressAccount> monitorAddressAccountList = iMonitorAddressInfoService.selectAllMonitorAddressAccount(monitorAddressAccountExample);*/
List<MonitorAddressInfo> monitorAddressInfoList = iMonitorAddressInfoService.selectAllValidMonitorAddressAccount();
String trx2Energy = DictUtils.getDictValue("sys_busi_type", "TRX兑能量");
List<MonitorAddressInfo> monitorAddressInfoList = iMonitorAddressInfoService.selectAllValidMonitorAddressAccount(trx2Energy);
List<MonitorAddressAccount> monitorAddressAccountList = new ArrayList<>();
for (MonitorAddressInfo monitorAddressInfo : monitorAddressInfoList) {

View File

@ -1,4 +1,35 @@
package com.ruoyi.quartz.task;
import com.ruoyi.common.core.domain.entity.MonitorAddressInfo;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.system.handler.UsdtTransferHandler;
import com.ruoyi.system.service.IMonitorAddressInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("monitorUsdtTransferTask")
@Slf4j
public class MonitorUsdtTransferTask {
@Autowired
private IMonitorAddressInfoService iMonitorAddressInfoService;
@Autowired
private UsdtTransferHandler usdtTransferHandler;
public void doMonitorUsdtTransferTask() throws Exception {
String usdt2Trx = DictUtils.getDictValue("sys_busi_type", "USDT兑TRX");
List<MonitorAddressInfo> monitorAddressInfoList =
iMonitorAddressInfoService.selectAllValidMonitorAddressAccount(usdt2Trx);
for (MonitorAddressInfo monitorAddressInfo : monitorAddressInfoList) {
usdtTransferHandler.doMonitorUsdtTransfer(monitorAddressInfo);
}
}
}

View File

@ -1,6 +1,7 @@
package com.ruoyi.quartz.task;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.core.domain.entity.TrxExchangeInfo;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.system.service.ITrxExchangeInfoService;
@ -8,6 +9,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
@Component("undelegateEnergyTask")
@ -23,7 +25,10 @@ public class UndelegateEnergyTask {
String dictValue = DictUtils.getDictValue("sys_delegate_status", "已委托");
TrxExchangeInfo trxExchangeInfoExample = TrxExchangeInfo.builder().delegateStatus(dictValue).build();
TrxExchangeInfo trxExchangeInfoExample = TrxExchangeInfo.builder()
.delegateStatus(dictValue)
.fcd(DateUtil.offsetDay(new Date(),-1))
.build();
List<TrxExchangeInfo> trxExchangeInfoList = trxExchangeInfoService.selectTrxExchangeInfoList(trxExchangeInfoExample);
for (TrxExchangeInfo trxExchangeInfo : trxExchangeInfoList) {

View File

@ -0,0 +1,10 @@
package com.ruoyi.system.api;
import com.ruoyi.system.api.entity.okx.OkxResponse;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public interface IOkxApi {
OkxResponse getSingleTickerOkxResponse() throws NoSuchAlgorithmException, InvalidKeyException;
}

View File

@ -0,0 +1,8 @@
package com.ruoyi.system.api;
import com.ruoyi.system.dto.TronGridResponse;
public interface ITronApi {
TronGridResponse getTronGridResponse(String monitorAddress, String apiKey);
}

View File

@ -0,0 +1,144 @@
package com.ruoyi.system.api.entity.okx;
import java.io.Serializable;
/**
* Auto-generated: 2024-04-20 16:33:40
*
* @author bejson.com (i@bejson.com)
* @website http://www.bejson.com/java2pojo/
*/
public class Data implements Serializable {
private static final long serialVersionUID = 1L;
private String instType;
private String instId;
private String last;
private String lastSz;
private String askPx;
private String askSz;
private String bidPx;
private String bidSz;
private String open24h;
private String high24h;
private String low24h;
private String volCcy24h;
private String vol24h;
private String ts;
private String sodUtc0;
private String sodUtc8;
public void setInstType(String instType) {
this.instType = instType;
}
public String getInstType() {
return instType;
}
public void setInstId(String instId) {
this.instId = instId;
}
public String getInstId() {
return instId;
}
public void setLast(String last) {
this.last = last;
}
public String getLast() {
return last;
}
public void setLastSz(String lastSz) {
this.lastSz = lastSz;
}
public String getLastSz() {
return lastSz;
}
public void setAskPx(String askPx) {
this.askPx = askPx;
}
public String getAskPx() {
return askPx;
}
public void setAskSz(String askSz) {
this.askSz = askSz;
}
public String getAskSz() {
return askSz;
}
public void setBidPx(String bidPx) {
this.bidPx = bidPx;
}
public String getBidPx() {
return bidPx;
}
public void setBidSz(String bidSz) {
this.bidSz = bidSz;
}
public String getBidSz() {
return bidSz;
}
public void setOpen24h(String open24h) {
this.open24h = open24h;
}
public String getOpen24h() {
return open24h;
}
public void setHigh24h(String high24h) {
this.high24h = high24h;
}
public String getHigh24h() {
return high24h;
}
public void setLow24h(String low24h) {
this.low24h = low24h;
}
public String getLow24h() {
return low24h;
}
public void setVolCcy24h(String volCcy24h) {
this.volCcy24h = volCcy24h;
}
public String getVolCcy24h() {
return volCcy24h;
}
public void setVol24h(String vol24h) {
this.vol24h = vol24h;
}
public String getVol24h() {
return vol24h;
}
public void setTs(String ts) {
this.ts = ts;
}
public String getTs() {
return ts;
}
public void setSodUtc0(String sodUtc0) {
this.sodUtc0 = sodUtc0;
}
public String getSodUtc0() {
return sodUtc0;
}
public void setSodUtc8(String sodUtc8) {
this.sodUtc8 = sodUtc8;
}
public String getSodUtc8() {
return sodUtc8;
}
}

View File

@ -0,0 +1,34 @@
package com.ruoyi.system.api.entity.okx;
import java.io.Serializable;
import java.util.List;
public class OkxResponse implements Serializable {
private static final long serialVersionUID = 1L;
private String code;
private String msg;
private List<Data> data;
public void setCode(String code) {
this.code = code;
}
public String getCode() {
return code;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getMsg() {
return msg;
}
public void setData(List<Data> data) {
this.data = data;
}
public List<Data> getData() {
return data;
}
}

View File

@ -0,0 +1,10 @@
package com.ruoyi.system.api.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum ContractType {
Approval, Transfer;
}

View File

@ -0,0 +1,10 @@
package com.ruoyi.system.api.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum Symbol {
USDT;
}

View File

@ -0,0 +1,79 @@
package com.ruoyi.system.api.impl;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.utils.http.RestTemplateUtils;
import com.ruoyi.system.api.IOkxApi;
import com.ruoyi.system.api.entity.okx.OkxResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.TimeZone;
@Component
@Slf4j
public class OkxApiImpl implements IOkxApi {
@Override
public OkxResponse getSingleTickerOkxResponse() throws NoSuchAlgorithmException, InvalidKeyException {
//apikey = "b5937540-0817-41f8-bff3-3fda1262c744"
//secretkey = "4CAAAA212D525D14AA1012E24B5FABDD"
//IP = ""
//备注名 = "实时查询费率"
//权限 = "读取"
HttpHeaders headers = new HttpHeaders();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String timestamp = dateFormat.format(new Date());
headers.add("OK-ACCESS-TIMESTAMP", timestamp);
String apiKey = "eb3163ad-5221-491a-9ae9-e74e9637574c";
headers.add("OK-ACCESS-KEY", apiKey);
String passphrase = "CHenduoqi0101!";
headers.add("OK-ACCESS-PASSPHRASE", passphrase);
String method = "GET";
String sign = generateSignature(timestamp, "get", "/api/v5/market/ticker?instId=TRX-USDT", "", "4CAAAA212D525D14AA1012E24B5FABDD");
headers.add("OK-ACCESS-SIGN", sign);
//监听
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://www.okx.com/api/v5/market/ticker?instId=TRX-USDT");
String uriString = builder.toUriString();
ResponseEntity responseEntity = RestTemplateUtils.get(uriString, headers, String.class);
if (responseEntity == null) {
log.error("getSingleTickerOkxResponse:responseEntity is null");
return null;
}
HttpStatus statusCode = responseEntity.getStatusCode();
if (statusCode != HttpStatus.OK) {
log.error("getSingleTickerOkxResponse响应失败:{}", JSONUtil.toJsonStr(responseEntity));
return null;
}
Object responseEntityBody = responseEntity.getBody();
if (responseEntityBody == null) {
log.warn("getSingleTickerOkxResponse:responseEntityBody is null");
return null;
}
OkxResponse okxResponse = JSONUtil.toBean((String) responseEntityBody, OkxResponse.class);
return okxResponse;
}
private static String generateSignature(String timestamp, String method, String requestPath, String body, String secretKey)
throws NoSuchAlgorithmException, InvalidKeyException {
String preHash = timestamp + method + requestPath + body;
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKeySpec);
byte[] hmacSha256 = mac.doFinal(preHash.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(hmacSha256);
}
}

View File

@ -0,0 +1,74 @@
package com.ruoyi.system.api.impl;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.utils.http.RestTemplateUtils;
import com.ruoyi.system.api.ITronApi;
import com.ruoyi.system.dto.TronGridResponse;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
@Component
@Slf4j
public class TronApiImpl implements ITronApi {
@Autowired
private ISysConfigService configService;
@Override
public TronGridResponse getTronGridResponse(String monitorAddress, String apiKey) {
HttpHeaders headers = new HttpHeaders();
headers.add("TRON-PRO-API-KEY", apiKey);
//监听
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("https://api.trongrid.io/v1/accounts/" + monitorAddress + "/transactions/trc20");
// builder.queryParam("only_confirmed", true);
builder.queryParam("only_to", true);
builder.queryParam("limit", 200);
// String sysTransferBetween = configService.selectConfigByKey("sys.transfer.between");
//
// DateTime min_timestamp = DateUtil.offset(new Date(), DateField.MINUTE, Integer.valueOf(sysTransferBetween));
// builder.queryParam("min_timestamp", min_timestamp.getTime());
String uriString = builder.toUriString();
ResponseEntity responseEntity = RestTemplateUtils.get(uriString, headers, String.class);
Object responseEntityBody = getResponseEntityBody(responseEntity, monitorAddress);
if (responseEntityBody == null) return null;
TronGridResponse tronGridResponse = JSONUtil.toBean((String) responseEntityBody, TronGridResponse.class);
if (log.isInfoEnabled()) {
log.info("{}responseEntityBody:{}", monitorAddress, JSONUtil.toJsonStr(tronGridResponse));
}
return tronGridResponse;
}
/**
*
*
* @param responseEntity
* @param address
* @return
*/
private static Object getResponseEntityBody(ResponseEntity responseEntity, String address) {
if (responseEntity == null) {
log.warn("{}:responseEntity is null", address);
return null;
}
HttpStatus statusCode = responseEntity.getStatusCode();
if (statusCode != HttpStatus.OK) {
log.error("获取trx交易信息失败:{}", address);
return null;
}
Object responseEntityBody = responseEntity.getBody();
if (responseEntityBody == null) {
log.warn("{}:responseEntityBody is null", address);
return null;
}
return responseEntityBody;
}
}

View File

@ -0,0 +1,192 @@
package com.ruoyi.system.handler;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.google.common.base.Preconditions;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.MonitorAddressInfo;
import com.ruoyi.common.core.domain.entity.UsdtExchangeInfo;
import com.ruoyi.system.api.IOkxApi;
import com.ruoyi.system.api.ITronApi;
import com.ruoyi.system.api.entity.okx.OkxResponse;
import com.ruoyi.system.api.enums.ContractType;
import com.ruoyi.system.api.enums.Symbol;
import com.ruoyi.system.dto.Data;
import com.ruoyi.system.dto.Token_info;
import com.ruoyi.system.dto.TronGridResponse;
import com.ruoyi.system.mapper.UsdtExchangeInfoMapper;
import com.ruoyi.system.service.IAccountAddressInfoService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.util.AddressUtil;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.tron.trident.core.ApiWrapper;
import org.tron.trident.core.exceptions.IllegalException;
import org.tron.trident.proto.Chain;
import org.tron.trident.proto.Response;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
public class UsdtTransferHandler {
@Autowired
private ITronApi tronApi;
@Autowired
private IOkxApi okxApi;
@Autowired
private IAccountAddressInfoService accountAddressInfoService;
@Autowired
private UsdtExchangeInfoMapper usdtExchangeInfoMapper;
@Autowired
private ISysConfigService configService;
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private RedissonClient redissonClient;
public void doMonitorUsdtTransfer(MonitorAddressInfo monitorAddressInfo) throws Exception {
String monitorAddress = monitorAddressInfo.getMonitorAddress();
String apiKey = monitorAddressInfo.getApiKey();
TronGridResponse tronGridResponse = tronApi.getTronGridResponse(monitorAddress, apiKey);
List<Data> dataList = tronGridResponse.getData();
if (CollectionUtil.isEmpty(dataList)) {
return;
}
//获取欧易费率
BigDecimal oneUsdtToTrx = getOneUsdtToTrx();
for (Data data : dataList) {
doMonitorUsdtTransferByData(monitorAddressInfo, data, oneUsdtToTrx, apiKey);
}
}
private void doMonitorUsdtTransferByData(MonitorAddressInfo monitorAddressInfo, Data data, BigDecimal oneUsdtToTrx, String apiKey) throws Exception {
BigDecimal transferValue = getTransferValue(data);
if (transferValue == null) return;
BigDecimal trxValue = transferValue.multiply(oneUsdtToTrx);
String accountAddress = monitorAddressInfo.getAccountAddress();
String decryptPrivateKey = accountAddressInfoService.getDecryptPrivateKey(accountAddress);
//转账地址
String from = data.getFrom();
//接收地址
String dataTo = data.getTo();
String transactionId = data.getTransaction_id();
doTransferUsdtAndStore(oneUsdtToTrx, apiKey, decryptPrivateKey, accountAddress, from, trxValue, dataTo, transactionId, transferValue);
redisTemplate.opsForValue().set("transfer_USDT_" + transactionId, transactionId, 1, TimeUnit.DAYS);
}
public void doTransferUsdtAndStore(BigDecimal oneUsdtToTrx, String apiKey, String decryptPrivateKey, String accountAddress, String from, BigDecimal trxValue, String dataTo, String transactionId, BigDecimal transferValue) throws IllegalException {
String systronApiSwitch = configService.selectConfigByKey("sys.tron.api");
String txId = null;
if (UserConstants.YES.equals(systronApiSwitch)) {
ApiWrapper apiWrapper = ApiWrapper.ofMainnet(decryptPrivateKey, apiKey);
//转账
Response.TransactionExtention transfer = apiWrapper.transfer(accountAddress, from, trxValue.movePointRight(6).longValue());
//签名
Chain.Transaction transaction = apiWrapper.signTransaction(transfer);
//广播
txId = apiWrapper.broadcastTransaction(transaction);
}
UsdtExchangeInfo usdtExchangeInfo = new UsdtExchangeInfo();
usdtExchangeInfo.setFromAddress(AddressUtil.hexToBase58(from))
.setToAddress(AddressUtil.hexToBase58(dataTo))
.setAccountAddress(accountAddress)
.setUsdtTxId(transactionId)
.setUsdtAmount(transferValue)
.setTrxAmount(trxValue)
.setExchangeRate(oneUsdtToTrx)
.setOrginalExchangeRate(oneUsdtToTrx)
.setTrxTxId(txId);
usdtExchangeInfoMapper.insertUsdtExchangeInfo(usdtExchangeInfo);
}
/**
* U
*
* @param data
* @return
*/
private BigDecimal getTransferValue(Data data) {
String transFerName = ContractType.Transfer.name();
if (!transFerName.equals(data.getType())) {
log.warn("未知交易类型:{},交易数据:{}", data.getType(), JSONUtil.toJsonStr(data));
return null;
}
Token_info tokenInfo = data.getToken_info();
if (!Symbol.USDT.name().equals(tokenInfo.getSymbol())) {
log.warn("未知交易币种:{},交易数据:{}", tokenInfo.getSymbol(), JSONUtil.toJsonStr(data));
return null;
}
int decimals = tokenInfo.getDecimals();
//转账金额
BigDecimal transferValue = new BigDecimal(data.getValue()).movePointLeft(decimals);
if (transferValue.compareTo(BigDecimal.ONE) == -1) {
log.warn("交易金额小于1,交易数据:{}", JSONUtil.toJsonStr(data));
return null;
}
return transferValue;
}
/**
* 1U
*
* @return
* @throws NoSuchAlgorithmException
* @throws InvalidKeyException
*/
public BigDecimal getOneUsdtToTrx() throws NoSuchAlgorithmException, InvalidKeyException {
OkxResponse oksResponse = okxApi.getSingleTickerOkxResponse();
Preconditions.checkNotNull(oksResponse, "查询费率失败无法兑换");
String code = oksResponse.getCode();
Preconditions.checkState("0".equals(code), "okx响应码异常:" + JSONUtil.toJsonStr(oksResponse));
List<com.ruoyi.system.api.entity.okx.Data> oksResponseDataList = oksResponse.getData();
Preconditions.checkState(CollectionUtil.isNotEmpty(oksResponseDataList), "okx费率响应为空:" + JSONUtil.toJsonStr(oksResponse));
log.info("oksResponse:{}",oksResponse);
String last = oksResponseDataList.get(0).getLast();
BigDecimal oneUsdtToTrx = BigDecimal.ONE.divide(new BigDecimal(last)).setScale(6, BigDecimal.ROUND_HALF_DOWN);
return oneUsdtToTrx;
}
}

View File

@ -0,0 +1,63 @@
package com.ruoyi.system.mapper;
import com.ruoyi.common.core.domain.entity.UsdtExchangeInfo;
import java.util.List;
/**
* USDTMapper
*
* @author dorion
* @date 2024-04-19
*/
public interface UsdtExchangeInfoMapper
{
/**
* USDT
*
* @param idUsdtExchangeInfo USDT
* @return USDT
*/
public UsdtExchangeInfo selectUsdtExchangeInfoByIdUsdtExchangeInfo(Long idUsdtExchangeInfo);
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return USDT
*/
public List<UsdtExchangeInfo> selectUsdtExchangeInfoList(UsdtExchangeInfo usdtExchangeInfo);
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return
*/
public int insertUsdtExchangeInfo(UsdtExchangeInfo usdtExchangeInfo);
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return
*/
public int updateUsdtExchangeInfo(UsdtExchangeInfo usdtExchangeInfo);
/**
* USDT
*
* @param idUsdtExchangeInfo USDT
* @return
*/
public int deleteUsdtExchangeInfoByIdUsdtExchangeInfo(Long idUsdtExchangeInfo);
/**
* USDT
*
* @param idUsdtExchangeInfos
* @return
*/
public int deleteUsdtExchangeInfoByIdUsdtExchangeInfos(String[] idUsdtExchangeInfos);
}

View File

@ -60,12 +60,6 @@ public interface IMonitorAddressInfoService
* @return
*/
public int deleteMonitorAddressInfoByIdMonitorAddress(Long idMonitorAddress);
/*
List<MonitorAddressAccount> selectAllMonitorAddressAccount(MonitorAddressAccount monitorAddressAccountExample);
*/
List<MonitorAddressInfo> selectAllValidMonitorAddressAccount();
List<MonitorAddressInfo> selectAllValidMonitorAddressAccount(String busiType);
}

View File

@ -0,0 +1,65 @@
package com.ruoyi.system.service;
import com.ruoyi.common.core.domain.entity.UsdtExchangeInfo;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
/**
* USDTService
*
* @author dorion
* @date 2024-04-19
*/
public interface IUsdtExchangeInfoService
{
/**
* USDT
*
* @param idUsdtExchangeInfo USDT
* @return USDT
*/
public UsdtExchangeInfo selectUsdtExchangeInfoByIdUsdtExchangeInfo(Long idUsdtExchangeInfo);
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return USDT
*/
public List<UsdtExchangeInfo> selectUsdtExchangeInfoList(UsdtExchangeInfo usdtExchangeInfo);
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return
*/
public int insertUsdtExchangeInfo(UsdtExchangeInfo usdtExchangeInfo) throws Exception;
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return
*/
public int updateUsdtExchangeInfo(UsdtExchangeInfo usdtExchangeInfo);
/**
* USDT
*
* @param idUsdtExchangeInfos USDT
* @return
*/
public int deleteUsdtExchangeInfoByIdUsdtExchangeInfos(String idUsdtExchangeInfos);
/**
* USDT
*
* @param idUsdtExchangeInfo USDT
* @return
*/
public int deleteUsdtExchangeInfoByIdUsdtExchangeInfo(Long idUsdtExchangeInfo);
}

View File

@ -102,9 +102,10 @@ public class MonitorAddressInfoServiceImpl implements IMonitorAddressInfoService
}*/
@Override
public List<MonitorAddressInfo> selectAllValidMonitorAddressAccount() {
public List<MonitorAddressInfo> selectAllValidMonitorAddressAccount(String busiType) {
MonitorAddressInfo monitorAddressInfo = new MonitorAddressInfo();
monitorAddressInfo.setIsValid("Y");
monitorAddressInfo.setBusiType(busiType);
return monitorAddressInfoMapper.selectMonitorAddressInfoList(monitorAddressInfo);
}

View File

@ -0,0 +1,136 @@
package com.ruoyi.system.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.google.common.base.Preconditions;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.AccountAddressInfo;
import com.ruoyi.common.core.domain.entity.UsdtExchangeInfo;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.system.handler.UsdtTransferHandler;
import com.ruoyi.system.mapper.AccountAddressInfoMapper;
import com.ruoyi.system.mapper.UsdtExchangeInfoMapper;
import com.ruoyi.system.service.IUsdtExchangeInfoService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
/**
* USDTService
*
* @author dorion
* @date 2024-04-19
*/
@Service
public class UsdtExchangeInfoServiceImpl implements IUsdtExchangeInfoService {
@Autowired
private UsdtExchangeInfoMapper usdtExchangeInfoMapper;
@Autowired
private UsdtTransferHandler usdtTransferHandler;
@Autowired
private AccountAddressInfoMapper accountAddressInfoMapper;
@Autowired
private AccountAddressInfoServiceImpl accountAddressInfoService;
@Autowired
private SysConfigServiceImpl configService;
/**
* USDT
*
* @param idUsdtExchangeInfo USDT
* @return USDT
*/
@Override
public UsdtExchangeInfo selectUsdtExchangeInfoByIdUsdtExchangeInfo(Long idUsdtExchangeInfo) {
return usdtExchangeInfoMapper.selectUsdtExchangeInfoByIdUsdtExchangeInfo(idUsdtExchangeInfo);
}
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return USDT
*/
@Override
public List<UsdtExchangeInfo> selectUsdtExchangeInfoList(UsdtExchangeInfo usdtExchangeInfo) {
return usdtExchangeInfoMapper.selectUsdtExchangeInfoList(usdtExchangeInfo);
}
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return
*/
@Override
public int insertUsdtExchangeInfo(UsdtExchangeInfo usdtExchangeInfo) throws Exception {
BigDecimal oneUsdtToTrx;
String systronApiSwitch = configService.selectConfigByKey("sys.tron.api");
if (UserConstants.YES.equals(systronApiSwitch)) {
oneUsdtToTrx = usdtTransferHandler.getOneUsdtToTrx();
} else {
oneUsdtToTrx = new BigDecimal("7.565113");
}
BigDecimal usdtAmount = usdtExchangeInfo.getUsdtAmount();
BigDecimal trxValue = usdtAmount.multiply(oneUsdtToTrx);
String accountAddress = usdtExchangeInfo.getAccountAddress();
if (StringUtils.isEmpty(accountAddress)) {
AccountAddressInfo accountAddressInfoExample = new AccountAddressInfo();
accountAddressInfoExample.setIsValid("Y");
accountAddressInfoExample.setBusiType(DictUtils.getDictValue("sys_busi_type", "USDT兑TRX"));
List<AccountAddressInfo> accountAddressInfoList = accountAddressInfoMapper.selectAccountAddressInfoList(accountAddressInfoExample);
Preconditions.checkState(CollectionUtil.isNotEmpty(accountAddressInfoList), "无合适的转trx账户,请先设置");
accountAddress = accountAddressInfoList.get(0).getAddress();
}
String decryptPrivateKey = accountAddressInfoService.getDecryptPrivateKey(accountAddress);
String tronApiKey = DictUtils.getDictValue("sys_tron_api_key", "synp@outlook");
String fromAddress = usdtExchangeInfo.getFromAddress();
usdtTransferHandler.
doTransferUsdtAndStore(oneUsdtToTrx, tronApiKey, decryptPrivateKey, accountAddress, fromAddress, trxValue, null, null, usdtAmount);
return 1;
}
/**
* USDT
*
* @param usdtExchangeInfo USDT
* @return
*/
@Override
public int updateUsdtExchangeInfo(UsdtExchangeInfo usdtExchangeInfo) {
return usdtExchangeInfoMapper.updateUsdtExchangeInfo(usdtExchangeInfo);
}
/**
* USDT
*
* @param idUsdtExchangeInfos USDT
* @return
*/
@Override
public int deleteUsdtExchangeInfoByIdUsdtExchangeInfos(String idUsdtExchangeInfos) {
return usdtExchangeInfoMapper.deleteUsdtExchangeInfoByIdUsdtExchangeInfos(Convert.toStrArray(idUsdtExchangeInfos));
}
/**
* USDT
*
* @param idUsdtExchangeInfo USDT
* @return
*/
@Override
public int deleteUsdtExchangeInfoByIdUsdtExchangeInfo(Long idUsdtExchangeInfo) {
return usdtExchangeInfoMapper.deleteUsdtExchangeInfoByIdUsdtExchangeInfo(idUsdtExchangeInfo);
}
}

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.UsdtExchangeInfoMapper">
<resultMap type="UsdtExchangeInfo" id="UsdtExchangeInfoResult">
<result property="idUsdtExchangeInfo" column="id_usdt_exchange_info" />
<result property="fromAddress" column="from_address" />
<result property="toAddress" column="to_address" />
<result property="accountAddress" column="account_address" />
<result property="usdtTxId" column="usdt_tx_id" />
<result property="usdtAmount" column="usdt_amount" />
<result property="trxAmount" column="trx_amount" />
<result property="exchangeRate" column="exchange_rate" />
<result property="trxTxId" column="trx_tx_id" />
<result property="orginalExchangeRate" column="orginal_exchange_rate" />
<result property="fcd" column="fcd" />
<result property="fcu" column="fcu" />
<result property="lcd" column="lcd" />
<result property="lcu" column="lcu" />
</resultMap>
<sql id="selectUsdtExchangeInfoVo">
select id_usdt_exchange_info, from_address, to_address, account_address, usdt_tx_id, usdt_amount, trx_amount, exchange_rate, trx_tx_id, orginal_exchange_rate, fcd, fcu, lcd, lcu from usdt_exchange_info
</sql>
<select id="selectUsdtExchangeInfoList" parameterType="UsdtExchangeInfo" resultMap="UsdtExchangeInfoResult">
<include refid="selectUsdtExchangeInfoVo"/>
<where>
<if test="fromAddress != null and fromAddress != ''"> and from_address = #{fromAddress}</if>
<if test="toAddress != null and toAddress != ''"> and to_address = #{toAddress}</if>
<if test="accountAddress != null and accountAddress != ''"> and account_address = #{accountAddress}</if>
<if test="usdtTxId != null and usdtTxId != ''"> and usdt_tx_id = #{usdtTxId}</if>
<if test="usdtAmount != null "> and usdt_amount = #{usdtAmount}</if>
<if test="trxAmount != null "> and trx_amount = #{trxAmount}</if>
<if test="exchangeRate != null "> and exchange_rate = #{exchangeRate}</if>
<if test="trxTxId != null and trxTxId != ''"> and trx_tx_id = #{trxTxId}</if>
<if test="orginalExchangeRate != null "> and orginal_exchange_rate = #{orginalExchangeRate}</if>
<if test="fcd != null "> and fcd = #{fcd}</if>
<if test="fcu != null and fcu != ''"> and fcu = #{fcu}</if>
<if test="lcd != null "> and lcd = #{lcd}</if>
<if test="lcu != null and lcu != ''"> and lcu = #{lcu}</if>
</where>
</select>
<select id="selectUsdtExchangeInfoByIdUsdtExchangeInfo" parameterType="Long" resultMap="UsdtExchangeInfoResult">
<include refid="selectUsdtExchangeInfoVo"/>
where id_usdt_exchange_info = #{idUsdtExchangeInfo}
</select>
<insert id="insertUsdtExchangeInfo" parameterType="UsdtExchangeInfo" useGeneratedKeys="true" keyProperty="idUsdtExchangeInfo">
insert into usdt_exchange_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="fromAddress != null">from_address,</if>
<if test="toAddress != null">to_address,</if>
<if test="accountAddress != null">account_address,</if>
<if test="usdtTxId != null">usdt_tx_id,</if>
<if test="usdtAmount != null">usdt_amount,</if>
<if test="trxAmount != null">trx_amount,</if>
<if test="exchangeRate != null">exchange_rate,</if>
<if test="trxTxId != null">trx_tx_id,</if>
<if test="orginalExchangeRate != null">orginal_exchange_rate,</if>
<if test="fcd != null">fcd,</if>
<if test="fcu != null">fcu,</if>
<if test="lcd != null">lcd,</if>
<if test="lcu != null">lcu,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="fromAddress != null">#{fromAddress},</if>
<if test="toAddress != null">#{toAddress},</if>
<if test="accountAddress != null">#{accountAddress},</if>
<if test="usdtTxId != null">#{usdtTxId},</if>
<if test="usdtAmount != null">#{usdtAmount},</if>
<if test="trxAmount != null">#{trxAmount},</if>
<if test="exchangeRate != null">#{exchangeRate},</if>
<if test="trxTxId != null">#{trxTxId},</if>
<if test="orginalExchangeRate != null">#{orginalExchangeRate},</if>
<if test="fcd != null">#{fcd},</if>
<if test="fcu != null">#{fcu},</if>
<if test="lcd != null">#{lcd},</if>
<if test="lcu != null">#{lcu},</if>
</trim>
</insert>
<update id="updateUsdtExchangeInfo" parameterType="UsdtExchangeInfo">
update usdt_exchange_info
<trim prefix="SET" suffixOverrides=",">
<if test="fromAddress != null">from_address = #{fromAddress},</if>
<if test="toAddress != null">to_address = #{toAddress},</if>
<if test="accountAddress != null">account_address = #{accountAddress},</if>
<if test="usdtTxId != null">usdt_tx_id = #{usdtTxId},</if>
<if test="usdtAmount != null">usdt_amount = #{usdtAmount},</if>
<if test="trxAmount != null">trx_amount = #{trxAmount},</if>
<if test="exchangeRate != null">exchange_rate = #{exchangeRate},</if>
<if test="trxTxId != null">trx_tx_id = #{trxTxId},</if>
<if test="orginalExchangeRate != null">orginal_exchange_rate = #{orginalExchangeRate},</if>
<if test="fcd != null">fcd = #{fcd},</if>
<if test="fcu != null">fcu = #{fcu},</if>
<if test="lcd != null">lcd = #{lcd},</if>
<if test="lcu != null">lcu = #{lcu},</if>
</trim>
where id_usdt_exchange_info = #{idUsdtExchangeInfo}
</update>
<delete id="deleteUsdtExchangeInfoByIdUsdtExchangeInfo" parameterType="Long">
delete from usdt_exchange_info where id_usdt_exchange_info = #{idUsdtExchangeInfo}
</delete>
<delete id="deleteUsdtExchangeInfoByIdUsdtExchangeInfos" parameterType="String">
delete from usdt_exchange_info where id_usdt_exchange_info in
<foreach item="idUsdtExchangeInfo" collection="array" open="(" separator="," close=")">
#{idUsdtExchangeInfo}
</foreach>
</delete>
</mapper>