From c9ebd6b518eddfedb97202b02c26841bcd22f865 Mon Sep 17 00:00:00 2001 From: "Yuan, Harry Hongbin" Date: Tue, 21 May 2024 00:46:34 +0200 Subject: [PATCH] Add NFT claim query API (#250) * fix error and add CacheDevController * add NFT claim query API --- .../activity/ActivityController.java | 20 + .../common/utils/ECSignatureUtil.java | 125 +++ .../common/utils/EcdsaRecoverUtil.java | 58 -- .../common/utils/SignatureGeneration.java | 62 -- .../nft/config/ContractConfigService.java | 16 +- .../nft/config/EcdsaKeyConfigService.java | 6 +- .../nft/contract/WarCraftContract.java | 776 ++++++++++++++++++ .../nft/service/WarCraftContractService.java | 65 ++ 8 files changed, 1003 insertions(+), 125 deletions(-) create mode 100644 src/main/java/com/dl/officialsite/common/utils/ECSignatureUtil.java delete mode 100644 src/main/java/com/dl/officialsite/common/utils/EcdsaRecoverUtil.java delete mode 100644 src/main/java/com/dl/officialsite/common/utils/SignatureGeneration.java create mode 100644 src/main/java/com/dl/officialsite/nft/contract/WarCraftContract.java create mode 100644 src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java diff --git a/src/main/java/com/dl/officialsite/activity/ActivityController.java b/src/main/java/com/dl/officialsite/activity/ActivityController.java index 06c135cc..a112b486 100644 --- a/src/main/java/com/dl/officialsite/activity/ActivityController.java +++ b/src/main/java/com/dl/officialsite/activity/ActivityController.java @@ -16,6 +16,7 @@ import com.dl.officialsite.nft.constant.ContractNameEnum; import com.dl.officialsite.nft.constant.EcdsaKeyTypeEnum; import com.dl.officialsite.nft.dto.SignatureDto; +import com.dl.officialsite.nft.service.WarCraftContractService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -51,6 +52,8 @@ public class ActivityController { private ChainConfig chainConfig; @Autowired private EcdsaKeyConfigService ecdsaKeyConfigService; + @Autowired + private WarCraftContractService warCraftContractService; /** * 获取活动中用户的状态 @@ -118,4 +121,21 @@ public BaseResponse verifyAndMint(@NotNull @RequestParam("chainId") String chain return BaseResponse.failWithReason("1204", "Generate signature failed."); } + /** + * 检查用户是否完成所有任务,如果完成,则生成 NFT mint 签名 + */ + @GetMapping("/claim/result") + public BaseResponse claimResult(@NotNull @RequestParam("chainId") String chainIdParam, + @RequestParam(required = false) String addressForTesting, + @RequestParam(required = false, defaultValue = "WarCraft") String contractName, + HttpSession session) { + String chainId = Arrays.stream(chainConfig.getIds()).filter(id -> StringUtils.equalsIgnoreCase(chainIdParam, id)) + .findFirst() + .orElseThrow(() -> new BizException(PARAM_ERROR.getCode(), String.format("Chain id %s not exists", chainIdParam))); + + SessionUserInfo sessionUserInfo = HttpSessionUtils.getMember(session); + final String address = sessionUserInfo != null ? sessionUserInfo.getAddress() : addressForTesting; + + return this.warCraftContractService.rank(address, ContractNameEnum.fromValue(contractName), chainId); + } } \ No newline at end of file diff --git a/src/main/java/com/dl/officialsite/common/utils/ECSignatureUtil.java b/src/main/java/com/dl/officialsite/common/utils/ECSignatureUtil.java new file mode 100644 index 00000000..18586674 --- /dev/null +++ b/src/main/java/com/dl/officialsite/common/utils/ECSignatureUtil.java @@ -0,0 +1,125 @@ +package com.dl.officialsite.common.utils; + +import org.apache.commons.lang3.StringUtils; +import org.web3j.abi.TypeEncoder; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.DynamicStruct; +import org.web3j.abi.datatypes.Uint; +import org.web3j.abi.datatypes.generated.Uint256; +import org.web3j.crypto.Credentials; +import org.web3j.crypto.Hash; +import org.web3j.crypto.Keys; +import org.web3j.crypto.Sign; +import org.web3j.utils.Numeric; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.security.SignatureException; + +public class ECSignatureUtil { + + private static final String MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n32"; + + + public static String sign(Credentials credentials, String receiverAddress, BigInteger seed, BigInteger signedAt, + BigInteger chainId, String nftAddress) { + Sign.SignatureData signature = + Sign.signMessage( + toEthSignedMessageHash(sha3AbiEncodedData(receiverAddress, seed, signedAt, chainId, nftAddress)), + credentials.getEcKeyPair(), false); + + byte[] retVal = new byte[65]; + System.arraycopy(signature.getR(), 0, retVal, 0, 32); + System.arraycopy(signature.getS(), 0, retVal, 32, 32); + System.arraycopy(signature.getV(), 0, retVal, 64, 1); + return Numeric.toHexString(retVal); + } + + private static byte[] toEthSignedMessageHash(String sha3AbiEncodedData) { + byte[] prefixBytes = MESSAGE_PREFIX.getBytes(); + byte[] messageBytes = Numeric.hexStringToByteArray(sha3AbiEncodedData); + + byte[] msgBytes = new byte[MESSAGE_PREFIX.getBytes().length + messageBytes.length]; + System.arraycopy(prefixBytes, 0, msgBytes, 0, prefixBytes.length); + System.arraycopy(messageBytes, 0, msgBytes, prefixBytes.length, messageBytes.length); + + return Hash.sha3(msgBytes); + } + + public static BigInteger randomSeed() { + // Create a SecureRandom instance + SecureRandom random = new SecureRandom(); + + // Specify the bit length for the BigInteger + int bitLength = 128; // You can change this to any size you need + + // Generate a random BigInteger + return new BigInteger(bitLength, random); + } + + /** + * Sha3 == keccak256 + * + * @param receiverAddress + * @param seed + * @param signedAt + * @param chainId + * @param nftAddress + * @return + */ + private static String sha3AbiEncodedData(String receiverAddress, BigInteger seed, BigInteger signedAt, + BigInteger chainId, String nftAddress) { + return Hash.sha3(abiEncode(receiverAddress, seed, signedAt, chainId, nftAddress)); + } + + private static String abiEncode(String receiverAddress, BigInteger seed, BigInteger signedAt, + BigInteger chainId, String nftAddress) { + return TypeEncoder.encode(new DynamicStruct( + new Address(receiverAddress), + new Uint256(seed), + new Uint256(signedAt), + new Uint(chainId), + new Address(nftAddress) + )); + } + + public static boolean verifySignature(String signature, + String expectedAddress, + String receiverAddress, + BigInteger seed, + BigInteger signedAt, + BigInteger chainId, + String nftAddress) { + byte[] ethSignedMessageHash = toEthSignedMessageHash(sha3AbiEncodedData(receiverAddress, seed, signedAt, chainId, nftAddress)); + + String extractedAddress = recoverAddress(ethSignedMessageHash, signature); + + return StringUtils.equalsIgnoreCase(expectedAddress, extractedAddress); + } + + public static String recoverAddress(byte[] digest, String signature) { + if (signature.startsWith("0x")) { + signature = signature.substring(2); + } + + // No need to prepend these strings with 0x because + // Numeric.hexStringToByteArray() accepts both formats + String r = signature.substring(0, 64); + String s = signature.substring(64, 128); + String v = signature.substring(128, 130); + + BigInteger pubkey = null; + try { + pubkey = Sign.signedMessageHashToKey(digest, + new Sign.SignatureData( + Numeric.hexStringToByteArray(v)[0], + Numeric.hexStringToByteArray(r), + Numeric.hexStringToByteArray(s))); + } catch (SignatureException e) { + throw new RuntimeException(e); + } + + return "0x" + Keys.getAddress(pubkey); + } + +} diff --git a/src/main/java/com/dl/officialsite/common/utils/EcdsaRecoverUtil.java b/src/main/java/com/dl/officialsite/common/utils/EcdsaRecoverUtil.java deleted file mode 100644 index 7a1eea92..00000000 --- a/src/main/java/com/dl/officialsite/common/utils/EcdsaRecoverUtil.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.dl.officialsite.common.utils; - -import org.web3j.crypto.ECDSASignature; -import org.web3j.crypto.Hash; -import org.web3j.crypto.Keys; -import org.web3j.crypto.Sign; -import org.web3j.crypto.Sign.SignatureData; -import org.web3j.utils.Numeric; - -import java.math.BigInteger; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -public class EcdsaRecoverUtil { - private static final String MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n"; - - public static String verifyMessage(String message, String signature) { - return EcdsaRecoverUtil.recoverAddress(EcdsaRecoverUtil.hashMessage(message), signature); - } - - public static String hashMessage(String message) { - return Hash.sha3( - Numeric.toHexStringNoPrefix( - (EcdsaRecoverUtil.MESSAGE_PREFIX + message.length() + message).getBytes(StandardCharsets.UTF_8))); - } - - public static String recoverAddress(String digest, String signature) { - SignatureData signatureData = EcdsaRecoverUtil.getSignatureData(signature); - int header = 0; - for (byte b : signatureData.getV()) { - header = (header << 8) + (b & 0xFF); - } - if (header < 27 || header > 34) { - return null; - } - int recId = header - 27; - BigInteger key = Sign.recoverFromSignature( - recId, - new ECDSASignature( - new BigInteger(1, signatureData.getR()), new BigInteger(1, signatureData.getS())), - Numeric.hexStringToByteArray(digest)); - if (key == null) { - return null; - } - return ("0x" + Keys.getAddress(key)).trim(); - } - - private static SignatureData getSignatureData(String signature) { - byte[] signatureBytes = Numeric.hexStringToByteArray(signature); - byte v = signatureBytes[64]; - if (v < 27) { - v += 27; - } - byte[] r = (byte[]) Arrays.copyOfRange(signatureBytes, 0, 32); - byte[] s = (byte[]) Arrays.copyOfRange(signatureBytes, 32, 64); - return new SignatureData(v, r, s); - } -} \ No newline at end of file diff --git a/src/main/java/com/dl/officialsite/common/utils/SignatureGeneration.java b/src/main/java/com/dl/officialsite/common/utils/SignatureGeneration.java deleted file mode 100644 index a6f8e36d..00000000 --- a/src/main/java/com/dl/officialsite/common/utils/SignatureGeneration.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.dl.officialsite.common.utils; - -import org.apache.commons.lang3.StringUtils; -import org.web3j.abi.TypeEncoder; -import org.web3j.abi.datatypes.Address; -import org.web3j.abi.datatypes.DynamicStruct; -import org.web3j.abi.datatypes.Uint; -import org.web3j.crypto.Credentials; -import org.web3j.crypto.Hash; -import org.web3j.crypto.Sign; -import org.web3j.utils.Numeric; - -import java.math.BigInteger; -import java.security.SecureRandom; - -public class SignatureGeneration { - - public static String sign(Credentials credentials, String receiverAddress, BigInteger seed, BigInteger signedAt, - BigInteger chainId, String nftAddress) { - Sign.SignatureData signature = - Sign.signPrefixedMessage(concatParams(receiverAddress, seed, signedAt, chainId, nftAddress).getBytes(), - credentials.getEcKeyPair()); - byte[] retval = new byte[65]; - System.arraycopy(signature.getR(), 0, retval, 0, 32); - System.arraycopy(signature.getS(), 0, retval, 32, 32); - System.arraycopy(signature.getV(), 0, retval, 64, 1); - return Numeric.toHexString(retval); - } - - public static boolean verifySignature(String signature, - String expectedAddress, - String receiverAddress, BigInteger seed, BigInteger signedAt, - BigInteger chainId, String nftAddress) { - String messageValue = concatParams(receiverAddress, seed, signedAt, chainId, nftAddress); - String extractedAddress = EcdsaRecoverUtil.verifyMessage(messageValue, signature); - return StringUtils.equalsIgnoreCase(expectedAddress, extractedAddress); - } - - public static BigInteger randomSeed() { - // Create a SecureRandom instance - SecureRandom random = new SecureRandom(); - - // Specify the bit length for the BigInteger - int bitLength = 128; // You can change this to any size you need - - // Generate a random BigInteger - return new BigInteger(bitLength, random); - } - - private static String concatParams(String receiverAddress, BigInteger seed, BigInteger signedAt, - BigInteger chainId, String nftAddress) { - return Hash.sha3(TypeEncoder.encode(new DynamicStruct( - new Address(receiverAddress), - new Uint(seed), - new Uint(signedAt), - new Uint(chainId), - new Address(nftAddress) - ))); - } - - -} diff --git a/src/main/java/com/dl/officialsite/nft/config/ContractConfigService.java b/src/main/java/com/dl/officialsite/nft/config/ContractConfigService.java index baa2046b..2a32ed50 100644 --- a/src/main/java/com/dl/officialsite/nft/config/ContractConfigService.java +++ b/src/main/java/com/dl/officialsite/nft/config/ContractConfigService.java @@ -32,14 +32,25 @@ public void startUpOrRefresh() { } public String getContractAddressByName(ContractNameEnum contractName, String chainId) { + return findByContractNameAndChainId(contractName, chainId) + .map(ContractAddressItem::getAddress) + .orElse(""); + } + + public String getRpcAddressByName(ContractNameEnum contractName, String chainId) { + return findByContractNameAndChainId(contractName, chainId) + .map(ContractAddressItem::getRpcAddress) + .orElse(""); + } + + private Optional findByContractNameAndChainId(ContractNameEnum contractName, String chainId){ return Optional.ofNullable(contractAddressConfig) .map(ContractAddressConfig::getContractAddressItemList) .flatMap(list -> list.stream() .filter(item -> StringUtils.equalsIgnoreCase(item.getContractName(), contractName.getContractName())) .filter(item -> StringUtils.equalsIgnoreCase(item.getChainId(), chainId)) - .map(ContractAddressItem::getAddress) .findFirst() - ).orElse(""); + ); } } @@ -54,4 +65,5 @@ class ContractAddressItem { private String chainId; private String chainName; private String address; + private String rpcAddress; } diff --git a/src/main/java/com/dl/officialsite/nft/config/EcdsaKeyConfigService.java b/src/main/java/com/dl/officialsite/nft/config/EcdsaKeyConfigService.java index 1423f229..8ea26c6c 100644 --- a/src/main/java/com/dl/officialsite/nft/config/EcdsaKeyConfigService.java +++ b/src/main/java/com/dl/officialsite/nft/config/EcdsaKeyConfigService.java @@ -1,6 +1,6 @@ package com.dl.officialsite.nft.config; -import com.dl.officialsite.common.utils.SignatureGeneration; +import com.dl.officialsite.common.utils.ECSignatureUtil; import com.dl.officialsite.config.bean.Configurable; import com.dl.officialsite.config.bean.Refreshable; import com.dl.officialsite.config.constant.ConfigEnum; @@ -48,7 +48,7 @@ public SignatureDto sign(EcdsaKeyTypeEnum keyType, ContractNameEnum contractName return null; } - BigInteger seed = SignatureGeneration.randomSeed(); + BigInteger seed = ECSignatureUtil.randomSeed(); long signedAt = Instant.now().getEpochSecond(); return Optional.ofNullable(ecdsaPrivateKeyConfig) @@ -59,7 +59,7 @@ public SignatureDto sign(EcdsaKeyTypeEnum keyType, ContractNameEnum contractName .map(privateKey -> new SignatureDto(receiverAddress, signedAt, - SignatureGeneration.sign(Credentials.create(privateKey), receiverAddress, seed, BigInteger.valueOf(signedAt), + ECSignatureUtil.sign(Credentials.create(privateKey), receiverAddress, seed, BigInteger.valueOf(signedAt), BigInteger.valueOf(Long.parseLong(chainId)), contractAddress), Numeric.toHexStringWithPrefix(seed), chainId, diff --git a/src/main/java/com/dl/officialsite/nft/contract/WarCraftContract.java b/src/main/java/com/dl/officialsite/nft/contract/WarCraftContract.java new file mode 100644 index 00000000..02927bcc --- /dev/null +++ b/src/main/java/com/dl/officialsite/nft/contract/WarCraftContract.java @@ -0,0 +1,776 @@ +package com.dl.officialsite.nft.contract; + +import io.reactivex.Flowable; +import io.reactivex.functions.Function; +import org.web3j.abi.EventEncoder; +import org.web3j.abi.FunctionEncoder; +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.Address; +import org.web3j.abi.datatypes.Bool; +import org.web3j.abi.datatypes.Event; +import org.web3j.abi.datatypes.Type; +import org.web3j.abi.datatypes.Utf8String; +import org.web3j.abi.datatypes.generated.Uint256; +import org.web3j.crypto.Credentials; +import org.web3j.protocol.Web3j; +import org.web3j.protocol.core.DefaultBlockParameter; +import org.web3j.protocol.core.RemoteCall; +import org.web3j.protocol.core.RemoteFunctionCall; +import org.web3j.protocol.core.methods.request.EthFilter; +import org.web3j.protocol.core.methods.response.BaseEventResponse; +import org.web3j.protocol.core.methods.response.Log; +import org.web3j.protocol.core.methods.response.TransactionReceipt; +import org.web3j.tx.Contract; +import org.web3j.tx.TransactionManager; +import org.web3j.tx.gas.ContractGasProvider; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + *

Auto generated code. + *

Do not modify! + *

Please use the web3j command line tools, + * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the + * codegen module to update. + * + *

Generated with web3j version 1.4.2. + */ +@SuppressWarnings("rawtypes") +public class WarCraftContract extends Contract { + public static final String BINARY = "608060405234801561000f575f80fd5b50604051613dcf380380613dcf83398181016040528101906100319190610398565b338484815f9081610042919061065d565b508060019081610052919061065d565b5050505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036100c5575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016100bc919061073b565b60405180910390fd5b6100d48161012e60201b60201c565b508160085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060099081610124919061065d565b5050505050610754565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f604051905090565b5f80fd5b5f80fd5b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6102508261020a565b810181811067ffffffffffffffff8211171561026f5761026e61021a565b5b80604052505050565b5f6102816101f1565b905061028d8282610247565b919050565b5f67ffffffffffffffff8211156102ac576102ab61021a565b5b6102b58261020a565b9050602081019050919050565b8281835e5f83830152505050565b5f6102e26102dd84610292565b610278565b9050828152602081018484840111156102fe576102fd610206565b5b6103098482856102c2565b509392505050565b5f82601f83011261032557610324610202565b5b81516103358482602086016102d0565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6103678261033e565b9050919050565b6103778161035d565b8114610381575f80fd5b50565b5f815190506103928161036e565b92915050565b5f805f80608085870312156103b0576103af6101fa565b5b5f85015167ffffffffffffffff8111156103cd576103cc6101fe565b5b6103d987828801610311565b945050602085015167ffffffffffffffff8111156103fa576103f96101fe565b5b61040687828801610311565b935050604061041787828801610384565b925050606085015167ffffffffffffffff811115610438576104376101fe565b5b61044487828801610311565b91505092959194509250565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061049e57607f821691505b6020821081036104b1576104b061045a565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026105137fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826104d8565b61051d86836104d8565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61056161055c61055784610535565b61053e565b610535565b9050919050565b5f819050919050565b61057a83610547565b61058e61058682610568565b8484546104e4565b825550505050565b5f90565b6105a2610596565b6105ad818484610571565b505050565b5b818110156105d0576105c55f8261059a565b6001810190506105b3565b5050565b601f821115610615576105e6816104b7565b6105ef846104c9565b810160208510156105fe578190505b61061261060a856104c9565b8301826105b2565b50505b505050565b5f82821c905092915050565b5f6106355f198460080261061a565b1980831691505092915050565b5f61064d8383610626565b9150826002028217905092915050565b61066682610450565b67ffffffffffffffff81111561067f5761067e61021a565b5b6106898254610487565b6106948282856105d4565b5f60209050601f8311600181146106c5575f84156106b3578287015190505b6106bd8582610642565b865550610724565b601f1984166106d3866104b7565b5f5b828110156106fa578489015182556001820191506020850194506020810190506106d5565b868310156107175784890151610713601f891682610626565b8355505b6001600288020188555050505b505050505050565b6107358161035d565b82525050565b5f60208201905061074e5f83018461072c565b92915050565b61366e806107615f395ff3fe608060405234801561000f575f80fd5b50600436106101ee575f3560e01c80636c0360eb1161010d578063a22cb465116100a0578063c87b56dd1161006f578063c87b56dd146105ca578063e985e9c5146105fa578063f2fde38b1461062a578063f76f950e14610646576101ee565b8063a22cb46514610544578063a562219314610560578063b88d4fde14610590578063c6fc65c3146105ac576101ee565b80638da5cb5b116100dc5780638da5cb5b146104a857806395d89b41146104c65780639726a197146104e4578063a195b69c14610514576101ee565b80636c0360eb146104205780636c8b703f1461043e57806370a082311461046e578063715018a61461049e576101ee565b80632530c9051161018557806342842e0e1161015457806342842e0e1461039a57806355f804b3146103b657806362e9685b146103d25780636352211e146103f0576101ee565b80632530c905146103005780632a73dead146103305780632ada8a321461034e578063414b78231461036a576101ee565b806312d8b659116101c157806312d8b6591461028c57806318160ddd146102a85780631cc7d743146102c657806323b872dd146102e4576101ee565b806301ffc9a7146101f257806306fdde0314610222578063081812fc14610240578063095ea7b314610270575b5f80fd5b61020c60048036038101906102079190612775565b610676565b60405161021991906127ba565b60405180910390f35b61022a610757565b6040516102379190612843565b60405180910390f35b61025a60048036038101906102559190612896565b6107e6565b6040516102679190612900565b60405180910390f35b61028a60048036038101906102859190612943565b610801565b005b6102a660048036038101906102a19190612981565b610817565b005b6102b0610899565b6040516102bd91906129bb565b60405180910390f35b6102ce6108a2565b6040516102db9190612900565b60405180910390f35b6102fe60048036038101906102f991906129d4565b6108c7565b005b61031a60048036038101906103159190612896565b6109c6565b60405161032791906129bb565b60405180910390f35b6103386109fe565b60405161034591906129bb565b60405180910390f35b61036860048036038101906103639190612a85565b610a04565b005b610384600480360381019061037f9190612981565b610c68565b60405161039191906129bb565b60405180910390f35b6103b460048036038101906103af91906129d4565b610c7d565b005b6103d060048036038101906103cb9190612c31565b610c9c565b005b6103da610cee565b6040516103e791906129bb565b60405180910390f35b61040a60048036038101906104059190612896565b610cf3565b6040516104179190612900565b60405180910390f35b610428610d04565b6040516104359190612843565b60405180910390f35b61045860048036038101906104539190612896565b610d90565b6040516104659190612843565b60405180910390f35b61048860048036038101906104839190612981565b610e2b565b60405161049591906129bb565b60405180910390f35b6104a6610ee1565b005b6104b0610ef4565b6040516104bd9190612900565b60405180910390f35b6104ce610f1c565b6040516104db9190612843565b60405180910390f35b6104fe60048036038101906104f99190612896565b610fac565b60405161050b91906127ba565b60405180910390f35b61052e60048036038101906105299190612981565b610fc9565b60405161053b91906127ba565b60405180910390f35b61055e60048036038101906105599190612ca2565b611012565b005b61057a60048036038101906105759190612981565b611028565b60405161058791906127ba565b60405180910390f35b6105aa60048036038101906105a59190612d7e565b611045565b005b6105b4611062565b6040516105c191906129bb565b60405180910390f35b6105e460048036038101906105df9190612896565b611068565b6040516105f19190612843565b60405180910390f35b610614600480360381019061060f9190612dfe565b6110ce565b60405161062191906127ba565b60405180910390f35b610644600480360381019061063f9190612981565b61115c565b005b610660600480360381019061065b9190612896565b6111e0565b60405161066d9190612843565b60405180910390f35b5f7f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061074057507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610750575061074f8261133e565b5b9050919050565b60605f805461076590612e69565b80601f016020809104026020016040519081016040528092919081815260200182805461079190612e69565b80156107dc5780601f106107b3576101008083540402835291602001916107dc565b820191905f5260205f20905b8154815290600101906020018083116107bf57829003601f168201915b5050505050905090565b5f6107f0826113a7565b506107fa8261142d565b9050919050565b610813828261080e611466565b61146d565b5050565b61081f61147f565b8060085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507fb3a45a79b2d77631258297d008a7191793950c864ee1a142b02af72654728cad8160405161088e9190612900565b60405180910390a150565b5f600a54905090565b60085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610937575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161092e9190612900565b60405180910390fd5b5f61094a8383610945611466565b611506565b90508373ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146109c0578382826040517f64283d7b0000000000000000000000000000000000000000000000000000000081526004016109b793929190612e99565b60405180910390fd5b50505050565b5f42438343406040516020016109df9493929190612f17565b604051602081830303815290604052805190602001205f1c9050919050565b610e1081565b610e1042610a129190612f91565b841015610a4b576040517fdf4cc36d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a5485610fc9565b15610a8b576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610a988584868585611711565b610ace576040517fc1606c2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ad8600761183a565b5f610ae3600761184e565b905080600e5f8873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055505f606c610b33866109c6565b610b3d9190612ff1565b90505f610b498261185a565b90505f610b55826111e0565b9050610b6189856118b8565b610b6b84826118d5565b6001600b5f8481526020019081526020015f205f6101000a81548160ff0219169083151502179055506001600d5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055507f032bc66be43dbccb7487781d168eb7bda224628a3b2c3388bdf69b532a3a161184604051610c1891906129bb565b60405180910390a17fb47026c665b5f2f16784988d451e2d894813dbea05be59eaba06043d9f1a0a90338a8684604051610c559493929190613021565b60405180910390a1505050505050505050565b600e602052805f5260405f205f915090505481565b610c9783838360405180602001604052805f815250611045565b505050565b610ca461147f565b8060099081610cb39190613208565b507f23c8c9488efebfd474e85a7956de6f39b17c7ab88502d42a623db2d8e382bbaa81604051610ce39190612843565b60405180910390a150565b606c81565b5f610cfd826113a7565b9050919050565b60098054610d1190612e69565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3d90612e69565b8015610d885780601f10610d5f57610100808354040283529160200191610d88565b820191905f5260205f20905b815481529060010190602001808311610d6b57829003601f168201915b505050505081565b600c602052805f5260405f205f915090508054610dac90612e69565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd890612e69565b8015610e235780601f10610dfa57610100808354040283529160200191610e23565b820191905f5260205f20905b815481529060010190602001808311610e0657829003601f168201915b505050505081565b5f8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610e9c575f6040517f89c62b64000000000000000000000000000000000000000000000000000000008152600401610e939190612900565b60405180910390fd5b60035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b610ee961147f565b610ef25f611902565b565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060018054610f2b90612e69565b80601f0160208091040260200160405190810160405280929190818152602001828054610f5790612e69565b8015610fa25780601f10610f7957610100808354040283529160200191610fa2565b820191905f5260205f20905b815481529060010190602001808311610f8557829003601f168201915b5050505050905090565b600b602052805f5260405f205f915054906101000a900460ff1681565b5f80600e5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205414159050919050565b61102461101d611466565b83836119c5565b5050565b600d602052805f5260405f205f915054906101000a900460ff1681565b6110508484846108c7565b61105c84848484611b2e565b50505050565b600a5481565b6060611073826113a7565b505f61107d611ce0565b90505f81511161109b5760405180602001604052805f8152506110c6565b806110a584611d70565b6040516020016110b6929190613311565b6040516020818303038152906040525b915050919050565b5f60055f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b61116461147f565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036111d4575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016111cb9190612900565b60405180910390fd5b6111dd81611902565b50565b60605f8203611226576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611339565b5f8290505f5b5f821461125557808061123e90613334565b915050600a8261124e919061337b565b915061122c565b5f8167ffffffffffffffff8111156112705761126f612b0d565b5b6040519080825280601f01601f1916602001820160405280156112a25781602001600182028036833780820191505090505b5090505f8290508593505b5f841461133157600a846112c19190612ff1565b60306112cd91906133ab565b60f81b82826112db906133de565b925082815181106112ef576112ee613405565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a8461132a919061337b565b93506112ad565b819450505050505b919050565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f806113b283611e3a565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361142457826040517f7e27328900000000000000000000000000000000000000000000000000000000815260040161141b91906129bb565b60405180910390fd5b80915050919050565b5f60045f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b5f33905090565b61147a8383836001611e73565b505050565b611487611466565b73ffffffffffffffffffffffffffffffffffffffff166114a5610ef4565b73ffffffffffffffffffffffffffffffffffffffff1614611504576114c8611466565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016114fb9190612900565b60405180910390fd5b565b5f8061151184611e3a565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461155257611551818486612032565b5b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146115dd576115915f855f80611e73565b600160035f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825403925050819055505b5f73ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161461165c57600160035f8773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8460025f8681526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4809150509392505050565b5f6041838390501461174f576040517fc1606c2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8686864630604051602001611769959493929190613432565b60405160208183030381529060405280519060200120905060085f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661181785858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f82011690508083019250505050505050611809846120f5565b61212890919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff161491505095945050505050565b6001815f015f828254019250508190555050565b5f815f01549050919050565b5f808290505b600b5f8281526020019081526020015f205f9054906101000a900460ff16156118af5760018161189091906133ab565b9050606c81106118aa57606c816118a79190612ff1565b90505b611860565b80915050919050565b6118d1828260405180602001604052805f815250612152565b5050565b6118de826113a7565b5080600c5f8481526020019081526020015f2090816118fd9190613208565b505050565b5f60065f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160065f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611a3557816040517f5b08ba18000000000000000000000000000000000000000000000000000000008152600401611a2c9190612900565b60405180910390fd5b8060055f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611b2191906127ba565b60405180910390a3505050565b5f8373ffffffffffffffffffffffffffffffffffffffff163b1115611cda578273ffffffffffffffffffffffffffffffffffffffff1663150b7a02611b71611466565b8685856040518563ffffffff1660e01b8152600401611b9394939291906134d5565b6020604051808303815f875af1925050508015611bce57506040513d601f19601f82011682018060405250810190611bcb9190613533565b60015b611c4f573d805f8114611bfc576040519150601f19603f3d011682016040523d82523d5f602084013e611c01565b606091505b505f815103611c4757836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611c3e9190612900565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614611cd857836040517f64a0ae92000000000000000000000000000000000000000000000000000000008152600401611ccf9190612900565b60405180910390fd5b505b50505050565b606060098054611cef90612e69565b80601f0160208091040260200160405190810160405280929190818152602001828054611d1b90612e69565b8015611d665780601f10611d3d57610100808354040283529160200191611d66565b820191905f5260205f20905b815481529060010190602001808311611d4957829003601f168201915b5050505050905090565b60605f6001611d7e8461216d565b0190505f8167ffffffffffffffff811115611d9c57611d9b612b0d565b5b6040519080825280601f01601f191660200182016040528015611dce5781602001600182028036833780820191505090505b5090505f82602001820190505b600115611e2f578080600190039150507f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a8581611e2457611e23612fc4565b5b0494505f8503611ddb575b819350505050919050565b5f60025f8381526020019081526020015f205f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b8080611eab57505f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b15611fdd575f611eba846113a7565b90505f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614158015611f2457508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614155b8015611f375750611f3581846110ce565b155b15611f7957826040517fa9fbf51f000000000000000000000000000000000000000000000000000000008152600401611f709190612900565b60405180910390fd5b8115611fdb57838573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45b505b8360045f8581526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050565b61203d8383836122be565b6120f0575f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036120b157806040517f7e2732890000000000000000000000000000000000000000000000000000000081526004016120a891906129bb565b60405180910390fd5b81816040517f177e802f0000000000000000000000000000000000000000000000000000000081526004016120e792919061355e565b60405180910390fd5b505050565b5f7f19457468657265756d205369676e6564204d6573736167653a0a3332000000005f5281601c52603c5f209050919050565b5f805f80612136868661237e565b92509250925061214682826123d3565b82935050505092915050565b61215c8383612535565b6121685f848484611b2e565b505050565b5f805f90507a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083106121c9577a184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000083816121bf576121be612fc4565b5b0492506040810190505b6d04ee2d6d415b85acef81000000008310612206576d04ee2d6d415b85acef810000000083816121fc576121fb612fc4565b5b0492506020810190505b662386f26fc10000831061223557662386f26fc10000838161222b5761222a612fc4565b5b0492506010810190505b6305f5e100831061225e576305f5e100838161225457612253612fc4565b5b0492506008810190505b612710831061228357612710838161227957612278612fc4565b5b0492506004810190505b606483106122a6576064838161229c5761229b612fc4565b5b0492506002810190505b600a83106122b5576001810190505b80915050919050565b5f8073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561237557508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612336575061233584846110ce565b5b8061237457508273ffffffffffffffffffffffffffffffffffffffff1661235c8361142d565b73ffffffffffffffffffffffffffffffffffffffff16145b5b90509392505050565b5f805f60418451036123be575f805f602087015192506040870151915060608701515f1a90506123b088828585612628565b9550955095505050506123cc565b5f600285515f1b9250925092505b9250925092565b5f60038111156123e6576123e5613585565b5b8260038111156123f9576123f8613585565b5b0315612531576001600381111561241357612412613585565b5b82600381111561242657612425613585565b5b0361245d576040517ff645eedf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600381111561247157612470613585565b5b82600381111561248457612483613585565b5b036124c857805f1c6040517ffce698f70000000000000000000000000000000000000000000000000000000081526004016124bf91906129bb565b60405180910390fd5b6003808111156124db576124da613585565b5b8260038111156124ee576124ed613585565b5b0361253057806040517fd78bce0c00000000000000000000000000000000000000000000000000000000815260040161252791906135c1565b60405180910390fd5b5b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036125a5575f6040517f64a0ae9200000000000000000000000000000000000000000000000000000000815260040161259c9190612900565b60405180910390fd5b5f6125b183835f611506565b90505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614612623575f6040517f73c6ac6e00000000000000000000000000000000000000000000000000000000815260040161261a9190612900565b60405180910390fd5b505050565b5f805f7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0845f1c1115612664575f600385925092509250612705565b5f6001888888886040515f815260200160405260405161268794939291906135f5565b6020604051602081039080840390855afa1580156126a7573d5f803e3d5ffd5b5050506020604051035190505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036126f8575f60015f801b93509350935050612705565b805f805f1b935093509350505b9450945094915050565b5f604051905090565b5f80fd5b5f80fd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61275481612720565b811461275e575f80fd5b50565b5f8135905061276f8161274b565b92915050565b5f6020828403121561278a57612789612718565b5b5f61279784828501612761565b91505092915050565b5f8115159050919050565b6127b4816127a0565b82525050565b5f6020820190506127cd5f8301846127ab565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f612815826127d3565b61281f81856127dd565b935061282f8185602086016127ed565b612838816127fb565b840191505092915050565b5f6020820190508181035f83015261285b818461280b565b905092915050565b5f819050919050565b61287581612863565b811461287f575f80fd5b50565b5f813590506128908161286c565b92915050565b5f602082840312156128ab576128aa612718565b5b5f6128b884828501612882565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6128ea826128c1565b9050919050565b6128fa816128e0565b82525050565b5f6020820190506129135f8301846128f1565b92915050565b612922816128e0565b811461292c575f80fd5b50565b5f8135905061293d81612919565b92915050565b5f806040838503121561295957612958612718565b5b5f6129668582860161292f565b925050602061297785828601612882565b9150509250929050565b5f6020828403121561299657612995612718565b5b5f6129a38482850161292f565b91505092915050565b6129b581612863565b82525050565b5f6020820190506129ce5f8301846129ac565b92915050565b5f805f606084860312156129eb576129ea612718565b5b5f6129f88682870161292f565b9350506020612a098682870161292f565b9250506040612a1a86828701612882565b9150509250925092565b5f80fd5b5f80fd5b5f80fd5b5f8083601f840112612a4557612a44612a24565b5b8235905067ffffffffffffffff811115612a6257612a61612a28565b5b602083019150836001820283011115612a7e57612a7d612a2c565b5b9250929050565b5f805f805f60808688031215612a9e57612a9d612718565b5b5f612aab8882890161292f565b9550506020612abc88828901612882565b9450506040612acd88828901612882565b935050606086013567ffffffffffffffff811115612aee57612aed61271c565b5b612afa88828901612a30565b92509250509295509295909350565b5f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b612b43826127fb565b810181811067ffffffffffffffff82111715612b6257612b61612b0d565b5b80604052505050565b5f612b7461270f565b9050612b808282612b3a565b919050565b5f67ffffffffffffffff821115612b9f57612b9e612b0d565b5b612ba8826127fb565b9050602081019050919050565b828183375f83830152505050565b5f612bd5612bd084612b85565b612b6b565b905082815260208101848484011115612bf157612bf0612b09565b5b612bfc848285612bb5565b509392505050565b5f82601f830112612c1857612c17612a24565b5b8135612c28848260208601612bc3565b91505092915050565b5f60208284031215612c4657612c45612718565b5b5f82013567ffffffffffffffff811115612c6357612c6261271c565b5b612c6f84828501612c04565b91505092915050565b612c81816127a0565b8114612c8b575f80fd5b50565b5f81359050612c9c81612c78565b92915050565b5f8060408385031215612cb857612cb7612718565b5b5f612cc58582860161292f565b9250506020612cd685828601612c8e565b9150509250929050565b5f67ffffffffffffffff821115612cfa57612cf9612b0d565b5b612d03826127fb565b9050602081019050919050565b5f612d22612d1d84612ce0565b612b6b565b905082815260208101848484011115612d3e57612d3d612b09565b5b612d49848285612bb5565b509392505050565b5f82601f830112612d6557612d64612a24565b5b8135612d75848260208601612d10565b91505092915050565b5f805f8060808587031215612d9657612d95612718565b5b5f612da38782880161292f565b9450506020612db48782880161292f565b9350506040612dc587828801612882565b925050606085013567ffffffffffffffff811115612de657612de561271c565b5b612df287828801612d51565b91505092959194509250565b5f8060408385031215612e1457612e13612718565b5b5f612e218582860161292f565b9250506020612e328582860161292f565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680612e8057607f821691505b602082108103612e9357612e92612e3c565b5b50919050565b5f606082019050612eac5f8301866128f1565b612eb960208301856129ac565b612ec660408301846128f1565b949350505050565b5f819050919050565b612ee8612ee382612863565b612ece565b82525050565b5f819050919050565b5f819050919050565b612f11612f0c82612eee565b612ef7565b82525050565b5f612f228287612ed7565b602082019150612f328286612ed7565b602082019150612f428285612ed7565b602082019150612f528284612f00565b60208201915081905095945050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f612f9b82612863565b9150612fa683612863565b9250828203905081811115612fbe57612fbd612f64565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f612ffb82612863565b915061300683612863565b92508261301657613015612fc4565b5b828206905092915050565b5f6080820190506130345f8301876128f1565b61304160208301866128f1565b61304e60408301856129ac565b8181036060830152613060818461280b565b905095945050505050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026130c77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261308c565b6130d1868361308c565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61310c61310761310284612863565b6130e9565b612863565b9050919050565b5f819050919050565b613125836130f2565b61313961313182613113565b848454613098565b825550505050565b5f90565b61314d613141565b61315881848461311c565b505050565b5b8181101561317b576131705f82613145565b60018101905061315e565b5050565b601f8211156131c0576131918161306b565b61319a8461307d565b810160208510156131a9578190505b6131bd6131b58561307d565b83018261315d565b50505b505050565b5f82821c905092915050565b5f6131e05f19846008026131c5565b1980831691505092915050565b5f6131f883836131d1565b9150826002028217905092915050565b613211826127d3565b67ffffffffffffffff81111561322a57613229612b0d565b5b6132348254612e69565b61323f82828561317f565b5f60209050601f831160018114613270575f841561325e578287015190505b61326885826131ed565b8655506132cf565b601f19841661327e8661306b565b5f5b828110156132a557848901518255600182019150602085019450602081019050613280565b868310156132c257848901516132be601f8916826131d1565b8355505b6001600288020188555050505b505050505050565b5f81905092915050565b5f6132eb826127d3565b6132f581856132d7565b93506133058185602086016127ed565b80840191505092915050565b5f61331c82856132e1565b915061332882846132e1565b91508190509392505050565b5f61333e82612863565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036133705761336f612f64565b5b600182019050919050565b5f61338582612863565b915061339083612863565b9250826133a05761339f612fc4565b5b828204905092915050565b5f6133b582612863565b91506133c083612863565b92508282019050808211156133d8576133d7612f64565b5b92915050565b5f6133e882612863565b91505f82036133fa576133f9612f64565b5b600182039050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f60a0820190506134455f8301886128f1565b61345260208301876129ac565b61345f60408301866129ac565b61346c60608301856129ac565b61347960808301846128f1565b9695505050505050565b5f81519050919050565b5f82825260208201905092915050565b5f6134a782613483565b6134b1818561348d565b93506134c18185602086016127ed565b6134ca816127fb565b840191505092915050565b5f6080820190506134e85f8301876128f1565b6134f560208301866128f1565b61350260408301856129ac565b8181036060830152613514818461349d565b905095945050505050565b5f8151905061352d8161274b565b92915050565b5f6020828403121561354857613547612718565b5b5f6135558482850161351f565b91505092915050565b5f6040820190506135715f8301856128f1565b61357e60208301846129ac565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6135bb81612eee565b82525050565b5f6020820190506135d45f8301846135b2565b92915050565b5f60ff82169050919050565b6135ef816135da565b82525050565b5f6080820190506136085f8301876135b2565b61361560208301866135e6565b61362260408301856135b2565b61362f60608301846135b2565b9594505050505056fea264697066735822122063edf5730113c5d17f8e6b51222e3bf3ecdb8f508e65421693981780706136d464736f6c63430008190033\n"; + + public static final String FUNC_RANKLENGTH = "RANKLENGTH"; + + public static final String FUNC_SIGNATURE_VALIDITY = "SIGNATURE_VALIDITY"; + + public static final String FUNC_APPROVE = "approve"; + + public static final String FUNC_BALANCEOF = "balanceOf"; + + public static final String FUNC_BASEURI = "baseURI"; + + public static final String FUNC_CLAIM = "claim"; + + public static final String FUNC_CLAIMEDBITMAP = "claimedBitMap"; + + public static final String FUNC_CLAIMEDTOKENIDBY = "claimedTokenIdBy"; + + public static final String FUNC_CLAIMEDTOTAL = "claimedTotal"; + + public static final String FUNC_GETAPPROVED = "getApproved"; + + public static final String FUNC_HASUSERCLAIMED = "hasUserClaimed"; + + public static final String FUNC_ISAPPROVEDFORALL = "isApprovedForAll"; + + public static final String FUNC_NAME = "name"; + + public static final String FUNC_OWNER = "owner"; + + public static final String FUNC_OWNEROF = "ownerOf"; + + public static final String FUNC_RAND = "rand"; + + public static final String FUNC_RENOUNCEOWNERSHIP = "renounceOwnership"; + + public static final String FUNC_safeTransferFrom = "safeTransferFrom"; + + public static final String FUNC_SETAPPROVALFORALL = "setApprovalForAll"; + + public static final String FUNC_SETBASEURI = "setBaseURI"; + + public static final String FUNC_SETVALIDSIGNER = "setValidSigner"; + + public static final String FUNC_SUPPORTSINTERFACE = "supportsInterface"; + + public static final String FUNC_SYMBOL = "symbol"; + + public static final String FUNC_TOKENURI = "tokenURI"; + + public static final String FUNC_TOKENURIS = "tokenURIs"; + + public static final String FUNC_TOTALSUPPLY = "totalSupply"; + + public static final String FUNC_TRANSFERFROM = "transferFrom"; + + public static final String FUNC_TRANSFEROWNERSHIP = "transferOwnership"; + + public static final String FUNC_UINT2STR = "uint2str"; + + public static final String FUNC_VALIDRANK = "validRank"; + + public static final String FUNC_VALIDSIGNER = "validSigner"; + + public static final Event APPROVAL_EVENT = new Event("Approval", + Arrays.>asList(new TypeReference

(true) {}, new TypeReference
(true) {}, new TypeReference(true) {})); + ; + + public static final Event APPROVALFORALL_EVENT = new Event("ApprovalForAll", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference() {})); + ; + + public static final Event CLAIMED_EVENT = new Event("Claimed", + Arrays.>asList(new TypeReference
() {}, new TypeReference
() {}, new TypeReference() {}, new TypeReference() {})); + ; + + public static final Event LOCKED_EVENT = new Event("Locked", + Arrays.>asList(new TypeReference() {})); + ; + + public static final Event OWNERSHIPTRANSFERRED_EVENT = new Event("OwnershipTransferred", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {})); + ; + + public static final Event SETBASEURI_EVENT = new Event("SetBaseURI", + Arrays.>asList(new TypeReference() {})); + ; + + public static final Event TRANSFER_EVENT = new Event("Transfer", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference(true) {})); + ; + + public static final Event VALIDSIGNERCHANGED_EVENT = new Event("ValidSignerChanged", + Arrays.>asList(new TypeReference
() {})); + ; + + @Deprecated + protected WarCraftContract(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected WarCraftContract(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected WarCraftContract(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected WarCraftContract(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static List getApprovalEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(APPROVAL_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + ApprovalEventResponse typedResponse = new ApprovalEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.approved = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokenId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable approvalEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public ApprovalEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(APPROVAL_EVENT, log); + ApprovalEventResponse typedResponse = new ApprovalEventResponse(); + typedResponse.log = log; + typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.approved = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokenId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + return typedResponse; + } + }); + } + + public Flowable approvalEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(APPROVAL_EVENT)); + return approvalEventFlowable(filter); + } + + public static List getApprovalForAllEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(APPROVALFORALL_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + ApprovalForAllEventResponse typedResponse = new ApprovalForAllEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.operator = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.approved = (Boolean) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable approvalForAllEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public ApprovalForAllEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(APPROVALFORALL_EVENT, log); + ApprovalForAllEventResponse typedResponse = new ApprovalForAllEventResponse(); + typedResponse.log = log; + typedResponse.owner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.operator = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.approved = (Boolean) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable approvalForAllEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(APPROVALFORALL_EVENT)); + return approvalForAllEventFlowable(filter); + } + + public static List getClaimedEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(CLAIMED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + ClaimedEventResponse typedResponse = new ClaimedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse._sender = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse._receiver = (String) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse._tokenId = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); + typedResponse.url = (String) eventValues.getNonIndexedValues().get(3).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable claimedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public ClaimedEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(CLAIMED_EVENT, log); + ClaimedEventResponse typedResponse = new ClaimedEventResponse(); + typedResponse.log = log; + typedResponse._sender = (String) eventValues.getNonIndexedValues().get(0).getValue(); + typedResponse._receiver = (String) eventValues.getNonIndexedValues().get(1).getValue(); + typedResponse._tokenId = (BigInteger) eventValues.getNonIndexedValues().get(2).getValue(); + typedResponse.url = (String) eventValues.getNonIndexedValues().get(3).getValue(); + return typedResponse; + } + }); + } + + public Flowable claimedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(CLAIMED_EVENT)); + return claimedEventFlowable(filter); + } + + public static List getLockedEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(LOCKED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + LockedEventResponse typedResponse = new LockedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse._tokenId = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable lockedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public LockedEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(LOCKED_EVENT, log); + LockedEventResponse typedResponse = new LockedEventResponse(); + typedResponse.log = log; + typedResponse._tokenId = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable lockedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(LOCKED_EVENT)); + return lockedEventFlowable(filter); + } + + public static List getOwnershipTransferredEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + OwnershipTransferredEventResponse typedResponse = new OwnershipTransferredEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.previousOwner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.newOwner = (String) eventValues.getIndexedValues().get(1).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable ownershipTransferredEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public OwnershipTransferredEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, log); + OwnershipTransferredEventResponse typedResponse = new OwnershipTransferredEventResponse(); + typedResponse.log = log; + typedResponse.previousOwner = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.newOwner = (String) eventValues.getIndexedValues().get(1).getValue(); + return typedResponse; + } + }); + } + + public Flowable ownershipTransferredEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(OWNERSHIPTRANSFERRED_EVENT)); + return ownershipTransferredEventFlowable(filter); + } + + public static List getSetBaseURIEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(SETBASEURI_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + SetBaseURIEventResponse typedResponse = new SetBaseURIEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse._tokenId = (String) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable setBaseURIEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public SetBaseURIEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(SETBASEURI_EVENT, log); + SetBaseURIEventResponse typedResponse = new SetBaseURIEventResponse(); + typedResponse.log = log; + typedResponse._tokenId = (String) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable setBaseURIEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(SETBASEURI_EVENT)); + return setBaseURIEventFlowable(filter); + } + + public static List getTransferEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(TRANSFER_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + TransferEventResponse typedResponse = new TransferEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.to = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokenId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable transferEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public TransferEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(TRANSFER_EVENT, log); + TransferEventResponse typedResponse = new TransferEventResponse(); + typedResponse.log = log; + typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue(); + typedResponse.to = (String) eventValues.getIndexedValues().get(1).getValue(); + typedResponse.tokenId = (BigInteger) eventValues.getIndexedValues().get(2).getValue(); + return typedResponse; + } + }); + } + + public Flowable transferEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(TRANSFER_EVENT)); + return transferEventFlowable(filter); + } + + public static List getValidSignerChangedEvents(TransactionReceipt transactionReceipt) { + List valueList = staticExtractEventParametersWithLog(VALIDSIGNERCHANGED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (EventValuesWithLog eventValues : valueList) { + ValidSignerChangedEventResponse typedResponse = new ValidSignerChangedEventResponse(); + typedResponse.log = eventValues.getLog(); + typedResponse._newValidSigner = (String) eventValues.getNonIndexedValues().get(0).getValue(); + responses.add(typedResponse); + } + return responses; + } + + public Flowable validSignerChangedEventFlowable(EthFilter filter) { + return web3j.ethLogFlowable(filter).map(new Function() { + @Override + public ValidSignerChangedEventResponse apply(Log log) { + EventValuesWithLog eventValues = extractEventParametersWithLog(VALIDSIGNERCHANGED_EVENT, log); + ValidSignerChangedEventResponse typedResponse = new ValidSignerChangedEventResponse(); + typedResponse.log = log; + typedResponse._newValidSigner = (String) eventValues.getNonIndexedValues().get(0).getValue(); + return typedResponse; + } + }); + } + + public Flowable validSignerChangedEventFlowable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) { + EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress()); + filter.addSingleTopic(EventEncoder.encode(VALIDSIGNERCHANGED_EVENT)); + return validSignerChangedEventFlowable(filter); + } + + public RemoteFunctionCall RANKLENGTH() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_RANKLENGTH, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall SIGNATURE_VALIDITY() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_SIGNATURE_VALIDITY, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall approve(String to, BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_APPROVE, + Arrays.asList(new Address(160, to), + new Uint256(tokenId)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall balanceOf(String owner) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_BALANCEOF, + Arrays.asList(new Address(160, owner)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall baseURI() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_BASEURI, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall claim(String _receiver, BigInteger _signedAt, BigInteger _seed, byte[] signature) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_CLAIM, + Arrays.asList(new Address(160, _receiver), + new Uint256(_signedAt), + new Uint256(_seed), + new org.web3j.abi.datatypes.DynamicBytes(signature)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall claimedBitMap(String param0) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_CLAIMEDBITMAP, + Arrays.asList(new Address(160, param0)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, Boolean.class); + } + + public RemoteFunctionCall claimedTokenIdBy(String userAddress) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_CLAIMEDTOKENIDBY, + Arrays.asList(new Address(160, userAddress)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall claimedTotal() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_CLAIMEDTOTAL, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall getApproved(BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_GETAPPROVED, + Arrays.asList(new Uint256(tokenId)), + Arrays.>asList(new TypeReference
() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall hasUserClaimed(String _user) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_HASUSERCLAIMED, + Arrays.asList(new Address(160, _user)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, Boolean.class); + } + + public RemoteFunctionCall isApprovedForAll(String owner, String operator) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_ISAPPROVEDFORALL, + Arrays.asList(new Address(160, owner), + new Address(160, operator)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, Boolean.class); + } + + public RemoteFunctionCall name() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_NAME, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall owner() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_OWNER, + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall ownerOf(BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_OWNEROF, + Arrays.asList(new Uint256(tokenId)), + Arrays.>asList(new TypeReference
() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall rand(BigInteger userSeed) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_RAND, + Arrays.asList(new Uint256(userSeed)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall renounceOwnership() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_RENOUNCEOWNERSHIP, + Arrays.asList(), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall safeTransferFrom(String from, String to, BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_safeTransferFrom, + Arrays.asList(new Address(160, from), + new Address(160, to), + new Uint256(tokenId)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall safeTransferFrom(String from, String to, BigInteger tokenId, byte[] data) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_safeTransferFrom, + Arrays.asList(new Address(160, from), + new Address(160, to), + new Uint256(tokenId), + new org.web3j.abi.datatypes.DynamicBytes(data)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall setApprovalForAll(String operator, Boolean approved) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_SETAPPROVALFORALL, + Arrays.asList(new Address(160, operator), + new Bool(approved)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall setBaseURI(String _newBaseURI) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_SETBASEURI, + Arrays.asList(new Utf8String(_newBaseURI)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall setValidSigner(String _validSigner) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_SETVALIDSIGNER, + Arrays.asList(new Address(160, _validSigner)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall supportsInterface(byte[] interfaceId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_SUPPORTSINTERFACE, + Arrays.asList(new org.web3j.abi.datatypes.generated.Bytes4(interfaceId)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, Boolean.class); + } + + public RemoteFunctionCall symbol() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_SYMBOL, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall tokenURI(BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_TOKENURI, + Arrays.asList(new Uint256(tokenId)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall tokenURIs(BigInteger param0) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_TOKENURIS, + Arrays.asList(new Uint256(param0)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall totalSupply() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_TOTALSUPPLY, + Arrays.asList(), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, BigInteger.class); + } + + public RemoteFunctionCall transferFrom(String from, String to, BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_TRANSFERFROM, + Arrays.asList(new Address(160, from), + new Address(160, to), + new Uint256(tokenId)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall transferOwnership(String newOwner) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_TRANSFEROWNERSHIP, + Arrays.asList(new Address(160, newOwner)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall uint2str(BigInteger _i) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_UINT2STR, + Arrays.asList(new Uint256(_i)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + public RemoteFunctionCall validRank(BigInteger param0) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_VALIDRANK, + Arrays.asList(new Uint256(param0)), + Arrays.>asList(new TypeReference() {})); + return executeRemoteCallSingleValueReturn(function, Boolean.class); + } + + public RemoteFunctionCall validSigner() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_VALIDSIGNER, + Arrays.asList(), + Arrays.>asList(new TypeReference
() {})); + return executeRemoteCallSingleValueReturn(function, String.class); + } + + @Deprecated + public static WarCraftContract load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return new WarCraftContract(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static WarCraftContract load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + return new WarCraftContract(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static WarCraftContract load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return new WarCraftContract(contractAddress, web3j, credentials, contractGasProvider); + } + + public static WarCraftContract load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return new WarCraftContract(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider, String _tokenName, String _tokenSymbol, String _validSigner, String _InitBaseURI) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Utf8String(_tokenName), + new Utf8String(_tokenSymbol), + new Address(160, _validSigner), + new Utf8String(_InitBaseURI))); + return deployRemoteCall(WarCraftContract.class, web3j, credentials, contractGasProvider, BINARY, encodedConstructor); + } + + public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider, String _tokenName, String _tokenSymbol, String _validSigner, String _InitBaseURI) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Utf8String(_tokenName), + new Utf8String(_tokenSymbol), + new Address(160, _validSigner), + new Utf8String(_InitBaseURI))); + return deployRemoteCall(WarCraftContract.class, web3j, transactionManager, contractGasProvider, BINARY, encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String _tokenName, String _tokenSymbol, String _validSigner, String _InitBaseURI) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Utf8String(_tokenName), + new Utf8String(_tokenSymbol), + new Address(160, _validSigner), + new Utf8String(_InitBaseURI))); + return deployRemoteCall(WarCraftContract.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, String _tokenName, String _tokenSymbol, String _validSigner, String _InitBaseURI) { + String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.asList(new Utf8String(_tokenName), + new Utf8String(_tokenSymbol), + new Address(160, _validSigner), + new Utf8String(_InitBaseURI))); + return deployRemoteCall(WarCraftContract.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor); + } + + public static class ApprovalEventResponse extends BaseEventResponse { + public String owner; + + public String approved; + + public BigInteger tokenId; + } + + public static class ApprovalForAllEventResponse extends BaseEventResponse { + public String owner; + + public String operator; + + public Boolean approved; + } + + public static class ClaimedEventResponse extends BaseEventResponse { + public String _sender; + + public String _receiver; + + public BigInteger _tokenId; + + public String url; + } + + public static class LockedEventResponse extends BaseEventResponse { + public BigInteger _tokenId; + } + + public static class OwnershipTransferredEventResponse extends BaseEventResponse { + public String previousOwner; + + public String newOwner; + } + + public static class SetBaseURIEventResponse extends BaseEventResponse { + public String _tokenId; + } + + public static class TransferEventResponse extends BaseEventResponse { + public String from; + + public String to; + + public BigInteger tokenId; + } + + public static class ValidSignerChangedEventResponse extends BaseEventResponse { + public String _newValidSigner; + } +} diff --git a/src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java b/src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java new file mode 100644 index 00000000..98fc612a --- /dev/null +++ b/src/main/java/com/dl/officialsite/nft/service/WarCraftContractService.java @@ -0,0 +1,65 @@ +package com.dl.officialsite.nft.service; + +import com.dl.officialsite.common.base.BaseResponse; +import com.dl.officialsite.nft.config.ContractConfigService; +import com.dl.officialsite.nft.constant.ContractNameEnum; +import com.dl.officialsite.nft.contract.WarCraftContract; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.web3j.protocol.Web3j; +import org.web3j.protocol.http.HttpService; +import org.web3j.tx.ClientTransactionManager; +import org.web3j.tx.gas.ContractGasProvider; +import org.web3j.tx.gas.StaticGasProvider; + +import java.math.BigInteger; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Service +public class WarCraftContractService { + private static final String ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; + private static final ContractGasProvider ZERO_GAS_PROVIDER = new StaticGasProvider(BigInteger.ZERO, BigInteger.ZERO); + public static final long TIMEOUT = 5; + + @Autowired + private ContractConfigService contractConfigService; + + public BaseResponse rank(String address, ContractNameEnum contractName, String chainId) { + String contractAddress = this.contractConfigService.getContractAddressByName(contractName, chainId); + String rpcAddress = this.contractConfigService.getRpcAddressByName(contractName, chainId); + + if (StringUtils.isAnyBlank(contractAddress, rpcAddress)) { + log.error("Fetch blank values of contractAddress:[{}] or rpcAddress:[{}] filtered by contractName:[{}] and chainId:[{}]", + contractAddress, rpcAddress, contractName.getContractName(), chainId); + return BaseResponse.failWithReason("1204", "Fetch rank failed, please try again later."); + } + + Web3j web3j = Web3j.build(new HttpService(rpcAddress)); + + ClientTransactionManager transactionManager = new ClientTransactionManager(web3j, ZERO_ADDRESS); + WarCraftContract contract = WarCraftContract.load(contractAddress, web3j, transactionManager, ZERO_GAS_PROVIDER); + + try { + BigInteger tokenId = contract.claimedTokenIdBy(address).sendAsync().get(TIMEOUT, TimeUnit.SECONDS); + if (tokenId == null || tokenId.intValue() == 0){ + log.error("No claim(tokenId) info found for address:[{}].", address); + return BaseResponse.failWithReason("1206", "No claim info found."); + } + + String rank = contract.tokenURI(tokenId).sendAsync().get(TIMEOUT, TimeUnit.SECONDS); + if (StringUtils.isBlank(rank)){ + log.error("No rank info found for address:[{}] and tokenId:[{}].", address, tokenId.intValue()); + return BaseResponse.failWithReason("1206", "No rank info found."); + } + return BaseResponse.successWithData(rank); + } catch (Exception e) { + log.error("Call contract method:[claimedTokenIdBy] remote error.", e); + return BaseResponse.failWithReason("1205", "Fetch rank failed, please try again later."); + } + + } + +} \ No newline at end of file