| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- package com.izouma.nineth.service;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONArray;
- import com.alipay.mychain.sdk.api.utils.Utils;
- import com.antfinancial.mychain.baas.tool.restclient.RestClient;
- import com.antfinancial.mychain.baas.tool.restclient.RestClientProperties;
- import com.antfinancial.mychain.baas.tool.restclient.model.CallRestBizParam;
- import com.antfinancial.mychain.baas.tool.restclient.model.Method;
- import com.antfinancial.mychain.baas.tool.restclient.model.ReceiptDecoration;
- import com.antfinancial.mychain.baas.tool.restclient.response.BaseResp;
- import com.izouma.nineth.config.Constants;
- import com.izouma.nineth.config.GeneralProperties;
- import com.izouma.nineth.dto.NFT;
- import com.izouma.nineth.dto.NFTAccount;
- import com.izouma.nineth.event.AccountCreatedEvent;
- import com.izouma.nineth.exception.BusinessException;
- import com.izouma.nineth.utils.SnowflakeIdWorker;
- import lombok.AllArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.codec.binary.Hex;
- import org.springframework.context.ApplicationContext;
- import org.springframework.core.env.Environment;
- import org.springframework.retry.annotation.Backoff;
- import org.springframework.retry.annotation.Retryable;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import java.math.BigInteger;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- @Service
- @Slf4j
- @AllArgsConstructor
- public class NFTService {
- private final RestClient restClient;
- private final RestClientProperties restClientProperties;
- private final GeneralProperties generalProperties;
- private final SnowflakeIdWorker snowflakeIdWorker;
- private final ApplicationContext context;
- private final Environment env;
- @Retryable(maxAttempts = 10, backoff = @Backoff(delay = 5000), value = BusinessException.class)
- public NFTAccount createAccount(String username) {
- CallRestBizParam callRestBizParam = CallRestBizParam.builder()
- .orderId(String.valueOf(snowflakeIdWorker.nextId()))
- .bizid(Constants.bizId)
- .account(restClientProperties.getAccount())
- .mykmsKeyId(restClientProperties.getKmsId())
- .newAccountId(username)
- .newAccountKmsId(Constants.kmsKey)
- .method(Method.TENANTCREATEACCUNT)
- .gas(100000L).build();
- try {
- BaseResp baseResp = restClient.chainCallForBiz(callRestBizParam);
- NFTAccount account = new NFTAccount(username, Constants.kmsKey, baseResp.getData());
- if (baseResp.isSuccess() || "400123".equals(baseResp.getCode())) {
- log.info("创建账户成功 {}", account);
- return account;
- } else {
- throw new RuntimeException(baseResp.getCode());
- }
- } catch (Exception e) {
- e.printStackTrace();
- log.error("创建账户失败", e);
- throw new BusinessException("创建账户失败");
- }
- }
- @Retryable(maxAttempts = 10, backoff = @Backoff(delay = 5000), value = BusinessException.class)
- public synchronized NFT createToken(String toAccount, String tokenId) throws Exception {
- log.info("开始执行EVM合约mint, toAccount: {}, tokenId: {}", toAccount, tokenId);
- if (Arrays.asList(env.getActiveProfiles()).contains("notifytest")) {
- NFT nft = new NFT("1", tokenId, new BigInteger("1"), new BigInteger("1"));
- log.info("测试服生成假token {}", tokenId);
- return nft;
- }
- JSONArray jsonArray = new JSONArray();
- jsonArray.add(Utils.getIdentityByName(toAccount));
- jsonArray.add(new BigInteger(tokenId, 16));
- CallRestBizParam callRestBizParam = CallRestBizParam.builder()
- .orderId(String.valueOf(snowflakeIdWorker.nextId()))
- .bizid(restClientProperties.getBizid())
- .account(restClientProperties.getAccount())
- .contractName(generalProperties.getContractName())
- .methodSignature("mint(identity,uint256)")
- .inputParamListStr(jsonArray.toJSONString())
- .outTypes("[]")//合约返回值类型
- .mykmsKeyId(restClientProperties.getKmsId())
- .method(Method.CALLCONTRACTBIZASYNC)
- .tenantid(restClientProperties.getTenantid())
- .gas(500000L)
- .build();
- BaseResp resp = restClient.bizChainCallWithReceipt(callRestBizParam);
- if (!resp.isSuccess()) {
- log.info("EVM合约执行失败: code: {}, data: {}, toAccount: {}, tokenId: {}", resp.getCode(), resp.getData(), toAccount, tokenId);
- }
- if ("200".equals(resp.getCode())) {
- log.info("EVM合约执行成功");
- // 合约调用交易回执内容
- ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
- BigInteger gasUsed = txReceipt.getGasUsed();
- long result = txReceipt.getResult();
- log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
- NFT nft = new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
- log.info("NFT生成成功 {}", nft);
- return nft;
- } else if ("211".equals(resp.getCode())) {
- log.error("EVM合约执行限流");
- } else if ("10201".equals(resp.getCode())) {
- // 异步交易未成功需要根据状态码判断交易状态
- ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
- String out = new String(matchAndReplaceNonEnglishChar(txReceipt.getOutput()));
- // 异步交易未成功需要根据状态码判断交易状态
- log.error("EVM合约执行未成功: code: {}, out: {}, tokenId: {}", resp.getCode(), out, tokenId);
- if (out.endsWith("ERC721: token already minted")) {
- return new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
- }
- }
- throw new BusinessException("执行EVM合约mint失败");
- }
- public static byte[] matchAndReplaceNonEnglishChar(byte[] data) {
- List<Byte> list = new ArrayList<>();
- for (byte c : data) {
- if (c >= 32 && c <= 127) {
- list.add(c);
- }
- }
- byte[] bytes = new byte[list.size()];
- for (int i = 0; i < list.size(); i++) {
- bytes[i] = list.get(i);
- }
- return bytes;
- }
- public String ownerOf(String tokenId) throws Exception {
- CallRestBizParam callRestBizParam = CallRestBizParam.builder()
- .orderId(String.valueOf(snowflakeIdWorker.nextId()))
- .bizid(restClientProperties.getBizid())
- .account(restClientProperties.getAccount())
- .contractName(generalProperties.getContractName())
- .methodSignature("ownerOf(uint256)")
- .inputParamListStr("[" + new BigInteger(tokenId, 16) + "]")
- .outTypes("[identity]")//合约返回值类型
- .mykmsKeyId(restClientProperties.getKmsId())
- .method(Method.CALLCONTRACTBIZASYNC)
- .tenantid(restClientProperties.getTenantid())
- .gas(500000L)
- .build();
- BaseResp resp = restClient.bizChainCallWithReceipt(callRestBizParam);
- if (!resp.isSuccess()) {
- log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
- }
- if ("200".equals(resp.getCode())) {
- log.info("EVM合约执行成功");
- // 合约调用交易回执内容
- ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
- BigInteger gasUsed = txReceipt.getGasUsed();
- long result = txReceipt.getResult();
- log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
- String identity = Hex.encodeHexString(txReceipt.getOutput());
- log.info("owner is: {}", identity);
- return identity;
- } else {
- // 异步交易未成功需要根据状态码判断交易状态
- log.error("EVM合约执行未成功: " + resp.getCode());
- throw new BusinessException("EVM合约执行未成功: " + resp.getCode());
- }
- }
- public NFT transferToken(String tokenId, String fromAccount, String toAccount) throws Exception {
- JSONArray jsonArray = new JSONArray();
- jsonArray.add(Utils.getIdentityByName("raex_official"));
- jsonArray.add(Utils.getIdentityByName("9th_HCWWflAZ_"));
- jsonArray.add("95057808871064671354760012409081314299");
- CallRestBizParam callRestBizParam = CallRestBizParam.builder()
- .orderId(String.valueOf(snowflakeIdWorker.nextId()))
- .bizid(restClientProperties.getBizid())
- .account(restClientProperties.getAccount())
- .contractName("raex12")
- .methodSignature("ownerTransfer(identity,identity,uint256)")
- .inputParamListStr(jsonArray.toJSONString())
- .outTypes("[]")//合约返回值类型
- .mykmsKeyId(restClientProperties.getKmsId())
- .method(Method.CALLCONTRACTBIZASYNC)
- .tenantid(restClientProperties.getTenantid())
- .gas(500000L)
- .build();
- BaseResp resp = restClient.bizChainCallWithReceipt(callRestBizParam);
- if (!resp.isSuccess()) {
- log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
- }
- if ("200".equals(resp.getCode())) {
- log.info("EVM合约执行成功");
- // 合约调用交易回执内容
- ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
- BigInteger gasUsed = txReceipt.getGasUsed();
- long result = txReceipt.getResult();
- log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
- return new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
- } else {
- // 异步交易未成功需要根据状态码判断交易状态
- log.error("EVM合约执行未成功: " + resp.getCode());
- }
- throw new BusinessException("转移token失败");
- }
- public NFT setApprovalForAll(String account) throws Exception {
- JSONArray jsonArray = new JSONArray();
- jsonArray.add(Utils.getIdentityByName(account));
- jsonArray.add(true);
- CallRestBizParam callRestBizParam = CallRestBizParam.builder()
- .orderId(String.valueOf(snowflakeIdWorker.nextId()))
- .bizid(restClientProperties.getBizid())
- .account(restClientProperties.getAccount())
- .contractName(generalProperties.getContractName())
- .methodSignature("setApprovalForAll(identity,bool)")
- .inputParamListStr(jsonArray.toJSONString())
- .outTypes("[]")//合约返回值类型
- .mykmsKeyId(restClientProperties.getKmsId())
- .method(Method.CALLCONTRACTBIZASYNC)
- .tenantid(restClientProperties.getTenantid())
- .gas(500000L)
- .build();
- BaseResp resp = restClient.bizChainCallWithReceipt(callRestBizParam);
- if (!resp.isSuccess()) {
- log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
- }
- if ("200".equals(resp.getCode())) {
- log.info("EVM合约执行成功");
- // 合约调用交易回执内容
- ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
- BigInteger gasUsed = txReceipt.getGasUsed();
- long result = txReceipt.getResult();
- log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
- } else {
- // 异步交易未成功需要根据状态码判断交易状态
- log.error("EVM合约执行未成功: " + resp.getCode());
- }
- throw new BusinessException("创建nft失败");
- }
- public void deployContract(String name, String code) throws Exception {
- String orderId = "order_" + System.currentTimeMillis();
- CallRestBizParam callRestBizParam = CallRestBizParam.builder()
- .orderId(orderId)
- .bizid(restClientProperties.getBizid())
- .account(restClientProperties.getAccount())
- .contractName(name)
- .contractCode(code)
- .mykmsKeyId(restClientProperties.getKmsId())
- .method(Method.DEPLOYCONTRACTFORBIZ)
- .tenantid(restClientProperties.getTenantid())
- .gas(1000000L).build();
- BaseResp resp = restClient.chainCallForBiz(callRestBizParam);
- if (!resp.isSuccess()) {
- log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
- }
- log.info("EVM合约执行成功");
- // 合约调用交易回执内容
- ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
- BigInteger gasUsed = txReceipt.getGasUsed();
- long result = txReceipt.getResult();
- log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
- }
- }
|