NFTService.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. package com.izouma.nineth.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alipay.mychain.sdk.api.utils.Utils;
  5. import com.alipay.mychain.sdk.domain.transaction.LogEntry;
  6. import com.antfinancial.mychain.baas.tool.restclient.RestClient;
  7. import com.antfinancial.mychain.baas.tool.restclient.RestClientProperties;
  8. import com.antfinancial.mychain.baas.tool.restclient.model.CallRestBizParam;
  9. import com.antfinancial.mychain.baas.tool.restclient.model.Method;
  10. import com.antfinancial.mychain.baas.tool.restclient.model.ReceiptDecoration;
  11. import com.antfinancial.mychain.baas.tool.restclient.response.BaseResp;
  12. import com.izouma.nineth.config.GeneralProperties;
  13. import com.izouma.nineth.config.Constants;
  14. import com.izouma.nineth.dto.NFT;
  15. import com.izouma.nineth.dto.NFTAccount;
  16. import com.izouma.nineth.exception.BusinessException;
  17. import com.izouma.nineth.utils.HashUtils;
  18. import com.izouma.nineth.utils.SnowflakeIdWorker;
  19. import lombok.AllArgsConstructor;
  20. import lombok.extern.slf4j.Slf4j;
  21. import org.springframework.retry.annotation.Backoff;
  22. import org.springframework.retry.annotation.Retryable;
  23. import org.springframework.stereotype.Service;
  24. import java.math.BigInteger;
  25. @Service
  26. @Slf4j
  27. @AllArgsConstructor
  28. public class NFTService {
  29. private final RestClient restClient;
  30. private final RestClientProperties restClientProperties;
  31. private final GeneralProperties generalProperties;
  32. public NFTAccount createAccount(String username) {
  33. CallRestBizParam callRestBizParam = CallRestBizParam.builder()
  34. .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
  35. .bizid(Constants.bizId)
  36. .account(restClientProperties.getAccount())
  37. .mykmsKeyId(restClientProperties.getKmsId())
  38. .newAccountId(username)
  39. .newAccountKmsId(Constants.kmsKey)
  40. .method(Method.TENANTCREATEACCUNT)
  41. .gas(100000L).build();
  42. try {
  43. BaseResp baseResp = restClient.chainCallForBiz(callRestBizParam);
  44. NFTAccount account = new NFTAccount(username, Constants.kmsKey, baseResp.getData());
  45. if (baseResp.isSuccess()) {
  46. log.info("创建账户成功 {}", account);
  47. return account;
  48. } else {
  49. throw new RuntimeException(baseResp.getCode());
  50. }
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. log.error("创建账户失败", e);
  54. throw new BusinessException("创建账户失败");
  55. }
  56. }
  57. @Retryable(maxAttempts = 100, backoff = @Backoff(delay = 5000), value = BusinessException.class)
  58. public synchronized NFT createToken(String toAccount) throws Exception {
  59. JSONArray jsonArray = new JSONArray();
  60. jsonArray.add(Utils.getIdentityByName(toAccount));
  61. CallRestBizParam callRestBizParam = CallRestBizParam.builder()
  62. .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
  63. .bizid(restClientProperties.getBizid())
  64. .account(restClientProperties.getAccount())
  65. .contractName(generalProperties.getContractName())
  66. .methodSignature("mint(identity)")
  67. .inputParamListStr(jsonArray.toJSONString())
  68. .outTypes("[]")//合约返回值类型
  69. .mykmsKeyId(restClientProperties.getKmsId())
  70. .method(Method.CALLCONTRACTBIZASYNC)
  71. .tenantid(restClientProperties.getTenantid())
  72. .gas(500000L)
  73. .build();
  74. BaseResp resp = restClient.bizChainCallWithReceipt(callRestBizParam);
  75. if (!resp.isSuccess()) {
  76. log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
  77. }
  78. if ("200".equals(resp.getCode())) {
  79. log.info("EVM合约执行成功");
  80. // 合约调用交易回执内容
  81. ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
  82. BigInteger gasUsed = txReceipt.getGasUsed();
  83. long result = txReceipt.getResult();
  84. log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
  85. for (LogEntry logEntry : txReceipt.getLogs()) {
  86. if (logEntry.getTopics().get(0).equals(HashUtils.Keccak256("Transfer(identity,identity,uint256)"))) {
  87. String tokenId = logEntry.getTopics().get(3);
  88. txReceipt.getBlockNumber();
  89. NFT nft = new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
  90. log.info("NFT生成成功 {}", nft);
  91. return nft;
  92. }
  93. }
  94. } else {
  95. // 异步交易未成功需要根据状态码判断交易状态
  96. log.error("EVM合约执行未成功: " + resp.getCode());
  97. }
  98. throw new BusinessException("创建nft失败");
  99. }
  100. public NFT transferToken(String tokenId, String fromAccount, String toAccount) throws Exception {
  101. JSONArray jsonArray = new JSONArray();
  102. jsonArray.add(Utils.getIdentityByName(fromAccount));
  103. jsonArray.add(Utils.getIdentityByName(toAccount));
  104. jsonArray.add(Long.parseLong(tokenId, 16));
  105. CallRestBizParam callRestBizParam = CallRestBizParam.builder()
  106. .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
  107. .bizid(restClientProperties.getBizid())
  108. .account(restClientProperties.getAccount())
  109. .contractName(generalProperties.getContractName())
  110. .methodSignature("transferFrom(identity,identity,uint256)")
  111. .inputParamListStr(jsonArray.toJSONString())
  112. .outTypes("[]")//合约返回值类型
  113. .mykmsKeyId(restClientProperties.getKmsId())
  114. .method(Method.CALLCONTRACTBIZASYNC)
  115. .tenantid(restClientProperties.getTenantid())
  116. .gas(500000L)
  117. .build();
  118. BaseResp resp = restClient.bizChainCallWithReceipt(callRestBizParam);
  119. if (!resp.isSuccess()) {
  120. log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
  121. }
  122. if ("200".equals(resp.getCode())) {
  123. log.info("EVM合约执行成功");
  124. // 合约调用交易回执内容
  125. ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
  126. BigInteger gasUsed = txReceipt.getGasUsed();
  127. long result = txReceipt.getResult();
  128. log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
  129. for (LogEntry logEntry : txReceipt.getLogs()) {
  130. if (logEntry.getTopics().get(0).equals(HashUtils.Keccak256("Transfer(identity,identity,uint256)"))) {
  131. String transferTokenId = logEntry.getTopics().get(3);
  132. txReceipt.getBlockNumber();
  133. NFT nft = new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
  134. log.info("NFT转移成功 {}", nft);
  135. return nft;
  136. }
  137. }
  138. } else {
  139. // 异步交易未成功需要根据状态码判断交易状态
  140. log.error("EVM合约执行未成功: " + resp.getCode());
  141. }
  142. throw new BusinessException("创建nft失败");
  143. }
  144. public NFT setApprovalForAll(String account) throws Exception {
  145. JSONArray jsonArray = new JSONArray();
  146. jsonArray.add(Utils.getIdentityByName(account));
  147. jsonArray.add(true);
  148. CallRestBizParam callRestBizParam = CallRestBizParam.builder()
  149. .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
  150. .bizid(restClientProperties.getBizid())
  151. .account(restClientProperties.getAccount())
  152. .contractName(generalProperties.getContractName())
  153. .methodSignature("setApprovalForAll(identity,bool)")
  154. .inputParamListStr(jsonArray.toJSONString())
  155. .outTypes("[]")//合约返回值类型
  156. .mykmsKeyId(restClientProperties.getKmsId())
  157. .method(Method.CALLCONTRACTBIZASYNC)
  158. .tenantid(restClientProperties.getTenantid())
  159. .gas(500000L)
  160. .build();
  161. BaseResp resp = restClient.bizChainCallWithReceipt(callRestBizParam);
  162. if (!resp.isSuccess()) {
  163. log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
  164. }
  165. if ("200".equals(resp.getCode())) {
  166. log.info("EVM合约执行成功");
  167. // 合约调用交易回执内容
  168. ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
  169. BigInteger gasUsed = txReceipt.getGasUsed();
  170. long result = txReceipt.getResult();
  171. log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
  172. } else {
  173. // 异步交易未成功需要根据状态码判断交易状态
  174. log.error("EVM合约执行未成功: " + resp.getCode());
  175. }
  176. throw new BusinessException("创建nft失败");
  177. }
  178. public void deployContract(String name, String code) throws Exception {
  179. String orderId = "order_" + System.currentTimeMillis();
  180. CallRestBizParam callRestBizParam = CallRestBizParam.builder()
  181. .orderId(orderId)
  182. .bizid(restClientProperties.getBizid())
  183. .account(restClientProperties.getAccount())
  184. .contractName(name)
  185. .contractCode(code)
  186. .mykmsKeyId(restClientProperties.getKmsId())
  187. .method(Method.DEPLOYCONTRACTFORBIZ)
  188. .tenantid(restClientProperties.getTenantid())
  189. .gas(1000000L).build();
  190. BaseResp resp = restClient.chainCallForBiz(callRestBizParam);
  191. if (!resp.isSuccess()) {
  192. log.info("EVM合约执行失败: " + resp.getCode() + ", " + resp.getData());
  193. }
  194. log.info("EVM合约执行成功");
  195. // 合约调用交易回执内容
  196. ReceiptDecoration txReceipt = JSON.parseObject(resp.getData(), ReceiptDecoration.class);
  197. BigInteger gasUsed = txReceipt.getGasUsed();
  198. long result = txReceipt.getResult();
  199. log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
  200. }
  201. }