package com.fzm.mall.server.admin.block_chain.util;

import cn.fzm.chain.simplesdk.client.MainChainClient;
import cn.fzm.chain.simplesdk.client.ParaChainClient;
import cn.fzm.chain.simplesdk.constant.EvmTokenEnum;
import cn.fzm.chain.simplesdk.constant.TokenStatusEnum;
import cn.fzm.chain.simplesdk.constant.TxStatusEnum;
import cn.fzm.chain.simplesdk.model.TxResult;
import com.alibaba.fastjson.JSON;
import com.fzm.mall.server.admin.enums.chain.ChainTypeEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author wangp
 * @date 2021/9/16 13:49
 * @description 链工具类(联盟链 | 平行链)
 * @since JDK 1.8
 */
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ChainUtil {

    @Value("${chain.para.cAddr}")
    private String cAddr;
    @Value("${chain.type}")
    private String type;
    @Value("${chain.main.token-manager}")
    private String mainTokenManager;
    @Value("${chain.main.token-manager-key}")
    private String mainTokenManagerKey;
    @Value("${chain.para.token-manager}")
    private String paraTokenManager;
    @Value("${chain.para.token-manager-key}")
    private String paraTokenManagerKey;
    //1BzfFBFf99DRhqfunEXhPsZRDgPwUWjab6
    //    String slcAddr = "1AdSxpZKKbdaFNuydxvGktBtUYHmcuP1C5";

    String slcAddr = "1MbJCfsBwEkTJhfbEgQ5ScHYTMPL3Nf8KF";
    String code = "[encoded data, 17138 characters]";
    String abi = "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burnToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"tokenIds\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"burnTokenBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getTokenInfo\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"getUserTokens\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mintToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"tokenIds\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"mintTokenBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"tokenInfo\",\"type\":\"string\"}],\"name\":\"setTokenInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]";
    String slcabi = "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"values\",\"type\":\"uint256[]\"}],\"name\":\"TransferBatch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"TransferSingle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"value\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"URI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"goodsID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int32\",\"name\":\"goodsType\",\"type\":\"int32\"},{\"indexed\":false,\"internalType\":\"int64\",\"name\":\"publishTime\",\"type\":\"int64\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"hash\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"string[]\",\"name\":\"source\",\"type\":\"string[]\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"publisher\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"labelID\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"remark\",\"type\":\"string\"}],\"name\":\"addNewGoodsResult\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"batchTransferResult\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"BatchTransferWithEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"int32\",\"name\":\"goodsType\",\"type\":\"int32\"},{\"internalType\":\"int64\",\"name\":\"publishTime\",\"type\":\"int64\"},{\"internalType\":\"string[]\",\"name\":\"hash\",\"type\":\"string[]\"},{\"internalType\":\"string[]\",\"name\":\"source\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"publisher\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"labelID\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"remark\",\"type\":\"string\"}],\"name\":\"addNewGoods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"goodsID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"int32\",\"name\":\"goodsType\",\"type\":\"int32\"},{\"internalType\":\"int64\",\"name\":\"publishTime\",\"type\":\"int64\"},{\"internalType\":\"string[]\",\"name\":\"hash\",\"type\":\"string[]\"},{\"internalType\":\"string[]\",\"name\":\"source\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"publisher\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"labelID\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"remark\",\"type\":\"string\"}],\"name\":\"addNewGoodsAssignGoodsID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"name\":\"balanceOfBatch\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"goodsID\",\"type\":\"uint256\"}],\"name\":\"getGoodsAttribute\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"goodsID\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"int32\",\"name\":\"goodsType\",\"type\":\"int32\"},{\"internalType\":\"int64\",\"name\":\"publishTime\",\"type\":\"int64\"},{\"internalType\":\"string\",\"name\":\"publisher\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"labelID\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"remark\",\"type\":\"string\"}],\"internalType\":\"struct ProcessingFactory.Goods\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"goodsID\",\"type\":\"uint256\"}],\"name\":\"getGoodsHash\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMaxGoodsID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"goodsID\",\"type\":\"uint256\"}],\"name\":\"getsourceHash\",\"outputs\":[{\"internalType\":\"string[]\",\"name\":\"\",\"type\":\"string[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"goodsHash\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxGoodsId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeBatchTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"sourceHash\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"uri\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]";
    String slccode = "[encoded data, 32154 characters]";

    private final MainChainClient mainClient;
    private final ParaChainClient paraClient;

    // =========================================地址=========================================
    //  -----------------------------------------首-----------------------------------------
    //创建账户
    public String accountCreate(String label) {
        String address = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                address = mainClient.walletCreateAccount(label);
                break;
            case PARA:
                address = paraClient.walletCreateAccount(label);
                break;
        }
        return address;
    }
    //  -----------------------------------------尾-----------------------------------------

    // =========================================NFT=========================================
    //  -----------------------------------------首-----------------------------------------
    //发行NFT,本次发行的是ERC1155 -- 发行确认一体
    public Map<String, String> evmPublishToken(String publisher, long tokenId, long amount) {
        Map<String, String> map = new HashMap<>();
        map.put("status", "SUCCESS");
        map.put("errMsg", "");

        String hash = null;
        TxResult tr = null;

        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.evmPublishToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, publisher, publisher, null, tokenId, amount, "publish", false);
                break;
            case PARA:
                hash = paraClient.evmPublishToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, publisher, publisher, null, tokenId, amount, "publish", true);
                break;
        }

        tr = cycleConfirmTxWithHash(hash);
        if (tr.getStatus() != TxStatusEnum.SUCCESS) {
            log.error("NFT发行失败，交易HASH:{},失败原因：{}", hash, tr.getErrMsg());
            map.put("status", "FAIL");
            map.put("errMsg", tr.getErrMsg().getValue());
            return map;
        }
        return map;
    }

    //发行NFT,本次发行的是ERC1155 发行确认分体
    public String evmPublishTokenSplit(String publisher, long tokenId, long amount) {
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.evmPublishToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, publisher, publisher, null, tokenId, amount, "publish", false);
                break;
            case PARA:
                hash = paraClient.evmPublishToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, publisher, publisher, null, tokenId, amount, "publish", true);
                break;
        }
        return hash;
    }

    //减发NFT,本次发行的是ERC1155 发行确认分体
    public String evmBurnTokenSplit(String publisher, long tokenId, long amount) {
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.evmBurnToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, publisher, publisher, null, tokenId, amount, "publish", false);
                break;
            case PARA:
                hash = paraClient.evmBurnToken(abi, cAddr, EvmTokenEnum.ERC1155, 0L, publisher, publisher, null, tokenId, amount, "publish", true);
                break;
        }
        return hash;
    }

    //发行NFT,本次发行的是ERC1155 发行确认分体
    public String evmPublishTokenSplitBatch(String publisher, long[] tokenIds, long[] amounts) {
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.evmPublishTokenBatch(abi, cAddr, 0L, publisher, publisher, null, tokenIds, amounts, "publish", false);
                break;
            case PARA:
                hash = paraClient.evmPublishTokenBatch(abi, cAddr, 0L, publisher, publisher, null, tokenIds, amounts, "publish", true);
                break;
        }
        return hash;
    }

    //NFT转账
    public String evmTransfer(String to, String publisher, long tokenId, long amount) {
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.evmTransfer(abi, cAddr, EvmTokenEnum.ERC1155, 0L, to, tokenId, amount,
                        "transfer", publisher, null, false);
                break;
            case PARA:
                hash = paraClient.evmTransfer(abi, cAddr, EvmTokenEnum.ERC1155, 0L, to, tokenId, amount,
                        "transfer", publisher, null, true);
                break;
        }
        return hash;
    }

    //NFT转账批量
    public String evmTransferBatch(String to, String publisher, long[] tokenIds, long[] amounts) {
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.evmTransferBatch(abi, cAddr, EvmTokenEnum.ERC1155, 0L, to, tokenIds, amounts,
                        "transfer", publisher, null, false);
                break;
            case PARA:
                hash = paraClient.evmTransferBatch(abi, cAddr, EvmTokenEnum.ERC1155, 0L, to, tokenIds, amounts,
                        "transfer", publisher, null, true);
                break;
        }
        return hash;
    }

    //查询NFT余额
    public long evmBalance(String publisher, long tokenId) {
        long balance = 0L;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                balance = mainClient.evmBalance(abi, cAddr, EvmTokenEnum.ERC1155, publisher, tokenId);
                break;
            case PARA:
                balance = paraClient.evmBalance(abi, cAddr, EvmTokenEnum.ERC1155, publisher, tokenId);
                break;
        }
        return balance;
    }

    //SLC nft 转帐
    public String evmExec(long[] tokenIds, long[] amounts, String from, String to) {
        String initParameter = "BatchTransferWithEvent(" + from + "," + to + "," + JSON.toJSONString(tokenIds) + "," + JSON.toJSONString(amounts) + ",)";
        String hash = paraClient.evmExec(slcabi, slcAddr, initParameter, 1000000L, "transfer", from, null, true);
        return hash;
    }

    //SLC 查询标识全称
    public String[] getGoodsAttribute(long tokenId, String from) {
        String parameter = "getGoodsAttribute(" + tokenId + ")";
        String hash = paraClient.evmQuery(slcabi, slcAddr, parameter, from);
        return hash.split(" ");
    }

    //SLC 查询交易hash
    public String getGoodsHash(long tokenId, String from) {
        String parameter = "getGoodsHash(" + tokenId + ")";
        String hash = paraClient.evmQuery(slcabi, slcAddr, parameter, from);
        return hash.substring(1, hash.lastIndexOf("]"));
    }

    //SLC 查询交易的来源hash
    public String getsourceHash(long tokenId, String from) {
        String parameter = "getsourceHash(" + tokenId + ")";
        String hash = paraClient.evmQuery(slcabi, slcAddr, parameter, from);
        return hash.substring(1, hash.lastIndexOf("]"));
    }
    //  -----------------------------------------尾-----------------------------------------

    // =========================================hash确认=========================================
    //  -----------------------------------------首-----------------------------------------
    //单次确认
    public TxResult confirmTxWithTxHash(String hash) {
        TxResult tr = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                tr = mainClient.confirmTxWithRealTxHash(hash);
                break;
            case PARA:
                tr = paraClient.confirmTxWithGrpTxHash(hash);
                break;
        }
        return tr;
    }

    //轮询确认
    public TxResult cycleConfirmTxWithHash(String hash) {
        TxResult tr = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                tr = mainClient.cycleConfirmTxWithHash(hash, false, 1000);
                break;
            case PARA:
                tr = paraClient.cycleConfirmTxWithHash(hash, true, 1000);
                break;
        }
        return tr;
    }
    //  -----------------------------------------尾-----------------------------------------

    // =========================================token=========================================
    //  -----------------------------------------首-----------------------------------------
    //判断商品币是否存在
    public boolean tokenExist(String coin) {
        boolean existPre = false;
        boolean existFin = false;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                existPre = mainClient.tokenExisted(coin, TokenStatusEnum.PREOK);
                existFin = mainClient.tokenExisted(coin, TokenStatusEnum.FINOK);
                break;
            case PARA:
                existPre = paraClient.tokenExisted(coin, TokenStatusEnum.PREOK);
                existFin = paraClient.tokenExisted(coin, TokenStatusEnum.FINOK);
                break;
        }
        if (existPre || existFin) {
            log.error("TOKEN发行失败，失败原因：TOKEN已存在，label:{}", coin);
        }
        return existPre || existFin;
    }

    //发行TOKEN -- 发行确认一体
    public Map<String, String> issueCoin(String coin, int amount, String tokenAddr) {
        Map<String, String> map = new HashMap<>();
        map.put("status", "SUCCESS");
        map.put("errMsg", "");

        BigDecimal totalAmt = new BigDecimal(amount);
        String hash = null;
        TxResult tr;
        //进行预发售
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTokenCreatePre(coin, coin, totalAmt, tokenAddr, mainTokenManager, mainTokenManagerKey);
                break;
            case PARA:
                hash = paraClient.paraTokenCreatePre(coin, coin, totalAmt, tokenAddr, paraTokenManager, paraTokenManagerKey);
                break;
        }
        tr = cycleConfirmTxWithHash(hash);
        if (tr.getStatus() != TxStatusEnum.SUCCESS) {
            log.error("TOKEN预发行失败，交易HASH:{},失败原因：{}", hash, tr.getErrMsg());
            map.put("status", "FAIL");
            map.put("errMsg", tr.getErrMsg().getValue());
            return map;
        }

        //完成发行
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                //完成发行
                hash = mainClient.mainTokenCreateFin(coin, tokenAddr, mainTokenManager, mainTokenManagerKey);
                break;
            case PARA:
                //完成发行
                hash = paraClient.paraTokenCreateFin(coin, tokenAddr, paraTokenManager, paraTokenManager);
                break;
        }
        tr = cycleConfirmTxWithHash(hash);
        if (tr.getStatus() != TxStatusEnum.SUCCESS) {
            log.error("TOKEN完成发行失败，交易HASH:{},失败原因：{}", hash, tr.getErrMsg());
            map.put("status", "FAIL");
            map.put("errMsg", tr.getErrMsg().getValue());
            return map;
        }

        return map;
    }

    //发行TOKEN -- 发行确认分体 -- 预发行
    public String issueCoinPre(String coin, int amount, String tokenAddr) {
        BigDecimal totalAmt = new BigDecimal(amount);
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTokenCreatePre(coin, coin, totalAmt, tokenAddr, mainTokenManager, mainTokenManagerKey);
                break;
            case PARA:
                hash = paraClient.paraTokenCreatePre(coin, coin, totalAmt, tokenAddr, paraTokenManager, paraTokenManagerKey);
                break;
        }
        return hash;
    }

    //发行TOKEN -- 发行确认分体 -- 完成发行
    public String issueCoinFin(String coin, String tokenAddr) {
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTokenCreateFin(coin, tokenAddr, mainTokenManager, mainTokenManagerKey);
                break;
            case PARA:
                hash = paraClient.paraTokenCreateFin(coin, tokenAddr, paraTokenManager, paraTokenManager);
                break;
        }
        return hash;
    }

    //增发TOKEN -- 发行确认一体
    public Map<String, String> coinMint(String coin, String addr, String key, int amount) {
        Map<String, String> map = new HashMap<>();
        map.put("status", "SUCCESS");
        map.put("errMsg", "");

        BigDecimal totalAmt = new BigDecimal(amount);
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTokenMint(coin, addr, key, totalAmt);
                break;
            case PARA:
                hash = paraClient.paraTokenMint(coin, addr, key, totalAmt);
                break;
        }
        TxResult tr = cycleConfirmTxWithHash(hash);
        if (tr.getStatus() != TxStatusEnum.SUCCESS) {
            log.error("TOKEN增发失败，交易HASH:{},失败原因：{}", hash, tr.getErrMsg());
            map.put("status", "FAIL");
            map.put("errMsg", tr.getErrMsg().getValue());
        }
        return map;
    }

    //增发TOKEN -- 发行确认分体
    public String coinMintSplit(String coin, String addr, String key, int amount) {
        BigDecimal totalAmt = new BigDecimal(amount);
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTokenMint(coin, addr, key, totalAmt);
                break;
            case PARA:
                hash = paraClient.paraTokenMint(coin, addr, key, totalAmt);
                break;
        }
        return hash;
    }

    //减发TOKEN -- 发行确认一体
    public Map<String, String> coinBurn(String coin, String addr, String key, int amount) {
        Map<String, String> map = new HashMap<>();
        map.put("status", "SUCCESS");
        map.put("errMsg", "");

        BigDecimal totalAmt = new BigDecimal(amount);
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTokenBurn(coin, addr, key, totalAmt);
                break;
            case PARA:
                hash = paraClient.paraTokenBurn(coin, addr, key, totalAmt);
                break;
        }
        TxResult tr = cycleConfirmTxWithHash(hash);
        if (tr.getStatus() != TxStatusEnum.SUCCESS) {
            log.error("TOKEN减发失败，交易HASH:{},失败原因：{}", hash, tr.getErrMsg());
            map.put("status", "FAIL");
            map.put("errMsg", tr.getErrMsg().getValue());
        }
        return map;
    }

    //减发TOKEN -- 发行确认分体
    public String coinBurnSplit(String coin, String addr, String key, int amount) {
        BigDecimal totalAmt = new BigDecimal(amount);
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTokenBurn(coin, addr, key, totalAmt);
                break;
            case PARA:
                hash = paraClient.paraTokenBurn(coin, addr, key, totalAmt);
                break;
        }
        return hash;
    }

    //token转账  fromPrikey 非必传
    public String tranToken(String fromAddr, String fromPriKey, String toAddr, BigDecimal amount, String tokenSymbol) {
        String hash = null;
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                hash = mainClient.mainTranToken(fromAddr, fromPriKey, toAddr, amount, tokenSymbol);
                break;
            case PARA:
                hash = paraClient.paraTranToken(fromAddr, fromPriKey, toAddr, amount, tokenSymbol);
                break;
        }
        return hash;
    }

    public String walletDumpPrivkey(String addr) {
        String key = "";
        switch (Objects.requireNonNull(ChainTypeEnum.getByType(type))) {
            case MAIN:
                key = mainClient.walletDumpPrivkey(addr);
                break;
            case PARA:
                key = paraClient.walletDumpPrivkey(addr);
                break;
        }
        return key;
    }
    //  -----------------------------------------尾-----------------------------------------


}
