xiongzhu 4 tahun lalu
induk
melakukan
4a07e739bf

+ 19 - 11
src/main/contract/9th.sol

@@ -158,7 +158,7 @@ library EnumerableMap {
         uint256 key,
         identity value
     ) internal returns (bool) {
-        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
+        return _set(map._inner, bytes32(key), bytes32(uint256(value)));
     }
 
     function remove(UintToAddressMap storage map, uint256 key)
@@ -190,7 +190,7 @@ library EnumerableMap {
         returns (uint256, identity)
     {
         (bytes32 key, bytes32 value) = _at(map._inner, index);
-        return (uint256(key), identity(uint160(uint256(value))));
+        return (uint256(key), identity(uint256(value)));
     }
 
     function tryGet(UintToAddressMap storage map, uint256 key)
@@ -199,7 +199,7 @@ library EnumerableMap {
         returns (bool, identity)
     {
         (bool success, bytes32 value) = _tryGet(map._inner, bytes32(key));
-        return (success, identity(uint160(uint256(value))));
+        return (success, identity(uint256(value)));
     }
 
     function get(UintToAddressMap storage map, uint256 key)
@@ -207,7 +207,7 @@ library EnumerableMap {
         view
         returns (identity)
     {
-        return identity(uint160(uint256(_get(map._inner, bytes32(key)))));
+        return identity(uint256(_get(map._inner, bytes32(key))));
     }
 
     function get(
@@ -217,7 +217,7 @@ library EnumerableMap {
     ) internal view returns (identity) {
         return
             identity(
-                uint160(uint256(_get(map._inner, bytes32(key), errorMessage)))
+                uint256(_get(map._inner, bytes32(key), errorMessage))
             );
     }
 }
@@ -307,15 +307,15 @@ library EnumerableSet {
     }
 
     function add(AddressSet storage set, identity value) internal returns (bool) {
-        return _add(set._inner, bytes32(uint256(uint160(value))));
+        return _add(set._inner, bytes32(uint256(value)));
     }
 
     function remove(AddressSet storage set, identity value) internal returns (bool) {
-        return _remove(set._inner, bytes32(uint256(uint160(value))));
+        return _remove(set._inner, bytes32(uint256(value)));
     }
 
     function contains(AddressSet storage set, identity value) internal view returns (bool) {
-        return _contains(set._inner, bytes32(uint256(uint160(value))));
+        return _contains(set._inner, bytes32(uint256(value)));
     }
 
     function length(AddressSet storage set) internal view returns (uint256) {
@@ -323,7 +323,7 @@ library EnumerableSet {
     }
 
     function at(AddressSet storage set, uint256 index) internal view returns (identity) {
-        return identity(uint160(uint256(_at(set._inner, index))));
+        return identity(uint256(_at(set._inner, index)));
     }
 
     struct UintSet {
@@ -1030,8 +1030,8 @@ contract ERC721PresetMinterPauserAutoId is Context, AccessControl, ERC721Burnabl
 
         // We cannot just use balanceOf to create the new tokenId because tokens
         // can be burned (destroyed), so we need a separate counter.
-        _mint(to, _tokenIdTracker.current());
-        _tokenIdTracker.increment();
+        _mint(to, tokenId);
+        //_tokenIdTracker.increment();
     }
 
     /**
@@ -1069,4 +1069,12 @@ contract ERC721PresetMinterPauserAutoId is Context, AccessControl, ERC721Burnabl
     function ownerTransfer(identity from, identity to, uint256 tokenId) public onlyowner {
         _transfer(from, to, tokenId);
     }
+
+    function setTokenURI(uint256 tokenId, string memory _tokenURI) public onlyowner {
+        _setTokenURI(tokenId, _tokenURI);
+    }
+
+    function setBaseURI(string memory baseURI_) public onlyowner {
+        _setBaseURI(baseURI_);
+    }
 }

+ 5 - 15
src/main/java/com/izouma/nineth/service/AssetMintService.java

@@ -8,9 +8,7 @@ import com.izouma.nineth.dto.NFTAccount;
 import com.izouma.nineth.event.CreateAssetEvent;
 import com.izouma.nineth.exception.BusinessException;
 import com.izouma.nineth.repo.AssetRepo;
-import com.izouma.nineth.repo.TokenHistoryRepo;
 import com.izouma.nineth.repo.UserRepo;
-import com.izouma.nineth.utils.SnowflakeIdWorker;
 import io.ipfs.api.IPFS;
 import io.ipfs.api.MerkleNode;
 import io.ipfs.api.NamedStreamable;
@@ -19,12 +17,10 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.context.ApplicationContext;
-import org.springframework.core.env.Environment;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
-import java.math.BigInteger;
-import java.util.Arrays;
 
 @Service
 @Slf4j
@@ -34,10 +30,9 @@ public class AssetMintService {
     private UserRepo           userRepo;
     private NFTService         nftService;
     private ApplicationContext applicationContext;
-    private TokenHistoryRepo   tokenHistoryRepo;
-    private Environment        env;
 
-    public void mint(Asset asset, Long historyId) {
+    @Async
+    public void mint(Asset asset) {
         User user = userRepo.findById(asset.getUserId()).orElseThrow(new BusinessException("用户不存在"));
         if (StringUtils.isEmpty(user.getPublicKey())) {
             NFTAccount account = nftService.createAccount(user.getUsername() + "_");
@@ -47,7 +42,7 @@ public class AssetMintService {
             userRepo.save(user);
         }
         try {
-            NFT nft = nftService.createToken(user.getNftAccount());
+            NFT nft = nftService.createToken(user.getNftAccount(), asset.getTokenId());
             if (nft != null) {
                 asset.setTokenId(nft.getTokenId());
                 asset.setBlockNumber(nft.getBlockNumber());
@@ -57,14 +52,9 @@ public class AssetMintService {
                     asset.setIpfsUrl(ipfsUpload(asset.getPic().get(0).getUrl()));
                 }
                 assetRepo.save(asset);
-
-                tokenHistoryRepo.findById(historyId).ifPresent(tokenHistory -> {
-                    tokenHistory.setTokenId(nft.getTokenId());
-                    tokenHistoryRepo.save(tokenHistory);
-                });
             }
         } catch (Exception e) {
-            e.printStackTrace();
+            log.error("铸造失败", e);
         }
         applicationContext.publishEvent(new CreateAssetEvent(this, true, asset));
     }

+ 12 - 14
src/main/java/com/izouma/nineth/service/AssetService.java

@@ -14,6 +14,7 @@ import com.izouma.nineth.lock.RedisLockable;
 import com.izouma.nineth.repo.*;
 import com.izouma.nineth.utils.JpaUtils;
 import com.izouma.nineth.utils.SecurityUtils;
+import com.izouma.nineth.utils.TokenUtils;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
@@ -22,7 +23,6 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.scheduling.annotation.Async;
-import org.springframework.scheduling.annotation.AsyncResult;
 import org.springframework.stereotype.Service;
 
 import java.math.BigDecimal;
@@ -32,7 +32,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 
 @Service
@@ -53,16 +52,15 @@ public class AssetService {
         return assetRepo.findAll(JpaUtils.toSpecification(pageQuery, Asset.class), JpaUtils.toPageRequest(pageQuery));
     }
 
-    @Async
-    public Future<Asset> createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type, Integer number) {
+    public Asset createAsset(Collection collection, User user, Long orderId, BigDecimal price, String type, Integer number) {
         Asset asset = Asset.create(collection, user);
+        asset.setTokenId(TokenUtils.genTokenId());
         asset.setNumber(number);
         asset.setOrderId(orderId);
         asset.setPrice(price);
-        asset.setIpfsUrl(assetMintService.ipfsUpload(collection.getPic().get(0).getUrl()));
         assetRepo.save(asset);
 
-        TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
+        tokenHistoryRepo.save(TokenHistory.builder()
                 .tokenId(asset.getTokenId())
                 .fromUser(collection.getMinter())
                 .fromUserId(collection.getMinterId())
@@ -73,19 +71,19 @@ public class AssetService {
                 .operation(type)
                 .price(price)
                 .build());
-        assetMintService.mint(asset, tokenHistory.getId());
-        return new AsyncResult<>(asset);
+        assetMintService.mint(asset);
+        return asset;
     }
 
-    @Async
-    public Future<Asset> createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type, Integer number) {
+    public Asset createAsset(BlindBoxItem winItem, User user, Long orderId, BigDecimal price, String type, Integer number) {
         Asset asset = Asset.create(winItem, user);
+        asset.setTokenId(TokenUtils.genTokenId());
         asset.setNumber(number);
         asset.setOrderId(orderId);
         asset.setPrice(price);
-        asset.setIpfsUrl(assetMintService.ipfsUpload(winItem.getPic().get(0).getUrl()));
         assetRepo.save(asset);
-        TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
+
+        tokenHistoryRepo.save(TokenHistory.builder()
                 .tokenId(asset.getTokenId())
                 .fromUser(winItem.getMinter())
                 .fromUserId(winItem.getMinterId())
@@ -96,8 +94,8 @@ public class AssetService {
                 .operation(type)
                 .price(price)
                 .build());
-        assetMintService.mint(asset, tokenHistory.getId());
-        return new AsyncResult<>(asset);
+        assetMintService.mint(asset);
+        return asset;
     }
 
 

+ 49 - 30
src/main/java/com/izouma/nineth/service/NFTService.java

@@ -3,22 +3,21 @@ 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.alipay.mychain.sdk.domain.transaction.LogEntry;
 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.GeneralProperties;
 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.exception.BusinessException;
-import com.izouma.nineth.utils.HashUtils;
 import com.izouma.nineth.utils.SnowflakeIdWorker;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Hex;
 import org.springframework.retry.annotation.Backoff;
 import org.springframework.retry.annotation.Retryable;
 import org.springframework.stereotype.Service;
@@ -60,15 +59,16 @@ public class NFTService {
     }
 
     @Retryable(maxAttempts = 100, backoff = @Backoff(delay = 5000), value = BusinessException.class)
-    public synchronized NFT createToken(String toAccount) throws Exception {
+    public synchronized NFT createToken(String toAccount, String tokenId) throws Exception {
         JSONArray jsonArray = new JSONArray();
         jsonArray.add(Utils.getIdentityByName(toAccount));
+        jsonArray.add(new BigInteger(tokenId, 16));
         CallRestBizParam callRestBizParam = CallRestBizParam.builder()
                 .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
                 .bizid(restClientProperties.getBizid())
                 .account(restClientProperties.getAccount())
                 .contractName(generalProperties.getContractName())
-                .methodSignature("mint(identity)")
+                .methodSignature("mint(identity,uint256)")
                 .inputParamListStr(jsonArray.toJSONString())
                 .outTypes("[]")//合约返回值类型
                 .mykmsKeyId(restClientProperties.getKmsId())
@@ -87,15 +87,9 @@ public class NFTService {
             BigInteger gasUsed = txReceipt.getGasUsed();
             long result = txReceipt.getResult();
             log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
-            for (LogEntry logEntry : txReceipt.getLogs()) {
-                if (logEntry.getTopics().get(0).equals(HashUtils.Keccak256("Transfer(identity,identity,uint256)"))) {
-                    String tokenId = logEntry.getTopics().get(3);
-                    txReceipt.getBlockNumber();
-                    NFT nft = new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
-                    log.info("NFT生成成功 {}", nft);
-                    return nft;
-                }
-            }
+            NFT nft = new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
+            log.info("NFT生成成功 {}", nft);
+            return nft;
         } else {
             // 异步交易未成功需要根据状态码判断交易状态
             log.error("EVM合约执行未成功: " + resp.getCode());
@@ -103,19 +97,52 @@ public class NFTService {
         throw new BusinessException("创建nft失败");
     }
 
+    public String ownerOf(String tokenId) throws Exception {
+        CallRestBizParam callRestBizParam = CallRestBizParam.builder()
+                .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).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(fromAccount));
-        jsonArray.add(Utils.getIdentityByName(toAccount));
-        jsonArray.add(Long.parseLong(tokenId, 16));
-
+        jsonArray.add(Utils.getIdentityByName("raex_official"));
+        jsonArray.add(Utils.getIdentityByName("9th_HCWWflAZ_"));
+        jsonArray.add("95057808871064671354760012409081314299");
         CallRestBizParam callRestBizParam = CallRestBizParam.builder()
                 .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
                 .bizid(restClientProperties.getBizid())
                 .account(restClientProperties.getAccount())
-                .contractName(generalProperties.getContractName())
-                .methodSignature("transferFrom(identity,identity,uint256)")
+                .contractName("raex12")
+                .methodSignature("ownerTransfer(identity,identity,uint256)")
                 .inputParamListStr(jsonArray.toJSONString())
                 .outTypes("[]")//合约返回值类型
                 .mykmsKeyId(restClientProperties.getKmsId())
@@ -134,20 +161,12 @@ public class NFTService {
             BigInteger gasUsed = txReceipt.getGasUsed();
             long result = txReceipt.getResult();
             log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
-            for (LogEntry logEntry : txReceipt.getLogs()) {
-                if (logEntry.getTopics().get(0).equals(HashUtils.Keccak256("Transfer(identity,identity,uint256)"))) {
-                    String transferTokenId = logEntry.getTopics().get(3);
-                    txReceipt.getBlockNumber();
-                    NFT nft = new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
-                    log.info("NFT转移成功 {}", nft);
-                    return nft;
-                }
-            }
+            return new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
         } else {
             // 异步交易未成功需要根据状态码判断交易状态
             log.error("EVM合约执行未成功: " + resp.getCode());
         }
-        throw new BusinessException("创建nft失败");
+        throw new BusinessException("转移token失败");
     }
 
     public NFT setApprovalForAll(String account) throws Exception {

+ 23 - 0
src/main/java/com/izouma/nineth/utils/TokenUtils.java

@@ -0,0 +1,23 @@
+package com.izouma.nineth.utils;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+public class TokenUtils {
+    public static String genTokenId() {
+        try {
+            Random random = ThreadLocalRandom.current();
+            byte[] r = new byte[32];
+            random.nextBytes(r);
+            MessageDigest m = MessageDigest.getInstance("MD5");
+            m.update(r, 0, r.length);
+            return new BigInteger(1, m.digest()).toString(16);
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

+ 1 - 1
src/main/resources/application.yaml

@@ -87,7 +87,7 @@ aliyun:
   sms-code: SMS_228870098
 general:
   host: https://test.raex.vip
-  contract-name: raex
+  contract-name: raex12
   name: 绿洲数字藏品中心
   org: 华储艺术品中心(深圳)有限公司
   short-name: 华储

+ 5 - 3
src/test/java/com/izouma/nineth/CommonTest.java

@@ -1,5 +1,6 @@
 package com.izouma.nineth;
 
+import com.alibaba.fastjson.JSONArray;
 import com.github.kevinsawicki.http.HttpRequest;
 import com.izouma.nineth.config.Constants;
 import com.izouma.nineth.domain.BaseEntity;
@@ -386,9 +387,10 @@ public class CommonTest {
         BigInteger bi = new BigInteger(1, m.digest());
         System.out.println(bi);
         System.out.println(bi.toString(16));
+        System.out.println(new BigInteger(bi.toString(16), 16));
 
-        BigInteger bi1 = new BigInteger(256, new Random());
-        System.out.println(bi1);
-        System.out.println(bi1.toString(16));
+        JSONArray jsonArray = new JSONArray();
+        jsonArray.add(bi);
+        System.out.println(jsonArray.toString());
     }
 }

+ 2 - 71
src/test/java/com/izouma/nineth/service/AssetServiceTest.java

@@ -3,14 +3,11 @@ package com.izouma.nineth.service;
 import com.izouma.nineth.ApplicationTests;
 import com.izouma.nineth.TokenHistory;
 import com.izouma.nineth.domain.*;
-import com.izouma.nineth.dto.NFT;
-import com.izouma.nineth.dto.NFTAccount;
 import com.izouma.nineth.repo.*;
 import org.apache.commons.lang3.StringUtils;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import java.util.Arrays;
 import java.util.List;
 
 class AssetServiceTest extends ApplicationTests {
@@ -67,7 +64,7 @@ class AssetServiceTest extends ApplicationTests {
     @Test
     public void mint() {
         Asset asset = assetRepo.findById(4622L).get();
-        assetMintService.mint(asset, 1L);
+        assetMintService.mint(asset);
     }
 
     @Test
@@ -86,78 +83,12 @@ class AssetServiceTest extends ApplicationTests {
         }
     }
 
-    @Test
-    public void fixHash() throws Exception {
-        for (Asset asset : assetRepo.findByTxHash("1")) {
-            User user = userRepo.findById(asset.getUserId()).get();
-            if (StringUtils.isEmpty(user.getPublicKey())) {
-                NFTAccount account = nftService.createAccount(user.getUsername() + "_");
-                user.setNftAccount(account.getAccountId());
-                user.setKmsId(account.getAccountKmsId());
-                user.setPublicKey(account.getPublicKey());
-                userRepo.save(user);
-            }
-            NFT nft = nftService.createToken(user.getNftAccount());
-            if (nft != null) {
-                asset.setTokenId(nft.getTokenId());
-                asset.setBlockNumber(nft.getBlockNumber());
-                asset.setTxHash(nft.getTxHash());
-                asset.setGasUsed(nft.getGasUsed());
-                assetRepo.save(asset);
-
-                List<TokenHistory> list = tokenHistoryRepo.findByTokenIdOrderByCreatedAtDesc(asset.getTokenId());
-                for (TokenHistory tokenHistory : list) {
-                    tokenHistory.setTokenId(asset.getTokenId());
-                }
-                tokenHistoryRepo.saveAll(list);
-            }
-        }
-    }
-
-    @Test
-    public void fixHash1() throws Exception {
-        List<Long> ids = Arrays.asList(27206L, 27216L, 27242L, 27271L, 27276L, 27280L, 27292L, 27294L, 43485L);
-        for (Asset asset : assetRepo.findByIdIn(ids)) {
-            User user = userRepo.findById(asset.getUserId()).get();
-            if (StringUtils.isEmpty(user.getPublicKey())) {
-                NFTAccount account = nftService.createAccount(user.getUsername() + "_");
-                user.setNftAccount(account.getAccountId());
-                user.setKmsId(account.getAccountKmsId());
-                user.setPublicKey(account.getPublicKey());
-                userRepo.save(user);
-            }
-            NFT nft = nftService.createToken(user.getNftAccount());
-            if (nft != null) {
-                asset.setTokenId(nft.getTokenId());
-                asset.setBlockNumber(nft.getBlockNumber());
-                asset.setTxHash(nft.getTxHash());
-                asset.setGasUsed(nft.getGasUsed());
-                assetRepo.save(asset);
-
-                TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
-                        .tokenId(asset.getTokenId())
-                        .fromUser(asset.getMinter())
-                        .fromUserId(asset.getMinterId())
-                        .fromAvatar(asset.getMinterAvatar())
-                        .toUser(user.getNickname())
-                        .toUserId(user.getId())
-                        .toAvatar(user.getAvatar())
-                        .operation("出售")
-                        .price(asset.getPrice())
-                        .tokenId(asset.getTokenId())
-                        .build());
-                tokenHistory.setCreatedAt(asset.getCreatedAt());
-                tokenHistoryRepo.save(tokenHistory);
-            }
-        }
-    }
-
     @Test
     public void fixNoHistory() {
         List<Asset> assets = assetRepo.findByNoHistory();
 
         for (Asset asset : assets) {
-            if (StringUtils.isNotBlank(asset.getTokenId())){
+            if (StringUtils.isNotBlank(asset.getTokenId())) {
                 User user = userRepo.findById(asset.getUserId()).get();
                 TokenHistory tokenHistory = tokenHistoryRepo.save(TokenHistory.builder()
                         .tokenId(asset.getTokenId())

+ 50 - 3
src/test/java/com/izouma/nineth/service/NFTServiceTest.java

@@ -16,6 +16,7 @@ import com.izouma.nineth.dto.NFT;
 import com.izouma.nineth.utils.HashUtils;
 import com.izouma.nineth.utils.SnowflakeIdWorker;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -59,7 +60,7 @@ public class NFTServiceTest extends ApplicationTests {
                 .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
                 .bizid(restClientProperties.getBizid())
                 .account(restClientProperties.getAccount())
-                .contractName("raex111")
+                .contractName("raex12")
                 .methodSignature("mint(identity,uint256)")
                 .inputParamListStr(jsonArray.toJSONString())
                 .outTypes("[]")//合约返回值类型
@@ -146,9 +147,9 @@ public class NFTServiceTest extends ApplicationTests {
                 .orderId(String.valueOf(new SnowflakeIdWorker(0, 0).nextId()))
                 .bizid(restClientProperties.getBizid())
                 .account(restClientProperties.getAccount())
-                .contractName("raex111")
+                .contractName("raex12")
                 .methodSignature("ownerOf(uint256)")
-                .inputParamListStr("[\"305596637601946315409962168553415519496\"]")
+                .inputParamListStr("[\"95057808871064671354760012409081314299\"]")
                 .outTypes("[identity]")//合约返回值类型
                 .mykmsKeyId(restClientProperties.getKmsId())
                 .method(Method.CALLCONTRACTBIZASYNC)
@@ -166,6 +167,52 @@ public class NFTServiceTest extends ApplicationTests {
             BigInteger gasUsed = txReceipt.getGasUsed();
             long result = txReceipt.getResult();
             log.info("EVM合约交易内容: 哈希 " + txReceipt.getHash() + ", 消耗燃料 " + gasUsed + ", 结果 " + result);
+            log.info("owner:{}", Hex.encodeHexString(txReceipt.getOutput()));
+            for (LogEntry logEntry : txReceipt.getLogs()) {
+                if (logEntry.getTopics().get(0).equals(HashUtils.Keccak256("Transfer(identity,identity,uint256)"))) {
+                    String tokenId = logEntry.getTopics().get(3);
+                    txReceipt.getBlockNumber();
+                    NFT nft = new NFT(txReceipt.getHash(), tokenId, txReceipt.getBlockNumber(), txReceipt.getGasUsed());
+                    log.info("NFT生成成功 {}", nft);
+                }
+            }
+        } else {
+            // 异步交易未成功需要根据状态码判断交易状态
+            log.error("EVM合约执行未成功: " + resp.getCode());
+        }
+    }
+
+    @Test
+    public void transfer() 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(new SnowflakeIdWorker(0, 0).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);
+            log.info("owner:{}", Hex.encodeHexString(txReceipt.getOutput()));
             for (LogEntry logEntry : txReceipt.getLogs()) {
                 if (logEntry.getTopics().get(0).equals(HashUtils.Keccak256("Transfer(identity,identity,uint256)"))) {
                     String tokenId = logEntry.getTopics().get(3);

+ 1 - 26
src/test/java/com/izouma/nineth/service/OrderServiceTest.java

@@ -5,8 +5,8 @@ import com.huifu.adapay.core.exception.BaseAdaPayException;
 import com.huifu.adapay.model.Payment;
 import com.izouma.nineth.ApplicationTests;
 import com.izouma.nineth.TokenHistory;
-import com.izouma.nineth.domain.*;
 import com.izouma.nineth.domain.Collection;
+import com.izouma.nineth.domain.*;
 import com.izouma.nineth.dto.UserBankCard;
 import com.izouma.nineth.enums.AssetStatus;
 import com.izouma.nineth.enums.AuthStatus;
@@ -23,7 +23,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import java.io.IOException;
 import java.time.LocalDateTime;
 import java.util.*;
-import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -177,30 +176,6 @@ public class OrderServiceTest extends ApplicationTests {
         }
     }
 
-    @Test
-    public void mint() {
-        for (Order order : orderRepo.findByStatus(OrderStatus.PROCESSING)) {
-            if (order.getPayTime().isBefore(LocalDateTime.of(2021, 12, 18, 15, 8))) {
-                try {
-                    Collection collection = collectionRepo.findById(order.getCollectionId())
-                            .orElseThrow(new BusinessException("无记录"));
-                    User user = userRepo.findById(order.getUserId()).orElseThrow(new BusinessException("无记录"));
-                    Future<Asset> f = assetService.createAsset(collection, user, order.getId(), order.getPrice(), "出售",
-                            collectionService.getNextNumber(order.getCollectionId()));
-                    while (true) {
-                        if (f.isDone()) {
-                            break;
-                        }
-                        Thread.sleep(300);
-                    }
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-
-        }
-    }
-
     @Test
     public void removeDuplicate() {
         List<Long> ids = new ArrayList<>();