package com.ichaoj.ams.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ichaoj.ams.common.bean.Wallet;
import com.ichaoj.ams.common.util.EthWalletPrivate;
import com.ichaoj.ams.common.util.WalletUtil;
import com.ichaoj.ams.entity.AmsAddressAccount;
import com.ichaoj.ams.mapper.AmsAddressAccountMapper;
import com.ichaoj.ams.request.address.BatchAddressRequest;
import com.ichaoj.ams.request.address.BatchKeyStoreRequest;
import com.ichaoj.ams.request.address.PageAddressRequest;
import com.ichaoj.ams.response.address.AddressResponse;
import com.ichaoj.ams.service.IAmsAddressAccountService;
import com.ichaoj.ams.service.ZipService;
import com.ichaoj.common.exception.ErrorServiceException;
import com.ichaoj.common.model.PublicPage;
import com.ichaoj.common.model.PublicResult;
import com.ichaoj.common.model.PublicUserInfo;
import com.ichaoj.disk.provider.client.DiskClient;
import com.ichaoj.disk.provider.resp.FileResponse;
import com.ichaoj.mybatis.service.SuperWhaleServiceImpl;
import com.ichaoj.web.context.SuperWhaleContext;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import static com.ichaoj.ams.constant.AmsConstant.WALLET_FILE_PATH;
/**
*
* 地址管理 服务实现类
*
*
* @author cjwen
* @since 2023-05-06
*/
@Service
@Slf4j
public class AmsAddressAccountServiceImpl extends SuperWhaleServiceImpl implements IAmsAddressAccountService {
@Autowired(required = false)
private AmsAddressAccountMapper baseMapper;
@Resource
private DiskClient diskClient;
@Resource
private ZipService zipService;
@Override
public List batchCreateAddress(BatchAddressRequest batchAddressRequest) {
String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
boolean existGroup = this.checkGroupName(batchAddressRequest.getGroupName(), userId);
if (existGroup) {
throw new ErrorServiceException("Please change the groupName because you have created");
}
long start = System.currentTimeMillis();
List wallets = WalletUtil.batchCreateWallet(userId, batchAddressRequest.getNumWallet(), batchAddressRequest.getPassword(), batchAddressRequest.getGroupName());
long end = System.currentTimeMillis();
log.info("本次共创建{}个钱包地址,耗时 {} 秒", wallets.size(), (end - start) / 1000);
long saveStart = System.currentTimeMillis();
wallets.forEach(wallet -> {
try {
String keystore = wallet.getKeystore();
// File file = FileUtil.createTempFile(new File(keystore));
// MultipartFile multipartFile = com.ichaoj.ccb.common.util.FileUtil.convertFileToMultipartFile(file);
// 上传服务器
// PublicResult result = diskClient.uploadFile(multipartFile, "ccb_address_account", "keystore");
// String fileId = result.getData();
// 将生成的地址存入数据库
AmsAddressAccount addressAccount = getAddressCountInstance(userId, wallet.getAddress(), 1);
// if (result.isSuccess() && StrUtil.isNotBlank(fileId)) {
// addressAccount.setKeystoreLocation(getLocation(fileId));
// }
addressAccount.setKeystore(keystore);
addressAccount.setGroupName(batchAddressRequest.getGroupName());
this.save(addressAccount);
} catch (Exception e) {
wallets.forEach(w -> {
EthWalletPrivate walletPrivate = JSONObject.parseObject(w.getKeystore(), EthWalletPrivate.class);
File file = new File(WALLET_FILE_PATH + userId + File.separator + batchAddressRequest.getGroupName() + File.separator + walletPrivate.getKeyStoreName());
if (file.exists()) {
file.delete();
}
});
throw new ErrorServiceException(e.getMessage());
}
});
long saveEnd = System.currentTimeMillis();
log.info("保存钱包地址信息到数据库耗时 {} ms", saveEnd - saveStart);
return wallets.stream().map(Wallet::getAddress).collect(Collectors.toList());
}
@Override
public boolean checkGroupName(String groupName, String userId) {
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
wrapper.eq(AmsAddressAccount::getUserId, userId)
.eq(AmsAddressAccount::getGroupName, groupName);
return this.count(wrapper) > 0;
}
@Override
public PublicPage pageAddress(PageAddressRequest pageAddressRequest) {
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
wrapper.eq(StrUtil.isNotBlank(pageAddressRequest.getGroupName()), AmsAddressAccount::getGroupName, pageAddressRequest.getGroupName())
.orderByDesc(AmsAddressAccount::getCreateTime);
Page result = this.page(this.buildPageObj(pageAddressRequest), wrapper);
return this.convertPublicPage(result, resp -> BeanUtil.copyProperties(resp, AddressResponse.class));
}
private String getLocation(String fileId) {
PublicResult result = diskClient.getFileById(fileId);
FileResponse data = result.getData();
if (result.isSuccess() && data != null) {
return data.getFileUrl();
}
return null;
}
/**
* 添加精品号
*
* @param address 精品号地址
*/
@Override
public void addPremiumAddress(String address) {
String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
AmsAddressAccount account = getAddressCountInstance(userId, address, 0);
this.save(account);
}
@Override
@SneakyThrows
public void batchKeystore(String groupName, String password, HttpServletResponse response) {
String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
boolean existGroup = this.checkGroupName(groupName, userId);
if (!existGroup) {
throw new ErrorServiceException("The address group name is incorrect");
}
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
wrapper.eq(AmsAddressAccount::getUserId, userId)
.eq(AmsAddressAccount::getGroupName, groupName);
List list = this.list(wrapper);
String keystoreJson = list.get(0).getKeystore();
EthWalletPrivate ethWalletPrivate = JSONObject.parseObject(keystoreJson, EthWalletPrivate.class);
if (!password.equals(ethWalletPrivate.getPassword())) {
throw new ErrorServiceException("PASSWORD OR GROUP NAME ERROR!");
}
// 将json_files目录下的所有文件打包成zip
File zipFile = new File(WalletUtil.getEncryptPwd(groupName) + ".zip");
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile));
File fileDir = new File(WALLET_FILE_PATH + userId + File.separator + WalletUtil.getEncryptPwd(groupName));
File[] files = fileDir.listFiles();
for (File file : files) {
ZipEntry entry = new ZipEntry(file.getName());
zos.putNextEntry(entry);
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
fis.close();
}
zos.close();
// 设置响应头,使浏览器下载该zip文件
response.addHeader("Content-Disposition", "attachment;filename=" + WalletUtil.getEncryptPwd(groupName) + ".zip");
InputStream inputStream = new FileInputStream(zipFile);
byte[] buffer = new byte[1024];
OutputStream outputStream = response.getOutputStream();
int len;
while ((len = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, len);
}
inputStream.close();
outputStream.close();
}
private void getFiles(BatchKeyStoreRequest keyStoreRequest, Set files, List list) {
try {
String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
Optional optional = list.stream().findAny();
if (optional.isPresent()) {
AmsAddressAccount account = optional.get();
String keystoreJson = account.getKeystore();
EthWalletPrivate ethWalletPrivate = JSONObject.parseObject(keystoreJson, EthWalletPrivate.class);
String pwd = WalletUtil.getEncryptPwd(keyStoreRequest.getPassword());
if (pwd.equals(ethWalletPrivate.getPassword())) {
files.addAll(
list.stream().map(
a -> new File(WALLET_FILE_PATH + userId + a.getGroupName() + File.separator + ethWalletPrivate.getKeyStoreName())
).collect(Collectors.toList()));
} else {
throw new ErrorServiceException("PASSWORD ERROR");
}
}
} catch (Exception e) {
log.error("getFiles 方法出错:{}", e.getMessage());
}
}
private AmsAddressAccount getAddressCountInstance(String userId, String address, Integer addressType) {
AmsAddressAccount account = new AmsAddressAccount();
account.setAddress(address);
account.setAddressType(addressType);
account.setCreateTime(LocalDateTime.now());
account.setUserId(userId);
return account;
}
}