
io.nuls.sdk.contract.service.impl.ContractServiceImpl Maven / Gradle / Ivy
The newest version!
package io.nuls.sdk.contract.service.impl;
import io.nuls.sdk.accountledger.model.Input;
import io.nuls.sdk.accountledger.model.TransactionCreatedReturnInfo;
import io.nuls.sdk.accountledger.utils.ConvertCoinTool;
import io.nuls.sdk.accountledger.utils.LedgerUtil;
import io.nuls.sdk.contract.ContractUtil;
import io.nuls.sdk.contract.model.ContractTransactionCreatedReturnInfo;
import io.nuls.sdk.contract.service.ContractService;
import io.nuls.sdk.core.contast.SDKConstant;
import io.nuls.sdk.core.contast.TransactionErrorCode;
import io.nuls.sdk.core.crypto.Hex;
import io.nuls.sdk.core.model.*;
import io.nuls.sdk.core.model.transaction.CallContractTransaction;
import io.nuls.sdk.core.model.transaction.CreateContractTransaction;
import io.nuls.sdk.core.model.transaction.DeleteContractTransaction;
import io.nuls.sdk.core.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* contract sdk
* Created by wangkun23 on 2018/10/8.
*/
public class ContractServiceImpl implements ContractService {
final Logger logger = LoggerFactory.getLogger(ContractServiceImpl.class);
private static ContractService instance = new ContractServiceImpl();
/**
* instance
*
* @return
*/
public static ContractService getInstance() {
return instance;
}
/**
* create contract transaction
*
* @param sender
* @param gasLimit
* @param price
* @param contractCodeHex
* @param args
* @param remark
* @return
*/
@Override
public Result createContractTransaction(String sender, Long gasLimit, Long price, String contractCodeHex, Object[] args, String remark, List utxos) {
try {
Na value = Na.ZERO;
long totalGas = LongUtils.mul(gasLimit, price);
Na totalNa = Na.valueOf(totalGas);
byte[] contractCode = Hex.decode(contractCodeHex);
byte[] senderBytes = AddressTool.getAddress(sender);
// 生成一个地址作为智能合约地址
Address contractAddress = AccountTool.createContractAddress();
byte[] contractAddressBytes = contractAddress.getAddressBytes();
// 组装txData
CreateContractData txData = new CreateContractData();
txData.setSender(senderBytes);
txData.setContractAddress(contractAddressBytes);
txData.setValue(value.getValue());
txData.setGasLimit(gasLimit);
txData.setPrice(price);
txData.setCodeLen(contractCode.length);
txData.setCode(contractCode);
if (args != null) {
txData.setArgsCount((byte) args.length);
if (args.length > 0) {
txData.setArgs(ContractUtil.twoDimensionalArray(args));
}
}
/**
* 组装交易数据
*/
CreateContractTransaction tx = new CreateContractTransaction();
if (StringUtils.isNotBlank(remark)) {
try {
tx.setRemark(remark.getBytes(SDKConstant.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
tx.setTime(TimeService.currentTimeMillis());
tx.setTxData(txData);
CoinData coinData = new CoinData();
List coinList = ConvertCoinTool.convertCoinList(utxos);
CoinDataResult coinDataResult = TransactionTool.getCoinData(senderBytes, totalNa, tx.size(), TransactionFeeCalculator.MIN_PRECE_PRE_1024_BYTES, coinList);
if (!coinDataResult.isEnough()) {
return Result.getFailed(TransactionErrorCode.INSUFFICIENT_BALANCE);
}
coinData.setFrom(coinDataResult.getCoinList());
// 找零的UTXO
if (coinDataResult.getChange() != null) {
coinData.getTo().add(coinDataResult.getChange());
}
tx.setCoinData(coinData);
// 重置为0,重新计算交易对象的size
tx.setSize(0);
if (tx.getSize() > TransactionFeeCalculator.MAX_TX_SIZE) {
return Result.getFailed(TransactionErrorCode.DATA_SIZE_ERROR);
}
TransactionCreatedReturnInfo returnInfo = LedgerUtil.makeReturnInfo(tx);
Map map = new LinkedHashMap<>();
map.put("value", new ContractTransactionCreatedReturnInfo(returnInfo, AddressTool.getStringAddressByBytes(contractAddress.getAddressBytes())));
return Result.getSuccess().setData(map);
} catch (Exception e) {
Log.error(e);
return Result.getFailed(e.getMessage());
}
}
/**
* @param sender
* @param value
* @param gasLimit
* @param price
* @param contractAddress
* @param methodName
* @param methodDesc
* @param args
* @param remark
* @param utxos
* @return
*/
@Override
public Result callContractTransaction(String sender, Long longValue, Long gasLimit, Long price, String contractAddress, String methodName, String methodDesc, Object[] args, String remark, List utxos) {
try {
byte[] senderBytes = AddressTool.getAddress(sender);
byte[] contractAddressBytes = AddressTool.getAddress(contractAddress);
Na value;
if (longValue == null) {
value = Na.ZERO;
} else {
value = Na.valueOf(longValue);
}
CallContractTransaction tx = new CallContractTransaction();
if (StringUtils.isNotBlank(remark)) {
try {
tx.setRemark(remark.getBytes(SDKConstant.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
Log.error(e);
throw new RuntimeException(e);
}
}
tx.setTime(TimeService.currentTimeMillis());
long gasUsed = gasLimit.longValue();
Na imputedNa = Na.valueOf(LongUtils.mul(gasUsed, price));
// 总花费
Na totalNa = imputedNa.add(value);
// 组装txData
CallContractData callContractData = new CallContractData();
callContractData.setContractAddress(contractAddressBytes);
callContractData.setSender(senderBytes);
callContractData.setValue(value.getValue());
callContractData.setPrice(price.longValue());
callContractData.setGasLimit(gasLimit.longValue());
callContractData.setMethodName(methodName);
callContractData.setMethodDesc(methodDesc);
if (args != null) {
callContractData.setArgsCount((byte) args.length);
callContractData.setArgs(ContractUtil.twoDimensionalArray(args));
}
tx.setTxData(callContractData);
CoinData coinData = new CoinData();
// 向智能合约账户转账
if (value.isGreaterThan(Na.ZERO)) {
Coin toCoin = new Coin(contractAddressBytes, value);
coinData.getTo().add(toCoin);
}
List coinList = ConvertCoinTool.convertCoinList(utxos);
CoinDataResult coinDataResult = TransactionTool.getCoinData(senderBytes, totalNa, tx.size() + coinData.size(), TransactionFeeCalculator.MIN_PRECE_PRE_1024_BYTES, coinList);
if (!coinDataResult.isEnough()) {
return Result.getFailed(TransactionErrorCode.INSUFFICIENT_BALANCE);
}
coinData.setFrom(coinDataResult.getCoinList());
// 找零的UTXO
if (coinDataResult.getChange() != null) {
coinData.getTo().add(coinDataResult.getChange());
}
tx.setCoinData(coinData);
// 重置为0,重新计算交易对象的size
tx.setSize(0);
if (tx.getSize() > TransactionFeeCalculator.MAX_TX_SIZE) {
return Result.getFailed(TransactionErrorCode.DATA_SIZE_ERROR);
}
TransactionCreatedReturnInfo returnInfo = LedgerUtil.makeReturnInfo(tx);
Map map = new LinkedHashMap<>();
map.put("value", new ContractTransactionCreatedReturnInfo(returnInfo, contractAddress));
return Result.getSuccess().setData(map);
} catch (Exception e) {
Log.error(e);
return Result.getFailed(e.getMessage());
}
}
/**
* delete smart contract
*
* @param sender
* @param contractAddress
* @param remark
* @param utxos
* @return
*/
@Override
public Result deleteContractTransaction(String sender, String contractAddress, String remark, List utxos) {
try {
DeleteContractTransaction tx = new DeleteContractTransaction();
if (StringUtils.isNotBlank(remark)) {
try {
tx.setRemark(remark.getBytes(SDKConstant.DEFAULT_ENCODING));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
tx.setTime(TimeService.currentTimeMillis());
byte[] senderBytes = AddressTool.getAddress(sender);
byte[] contractAddressBytes = AddressTool.getAddress(contractAddress);
// 组装txData
DeleteContractData deleteContractData = new DeleteContractData();
deleteContractData.setContractAddress(contractAddressBytes);
deleteContractData.setSender(senderBytes);
tx.setTxData(deleteContractData);
/**
* calculator transfer fee
*/
List coinList = ConvertCoinTool.convertCoinList(utxos);
CoinDataResult coinDataResult = TransactionTool.getCoinData(senderBytes, Na.ZERO, tx.size(), TransactionFeeCalculator.MIN_PRECE_PRE_1024_BYTES, coinList);
if (!coinDataResult.isEnough()) {
return Result.getFailed(TransactionErrorCode.INSUFFICIENT_BALANCE);
}
/**
* build coin data
*/
CoinData coinData = new CoinData();
coinData.setFrom(coinDataResult.getCoinList());
// 找零的UTXO
if (coinDataResult.getChange() != null) {
coinData.getTo().add(coinDataResult.getChange());
}
tx.setCoinData(coinData);
// 重置为0,重新计算交易对象的size
tx.setSize(0);
if (tx.getSize() > TransactionFeeCalculator.MAX_TX_SIZE) {
return Result.getFailed(TransactionErrorCode.DATA_SIZE_ERROR);
}
TransactionCreatedReturnInfo returnInfo = LedgerUtil.makeReturnInfo(tx);
Map map = new LinkedHashMap<>();
map.put("value", new ContractTransactionCreatedReturnInfo(returnInfo, contractAddress));
return Result.getSuccess().setData(map);
} catch (Exception e) {
Log.error(e);
return Result.getFailed(e.getMessage());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy