diff --git a/src/main/java/smart_contract_wrapper/SoulBoundTest.java b/src/main/java/smart_contract_wrapper/SoulBoundTest.java new file mode 100644 index 00000000..91a14de5 --- /dev/null +++ b/src/main/java/smart_contract_wrapper/SoulBoundTest.java @@ -0,0 +1,459 @@ +package smart_contract_wrapper; + +import io.reactivex.Flowable; +import io.reactivex.functions.Function; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import org.web3j.abi.EventEncoder; +import org.web3j.abi.TypeReference; +import org.web3j.abi.datatypes.*; +import org.web3j.abi.datatypes.generated.Bytes4; +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; + +/** + *

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 4.5.4. + */ +@SuppressWarnings("rawtypes") +public class SoulBoundTest extends Contract { + private static final String BINARY = "608060405234801562000010575f80fd5b506040518060400160405280600d81526020016c14dbdd5b109bdd5b9915195cdd609a1b8152506040518060400160405280600381526020016214d09560ea1b815250815f90816200006391906200018a565b5060016200007282826200018a565b5050506200008f620000896200009560201b60201c565b62000099565b62000252565b3390565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200011357607f821691505b6020821081036200013257634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000185575f81815260208120601f850160051c81016020861015620001605750805b601f850160051c820191505b8181101562000181578281556001016200016c565b5050505b505050565b81516001600160401b03811115620001a657620001a6620000ea565b620001be81620001b78454620000fe565b8462000138565b602080601f831160018114620001f4575f8415620001dc5750858301515b5f19600386901b1c1916600185901b17855562000181565b5f85815260208120601f198616915b82811015620002245788860151825594840194600190910190840162000203565b50858210156200024257878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b6117ad80620002605f395ff3fe608060405234801561000f575f80fd5b5060043610610106575f3560e01c8063715018a61161009e578063b88d4fde1161006e578063b88d4fde14610215578063c87b56dd14610228578063d204c45e1461023b578063e985e9c51461024e578063f2fde38b14610261575f80fd5b8063715018a6146101e15780638da5cb5b146101e957806395d89b41146101fa578063a22cb46514610202575f80fd5b806323b872dd116100d957806323b872dd1461018757806342842e0e1461019a5780636352211e146101ad57806370a08231146101c0575f80fd5b806301ffc9a71461010a57806306fdde0314610132578063081812fc14610147578063095ea7b314610172575b5f80fd5b61011d610118366004611185565b610274565b60405190151581526020015b60405180910390f35b61013a6102c5565b60405161012991906111ed565b61015a6101553660046111ff565b610354565b6040516001600160a01b039091168152602001610129565b610185610180366004611231565b610379565b005b610185610195366004611259565b610492565b6101856101a8366004611259565b6104c3565b61015a6101bb3660046111ff565b6104dd565b6101d36101ce366004611292565b61053c565b604051908152602001610129565b6101856105c0565b6007546001600160a01b031661015a565b61013a6105d3565b6101856102103660046112ab565b6105e2565b61018561022336600461136b565b6105f1565b61013a6102363660046111ff565b610629565b6101856102493660046113e2565b610634565b61011d61025c366004611440565b61066a565b61018561026f366004611292565b610697565b5f6001600160e01b031982166380ac58cd60e01b14806102a457506001600160e01b03198216635b5e139f60e01b145b806102bf57506301ffc9a760e01b6001600160e01b03198316145b92915050565b60605f80546102d390611471565b80601f01602080910402602001604051908101604052809291908181526020018280546102ff90611471565b801561034a5780601f106103215761010080835404028352916020019161034a565b820191905f5260205f20905b81548152906001019060200180831161032d57829003601f168201915b5050505050905090565b5f61035e82610710565b505f908152600460205260409020546001600160a01b031690565b5f610383826104dd565b9050806001600160a01b0316836001600160a01b0316036103f55760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b03821614806104115750610411813361066a565b6104835760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c000060648201526084016103ec565b61048d838361076e565b505050565b61049c33826107db565b6104b85760405162461bcd60e51b81526004016103ec906114a9565b61048d838383610839565b61048d83838360405180602001604052805f8152506105f1565b5f818152600260205260408120546001600160a01b0316806102bf5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016103ec565b5f6001600160a01b0382166105a55760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b60648201526084016103ec565b506001600160a01b03165f9081526003602052604090205490565b6105c86109dc565b6105d15f610a36565b565b6060600180546102d390611471565b6105ed338383610a87565b5050565b6105fb33836107db565b6106175760405162461bcd60e51b81526004016103ec906114a9565b61062384848484610b54565b50505050565b60606102bf82610b87565b61063c6109dc565b5f61064660085490565b9050610656600880546001019055565b6106608382610c89565b61048d8183610ca2565b6001600160a01b039182165f90815260056020908152604080832093909416825291909152205460ff1690565b61069f6109dc565b6001600160a01b0381166107045760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016103ec565b61070d81610a36565b50565b5f818152600260205260409020546001600160a01b031661070d5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b60448201526064016103ec565b5f81815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906107a2826104dd565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b5f806107e6836104dd565b9050806001600160a01b0316846001600160a01b0316148061080d575061080d818561066a565b806108315750836001600160a01b031661082684610354565b6001600160a01b0316145b949350505050565b826001600160a01b031661084c826104dd565b6001600160a01b0316146108b05760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b60648201526084016103ec565b6001600160a01b0382166109125760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b60648201526084016103ec565b61091d838383610d33565b6109275f8261076e565b6001600160a01b0383165f90815260036020526040812080546001929061094f90849061150b565b90915550506001600160a01b0382165f90815260036020526040812080546001929061097c90849061151e565b90915550505f8181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6007546001600160a01b031633146105d15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103ec565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b816001600160a01b0316836001600160a01b031603610ae85760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016103ec565b6001600160a01b038381165f81815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b610b5f848484610839565b610b6b84848484610d8a565b6106235760405162461bcd60e51b81526004016103ec90611531565b6060610b9282610710565b5f8281526006602052604081208054610baa90611471565b80601f0160208091040260200160405190810160405280929190818152602001828054610bd690611471565b8015610c215780601f10610bf857610100808354040283529160200191610c21565b820191905f5260205f20905b815481529060010190602001808311610c0457829003601f168201915b505050505090505f610c3d60408051602081019091525f815290565b905080515f03610c4e575092915050565b815115610c80578082604051602001610c68929190611583565b60405160208183030381529060405292505050919050565b61083184610e87565b6105ed828260405180602001604052805f815250610ef7565b5f828152600260205260409020546001600160a01b0316610d1c5760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201526d32bc34b9ba32b73a103a37b5b2b760911b60648201526084016103ec565b5f82815260066020526040902061048d82826115fe565b6001600160a01b0383161561048d5760405162461bcd60e51b815260206004820152601e60248201527f4572723a20746f6b656e207472616e7366657220697320424c4f434b4544000060448201526064016103ec565b5f6001600160a01b0384163b15610e7c57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290610dcd9033908990889088906004016116ba565b6020604051808303815f875af1925050508015610e07575060408051601f3d908101601f19168201909252610e04918101906116f6565b60015b610e62573d808015610e34576040519150601f19603f3d011682016040523d82523d5f602084013e610e39565b606091505b5080515f03610e5a5760405162461bcd60e51b81526004016103ec90611531565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610831565b506001949350505050565b6060610e9282610710565b5f610ea760408051602081019091525f815290565b90505f815111610ec55760405180602001604052805f815250610ef0565b80610ecf84610f29565b604051602001610ee0929190611583565b6040516020818303038152906040525b9392505050565b610f018383611026565b610f0d5f848484610d8a565b61048d5760405162461bcd60e51b81526004016103ec90611531565b6060815f03610f4f5750506040805180820190915260018152600360fc1b602082015290565b815f5b8115610f785780610f6281611711565b9150610f719050600a8361173d565b9150610f52565b5f8167ffffffffffffffff811115610f9257610f926112e4565b6040519080825280601f01601f191660200182016040528015610fbc576020820181803683370190505b5090505b841561083157610fd160018361150b565b9150610fde600a86611750565b610fe990603061151e565b60f81b818381518110610ffe57610ffe611763565b60200101906001600160f81b03191690815f1a90535061101f600a8661173d565b9450610fc0565b6001600160a01b03821661107c5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016103ec565b5f818152600260205260409020546001600160a01b0316156110e05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016103ec565b6110eb5f8383610d33565b6001600160a01b0382165f90815260036020526040812080546001929061111390849061151e565b90915550505f8181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001600160e01b03198116811461070d575f80fd5b5f60208284031215611195575f80fd5b8135610ef081611170565b5f5b838110156111ba5781810151838201526020016111a2565b50505f910152565b5f81518084526111d98160208601602086016111a0565b601f01601f19169290920160200192915050565b602081525f610ef060208301846111c2565b5f6020828403121561120f575f80fd5b5035919050565b80356001600160a01b038116811461122c575f80fd5b919050565b5f8060408385031215611242575f80fd5b61124b83611216565b946020939093013593505050565b5f805f6060848603121561126b575f80fd5b61127484611216565b925061128260208501611216565b9150604084013590509250925092565b5f602082840312156112a2575f80fd5b610ef082611216565b5f80604083850312156112bc575f80fd5b6112c583611216565b9150602083013580151581146112d9575f80fd5b809150509250929050565b634e487b7160e01b5f52604160045260245ffd5b5f67ffffffffffffffff80841115611312576113126112e4565b604051601f8501601f19908116603f0116810190828211818310171561133a5761133a6112e4565b81604052809350858152868686011115611352575f80fd5b858560208301375f602087830101525050509392505050565b5f805f806080858703121561137e575f80fd5b61138785611216565b935061139560208601611216565b925060408501359150606085013567ffffffffffffffff8111156113b7575f80fd5b8501601f810187136113c7575f80fd5b6113d6878235602084016112f8565b91505092959194509250565b5f80604083850312156113f3575f80fd5b6113fc83611216565b9150602083013567ffffffffffffffff811115611417575f80fd5b8301601f81018513611427575f80fd5b611436858235602084016112f8565b9150509250929050565b5f8060408385031215611451575f80fd5b61145a83611216565b915061146860208401611216565b90509250929050565b600181811c9082168061148557607f821691505b6020821081036114a357634e487b7160e01b5f52602260045260245ffd5b50919050565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b818103818111156102bf576102bf6114f7565b808201808211156102bf576102bf6114f7565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b5f83516115948184602088016111a0565b8351908301906115a88183602088016111a0565b01949350505050565b601f82111561048d575f81815260208120601f850160051c810160208610156115d75750805b601f850160051c820191505b818110156115f6578281556001016115e3565b505050505050565b815167ffffffffffffffff811115611618576116186112e4565b61162c816116268454611471565b846115b1565b602080601f83116001811461165f575f84156116485750858301515b5f19600386901b1c1916600185901b1785556115f6565b5f85815260208120601f198616915b8281101561168d5788860151825594840194600190910190840161166e565b50858210156116aa57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f906116ec908301846111c2565b9695505050505050565b5f60208284031215611706575f80fd5b8151610ef081611170565b5f60018201611722576117226114f7565b5060010190565b634e487b7160e01b5f52601260045260245ffd5b5f8261174b5761174b611729565b500490565b5f8261175e5761175e611729565b500690565b634e487b7160e01b5f52603260045260245ffdfea26469706673582212201a313239ed249fe011c5a670aad70e54a79928f56a2970dbe03081a0d8b2b2ab64736f6c63430008150033"; + + public static final String FUNC_APPROVE = "approve"; + + public static final String FUNC_BALANCEOF = "balanceOf"; + + public static final String FUNC_GETAPPROVED = "getApproved"; + + 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_RENOUNCEOWNERSHIP = "renounceOwnership"; + + public static final String FUNC_SAFEMINT = "safeMint"; + + public static final String FUNC_SAFETRANSFERFROM = "safeTransferFrom"; + + public static final String FUNC_SETAPPROVALFORALL = "setApprovalForAll"; + + 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_TRANSFERFROM = "transferFrom"; + + public static final String FUNC_TRANSFEROWNERSHIP = "transferOwnership"; + + 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 OWNERSHIPTRANSFERRED_EVENT = new Event("OwnershipTransferred", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {})); + ; + + public static final Event TRANSFER_EVENT = new Event("Transfer", + Arrays.>asList(new TypeReference
(true) {}, new TypeReference
(true) {}, new TypeReference(true) {})); + ; + + @Deprecated + protected SoulBoundTest(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + protected SoulBoundTest(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, credentials, contractGasProvider); + } + + @Deprecated + protected SoulBoundTest(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + protected SoulBoundTest(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider); + } + + public List getApprovalEvents(TransactionReceipt transactionReceipt) { + List valueList = extractEventParametersWithLog(APPROVAL_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.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) { + Contract.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 List getApprovalForAllEvents(TransactionReceipt transactionReceipt) { + List valueList = extractEventParametersWithLog(APPROVALFORALL_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.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) { + Contract.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 List getOwnershipTransferredEvents(TransactionReceipt transactionReceipt) { + List valueList = extractEventParametersWithLog(OWNERSHIPTRANSFERRED_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.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) { + Contract.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 List getTransferEvents(TransactionReceipt transactionReceipt) { + List valueList = extractEventParametersWithLog(TRANSFER_EVENT, transactionReceipt); + ArrayList responses = new ArrayList(valueList.size()); + for (Contract.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) { + Contract.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 RemoteFunctionCall approve(String to, BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_APPROVE, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.generated.Uint256(tokenId)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall balanceOf(Address owner) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_BALANCEOF, + Arrays.asList(owner), + Arrays.asList(new TypeReference() { + })); + return executeRemoteCallSingleValueReturn(function); + } + public RemoteFunctionCall getApproved(BigInteger tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_GETAPPROVED, + Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(tokenId)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + 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 org.web3j.abi.datatypes.Address(160, owner), + new org.web3j.abi.datatypes.Address(160, operator)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + 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); + } + + public RemoteFunctionCall owner() { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_OWNER, + Arrays.asList(), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall
ownerOf(Uint256 tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_OWNEROF, + Arrays.asList(tokenId), + Arrays.asList(new TypeReference
() { + })); + return executeRemoteCallSingleValueReturn(function); + } + + 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 safeMint(String to, String uri) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function( + FUNC_SAFEMINT, + Arrays.asList(new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.Utf8String(uri)), + 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 org.web3j.abi.datatypes.Address(160, from), + new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.generated.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 org.web3j.abi.datatypes.Address(160, from), + new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.generated.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 org.web3j.abi.datatypes.Address(160, operator), + new org.web3j.abi.datatypes.Bool(approved)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + public RemoteFunctionCall supportsInterface(Bytes4 interfaceId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_SUPPORTSINTERFACE, + Arrays.asList(interfaceId), + Arrays.asList(new TypeReference() { + })); + return executeRemoteCallSingleValueReturn(function); + } + + 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); + } + + + + public RemoteFunctionCall tokenURI(Uint256 tokenId) { + final org.web3j.abi.datatypes.Function function = new org.web3j.abi.datatypes.Function(FUNC_TOKENURI, + Arrays.asList(tokenId), + Arrays.asList(new TypeReference() { + })); + return executeRemoteCallSingleValueReturn(function); + } + + 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 org.web3j.abi.datatypes.Address(160, from), + new org.web3j.abi.datatypes.Address(160, to), + new org.web3j.abi.datatypes.generated.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 org.web3j.abi.datatypes.Address(160, newOwner)), + Collections.>emptyList()); + return executeRemoteCallTransaction(function); + } + + @Deprecated + public static SoulBoundTest load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return new SoulBoundTest(contractAddress, web3j, credentials, gasPrice, gasLimit); + } + + @Deprecated + public static SoulBoundTest load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + return new SoulBoundTest(contractAddress, web3j, transactionManager, gasPrice, gasLimit); + } + + public static SoulBoundTest load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return new SoulBoundTest(contractAddress, web3j, credentials, contractGasProvider); + } + + public static SoulBoundTest load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return new SoulBoundTest(contractAddress, web3j, transactionManager, contractGasProvider); + } + + public static RemoteCall deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) { + return deployRemoteCall(SoulBoundTest.class, web3j, credentials, contractGasProvider, BINARY, ""); + } + + public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) { + return deployRemoteCall(SoulBoundTest.class, web3j, transactionManager, contractGasProvider, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(SoulBoundTest.class, web3j, credentials, gasPrice, gasLimit, BINARY, ""); + } + + @Deprecated + public static RemoteCall deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) { + return deployRemoteCall(SoulBoundTest.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, ""); + } + + 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 OwnershipTransferredEventResponse extends BaseEventResponse { + public String previousOwner; + + public String newOwner; + } + + public static class TransferEventResponse extends BaseEventResponse { + public String from; + + public String to; + + public BigInteger tokenId; + } +} diff --git a/src/main/kotlin/id/walt/nftkit/Values.kt b/src/main/kotlin/id/walt/nftkit/Values.kt index 9253eacb..19c81ffe 100644 --- a/src/main/kotlin/id/walt/nftkit/Values.kt +++ b/src/main/kotlin/id/walt/nftkit/Values.kt @@ -11,6 +11,7 @@ object Values { const val POLYGON_TESTNET_MUMBAI_CHAIN_ID: Long = 80001 const val MOONBEAM_MAINNET_CHAIN_ID: Long = 1284 const val ASTAR_MAINNET_CHAIN_ID: Long = 592 + const val SHIMMEREVM_TESTNET_CHAIN_ID: Long = 1072 const val ETHEREUM_MAINNET_SCAN_API_URL= "api.etherscan.io" const val ETHEREUM_TESTNET_GOERLI_SCAN_API_URL = "api-goerli.etherscan.io" @@ -23,6 +24,7 @@ object Values { const val ETHEREUM_TESTNET_SEPOLIA_BLOCK_EXPLORER_URL = "https://sepolia.etherscan.io/" const val POLYGON_MAINNET_BLOCK_EXPLORER_URL = "https://polygonscan.com" const val POLYGON_TESTNET_MUMBAI_BLOCK_EXPLORER_URL = "https://mumbai.polygonscan.com" + const val SHIMMEREVM_TESTNET_BLOCK_EXPLORER_URL = "https://explorer.evm.testnet.shimmer.network" const val ETHEREUM_MAINNET_ALCHEMY_URL = "https://eth-mainnet.alchemyapi.io/v2/" const val ETHEREUM_TESTNET_GOERLI_ALCHEMY_URL = "https://eth-goerli.g.alchemy.com/v2/" diff --git a/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/Erc721TokenStandard.kt b/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/Erc721TokenStandard.kt index 12c0d942..4577e68b 100644 --- a/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/Erc721TokenStandard.kt +++ b/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/Erc721TokenStandard.kt @@ -293,6 +293,7 @@ object Erc721TokenStandard : IErc721TokenStandard { EVMChain.MUMBAI -> Values.POLYGON_TESTNET_MUMBAI_CHAIN_ID EVMChain.ASTAR -> Values.ASTAR_MAINNET_CHAIN_ID EVMChain.MOONBEAM -> Values.MOONBEAM_MAINNET_CHAIN_ID + EVMChain.SHIMMEREVM -> Values.SHIMMEREVM_TESTNET_CHAIN_ID } val transactionManager: TransactionManager = RawTransactionManager( web3j, credentials, chainId @@ -317,4 +318,4 @@ object Erc721TokenStandard : IErc721TokenStandard { } -} +} \ No newline at end of file diff --git a/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/ISoulBoundTokenStandard.kt b/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/ISoulBoundTokenStandard.kt new file mode 100644 index 00000000..96522cfc --- /dev/null +++ b/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/ISoulBoundTokenStandard.kt @@ -0,0 +1,29 @@ +package id.walt.nftkit.chains.evm.erc721 +import id.walt.nftkit.services.Chain +import id.walt.nftkit.services.EVMChain +import org.web3j.abi.datatypes.Address +import org.web3j.abi.datatypes.Bool +import org.web3j.abi.datatypes.DynamicBytes +import org.web3j.abi.datatypes.Utf8String +import org.web3j.abi.datatypes.generated.Uint256 +import org.web3j.protocol.core.RemoteFunctionCall +import org.web3j.protocol.core.methods.response.TransactionReceipt +import java.math.BigInteger +interface ISoulBoundTokenStandard { + + fun safeMint(chain: EVMChain, contractAddress: String,to: String, uri: String): TransactionReceipt? + fun ownerOf(chain: EVMChain, contractAddress: String, tokenId: Uint256):String? + + fun name(chain: EVMChain, contractAddress: String): String? + + fun symbol(chain: EVMChain, contractAddress: String): String? + + fun tokenURI(chain: EVMChain, contractAddress: String, tokenId: Uint256): String? + + fun balanceOf(chain: EVMChain, contractAddress: String, owner: Address): BigInteger? + + fun safeTransferFrom(chain: EVMChain, contractAddress: String, from: Address, to: Address, tokenId: Uint256, signedAccount: String?): TransactionReceipt + + fun supportsInterface(chain: EVMChain, contractAddress: String): Boolean + +} \ No newline at end of file diff --git a/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/SoulBoundTokenStandard.kt b/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/SoulBoundTokenStandard.kt new file mode 100644 index 00000000..140e26d7 --- /dev/null +++ b/src/main/kotlin/id/walt/nftkit/chains/evm/erc721/SoulBoundTokenStandard.kt @@ -0,0 +1,133 @@ +package id.walt.nftkit.chains.evm.erc721 + +import id.walt.nftkit.Values +import id.walt.nftkit.WaltIdGasProvider +import id.walt.nftkit.services.* +import id.walt.nftkit.utilis.providers.ProviderFactory +import org.web3j.abi.datatypes.Address +import org.web3j.abi.datatypes.generated.Bytes4 +import org.web3j.abi.datatypes.generated.Uint256 +import org.web3j.crypto.Credentials +import org.web3j.protocol.core.RemoteCall +import org.web3j.protocol.core.methods.response.TransactionReceipt +import org.web3j.tx.RawTransactionManager +import org.web3j.tx.TransactionManager +import org.web3j.tx.gas.ContractGasProvider +import org.web3j.utils.Numeric +import smart_contract_wrapper.SoulBoundTest +import java.math.BigInteger + +object SoulBoundTokenStandard : ISoulBoundTokenStandard { + + + + + + + private fun loadContract(chain: EVMChain, address: String, signedAccount: String? ="") : SoulBoundTest { + val web3j = ProviderFactory.getProvider(chain)?.getWeb3j() + + val privateKey: String = if(signedAccount == null || "" == (signedAccount)){ + WaltIdServices.loadChainConfig().privateKey + }else{ + val lowercaseAddress= WaltIdServices.loadAccountKeysConfig().keys.mapKeys { it.key.lowercase() } + lowercaseAddress[signedAccount.lowercase()]!! + } + + val credentials: Credentials = Credentials.create(privateKey) + + val gasProvider: ContractGasProvider = WaltIdGasProvider + val chainId= when(chain){ + EVMChain.ETHEREUM -> Values.ETHEREUM_MAINNET_CHAIN_ID + EVMChain.GOERLI -> Values.ETHEREUM_TESTNET_GOERLI_CHAIN_ID + EVMChain.SEPOLIA -> Values.ETHEREUM_TESTNET_SEPOLIA_CHAIN_ID + EVMChain.POLYGON -> Values.POLYGON_MAINNET_CHAIN_ID + EVMChain.MUMBAI -> Values.POLYGON_TESTNET_MUMBAI_CHAIN_ID + EVMChain.ASTAR -> Values.ASTAR_MAINNET_CHAIN_ID + EVMChain.MOONBEAM -> Values.MOONBEAM_MAINNET_CHAIN_ID + EVMChain.SHIMMEREVM -> Values.SHIMMEREVM_TESTNET_CHAIN_ID + } + val transactionManager: TransactionManager = RawTransactionManager( + web3j, credentials, chainId + ) + return SoulBoundTest.load(address, web3j,transactionManager,gasProvider) + + } + + + override fun ownerOf(chain: EVMChain, contractAddress: String, tokenId: Uint256): String? { + return loadContract(chain, contractAddress).ownerOf(tokenId).send().value + } + + override fun name(chain: EVMChain, contractAddress: String): String? { + val contract = loadContract(chain, contractAddress) + return contract.name().send().value + } + + override fun symbol(chain: EVMChain, contractAddress: String): String? { + return loadContract(chain, contractAddress).symbol().send().value + } + + override fun tokenURI(chain: EVMChain, contractAddress: String, tokenId: Uint256): String? { + return loadContract(chain, contractAddress).tokenURI(tokenId).send().value + } + + override fun balanceOf(chain: EVMChain, contractAddress: String, owner: Address): BigInteger? { + return loadContract(chain, contractAddress).balanceOf(owner).send().value + } + + override fun safeTransferFrom( + chain: EVMChain, + contractAddress: String, + from: Address, + to: Address, + tokenId: Uint256, + signedAccount: String? + ): TransactionReceipt { + TODO("Not yet implemented") + } + + override fun safeMint(chain: EVMChain, contractAddress: String, to: String, uri: String): TransactionReceipt? { + return loadContract(chain, contractAddress).safeMint(to, uri).send() + } + + + fun deployContract(chain: EVMChain) : DeploymentResponse { + val chainId= when(chain){ + EVMChain.ETHEREUM -> Values.ETHEREUM_MAINNET_CHAIN_ID + EVMChain.GOERLI -> Values.ETHEREUM_TESTNET_GOERLI_CHAIN_ID + EVMChain.SEPOLIA -> Values.ETHEREUM_TESTNET_SEPOLIA_CHAIN_ID + EVMChain.POLYGON -> Values.POLYGON_MAINNET_CHAIN_ID + EVMChain.MUMBAI -> Values.POLYGON_TESTNET_MUMBAI_CHAIN_ID + EVMChain.ASTAR -> Values.ASTAR_MAINNET_CHAIN_ID + EVMChain.MOONBEAM -> Values.MOONBEAM_MAINNET_CHAIN_ID + EVMChain.SHIMMEREVM -> Values.SHIMMEREVM_TESTNET_CHAIN_ID + } + + val web3j = ProviderFactory.getProvider(chain)?.getWeb3j() + val credentials: Credentials = Credentials.create(WaltIdServices.loadChainConfig().privateKey) + val gasProvider: ContractGasProvider = WaltIdGasProvider + val remotCall: RemoteCall + val transactionManager: TransactionManager = RawTransactionManager( + web3j, credentials, chainId + ) + remotCall = SoulBoundTest.deploy(web3j, transactionManager, gasProvider) + + val contract = remotCall.send() + + val url = WaltIdServices.getBlockExplorerUrl(chain) + val ts = TransactionResponse( + contract.transactionReceipt.get().transactionHash, + "$url/tx/${contract.transactionReceipt.get().transactionHash}" + ) + return DeploymentResponse(ts, contract.contractAddress, "$url/address/${contract.contractAddress}") + } + + + override fun supportsInterface(chain: EVMChain, contractAddress: String) : Boolean { + val erc721URIStorageWrapper = loadContract(chain, contractAddress) + val data = Numeric.hexStringToByteArray("0x5b5e139f") // ERC721 interface id + val interfaceId = Bytes4(data) + return erc721URIStorageWrapper.supportsInterface(interfaceId).send().value + } +} \ No newline at end of file diff --git a/src/main/kotlin/id/walt/nftkit/rest/NftController.kt b/src/main/kotlin/id/walt/nftkit/rest/NftController.kt index 243edd32..53dc5cdd 100644 --- a/src/main/kotlin/id/walt/nftkit/rest/NftController.kt +++ b/src/main/kotlin/id/walt/nftkit/rest/NftController.kt @@ -81,6 +81,11 @@ object NftController { }.json("200") { it.description("Transaction ID and smart contract address") } + + + + + fun mint(ctx: Context) { val mintReq = ctx.bodyAsClass(MintRequest::class.java) val chain = ctx.pathParam("chain") diff --git a/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt b/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt index 39ae8135..1add9adf 100644 --- a/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt +++ b/src/main/kotlin/id/walt/nftkit/rest/NftKitApi.kt @@ -129,6 +129,7 @@ object NftKitApi { "chain/{chain}/contract/deploy", documented(NftController.deployDocs(), NftController::deploy) ) + post( "chain/{chain}/contract/{contractAddress}/token/mint", documented(NftController.mintDocs(), NftController::mint) diff --git a/src/main/kotlin/id/walt/nftkit/services/NftService.kt b/src/main/kotlin/id/walt/nftkit/services/NftService.kt index b89c3194..efc1522e 100644 --- a/src/main/kotlin/id/walt/nftkit/services/NftService.kt +++ b/src/main/kotlin/id/walt/nftkit/services/NftService.kt @@ -2,6 +2,7 @@ package id.walt.nftkit.services import id.walt.nftkit.Values import id.walt.nftkit.chains.evm.erc721.Erc721TokenStandard +import id.walt.nftkit.chains.evm.erc721.SoulBoundTokenStandard import id.walt.nftkit.metadata.IPFSMetadata import id.walt.nftkit.metadata.MetadataUri import id.walt.nftkit.metadata.MetadataUriFactory @@ -95,7 +96,8 @@ enum class EVMChain { SEPOLIA, MUMBAI, ASTAR, - MOONBEAM + MOONBEAM, + SHIMMEREVM, } enum class TokenStandard { @@ -281,9 +283,14 @@ object NftService { } fun deploySmartContractToken(chain: EVMChain, parameter: DeploymentParameter, options: DeploymentOptions): DeploymentResponse { - return Erc721TokenStandard.deployContract(chain, parameter, options) + return if (parameter.options.transferable){ + Erc721TokenStandard.deployContract(chain, parameter, options) + }else{ + SoulBoundTokenStandard.deployContract(chain) + } } + fun mintToken( chain: EVMChain, contractAddress: String, @@ -302,6 +309,7 @@ object NftService { return mintNewToken(parameter.recipientAddress, tokenUri, chain, contractAddress) } + fun getNftMetadata(chain: EVMChain, contractAddress: String, tokenId: BigInteger): NftMetadata { var uri = getMetadatUri(chain, contractAddress, tokenId) if(Common.getMetadataType(uri).equals(MetadataStorageType.ON_CHAIN)){ @@ -336,6 +344,10 @@ object NftService { return String() } + fun ownerOfSoulbound( chain: EVMChain , contractAddress: String , tokenId: Uint256) : String{ + return SoulBoundTokenStandard.ownerOf(chain, contractAddress, tokenId).toString() + } + fun transferFrom(chain: EVMChain, contractAddress: String, from: String, to: String, tokenId: BigInteger, signedAccount: String?): TransactionResponse { val transactionReceipt = Erc721TokenStandard.transferFrom(chain, contractAddress, Address(from), Address(to), Uint256(tokenId), signedAccount) return Common.getTransactionResponse(chain, transactionReceipt) @@ -573,7 +585,7 @@ object NftService { chain: EVMChain, contractAddress: String ): MintingResponse { - if (isErc721Standard(chain, contractAddress) == true) { + if (isErc721Standard(chain, contractAddress) && !isSoulBoundStandard(chain , contractAddress)) { //val erc721TokenStandard = Erc721TokenStandard() val recipient = Address(recipientAddress) val tokenUri = Utf8String(metadataUri) @@ -587,12 +599,25 @@ object NftService { TransactionResponse(transactionReceipt!!.transactionHash, "$url/tx/${transactionReceipt.transactionHash}") val mr = MintingResponse(ts, eventValues?.indexedValues?.get(2)?.value as BigInteger) return mr - } else { + } else if (isSoulBoundStandard(chain , contractAddress) && isErc721Standard(chain, contractAddress)){ + val recipient = recipientAddress + val tokenUri = metadataUri + val transactionReceipt: TransactionReceipt? = + SoulBoundTokenStandard.safeMint(chain, contractAddress, recipient, tokenUri) + val eventValues: EventValues? = + staticExtractEventParameters(Erc721OnchainCredentialWrapper.TRANSFER_EVENT, transactionReceipt?.logs?.get(0)) + val url = WaltIdServices.getBlockExplorerUrl(chain) + val ts = + TransactionResponse(transactionReceipt!!.transactionHash, "$url/tx/${transactionReceipt.transactionHash}") + val mr = MintingResponse(ts, eventValues?.indexedValues?.get(2)?.value as BigInteger) + return mr } return MintingResponse(null, null) } + + private fun getMetadatUri(chain: EVMChain, contractAddress: String, tokenId: BigInteger): String { if (isErc721Standard(chain, contractAddress) == true) { return Erc721TokenStandard.tokenURI(chain, contractAddress, Uint256(tokenId)) @@ -604,6 +629,9 @@ object NftService { private fun isErc721Standard(chain: EVMChain, contractAddress: String): Boolean { return Erc721TokenStandard.supportsInterface(chain, contractAddress) } + private fun isSoulBoundStandard(chain: EVMChain, contractAddress: String): Boolean { + return SoulBoundTokenStandard.supportsInterface(chain, contractAddress) + } private fun parseNftEvmMetadataResult(nft: JsonObject): NftMetadata{ var attributes: List?=null diff --git a/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt b/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt index 29619aa2..09f2b361 100644 --- a/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt +++ b/src/main/kotlin/id/walt/nftkit/services/WaltIdServices.kt @@ -8,7 +8,7 @@ import java.io.File import java.util.* -data class Providers(val ethereum: String, val goerli: String, val sepolia: String, val polygon: String, val mumbai: String, val astar: String, val moonbeam: String, val opal: String, val unique: String) +data class Providers(val ethereum: String, val goerli: String, val sepolia: String, val polygon: String, val mumbai: String, val astar: String, val moonbeam: String, val opal: String, val unique: String , val shimmerevm: String) data class ChainConfig(val providers: Providers, val privateKey: String) @@ -104,6 +104,7 @@ object WaltIdServices { EVMChain.SEPOLIA -> Values.ETHEREUM_TESTNET_SEPOLIA_BLOCK_EXPLORER_URL EVMChain.POLYGON -> Values.POLYGON_MAINNET_BLOCK_EXPLORER_URL EVMChain.MUMBAI -> Values.POLYGON_TESTNET_MUMBAI_BLOCK_EXPLORER_URL + EVMChain.SHIMMEREVM -> Values.SHIMMEREVM_TESTNET_BLOCK_EXPLORER_URL else -> {throw Exception("${chain.toString()} is not supported")} } } diff --git a/src/main/kotlin/id/walt/nftkit/utilis/providers/IotaWeb3.kt b/src/main/kotlin/id/walt/nftkit/utilis/providers/IotaWeb3.kt new file mode 100644 index 00000000..a81e1786 --- /dev/null +++ b/src/main/kotlin/id/walt/nftkit/utilis/providers/IotaWeb3.kt @@ -0,0 +1,11 @@ +package id.walt.nftkit.utilis.providers + +import id.walt.nftkit.services.WaltIdServices +import org.web3j.protocol.Web3j +import org.web3j.protocol.http.HttpService + +class IotaWeb3 : Web3jInstance { + override fun getWeb3j(): Web3j { + return Web3j.build(HttpService(WaltIdServices.loadChainConfig().providers.shimmerevm)) + } +} diff --git a/src/main/kotlin/id/walt/nftkit/utilis/providers/ProviderFactory.kt b/src/main/kotlin/id/walt/nftkit/utilis/providers/ProviderFactory.kt index 04b9d09f..58f69c8f 100644 --- a/src/main/kotlin/id/walt/nftkit/utilis/providers/ProviderFactory.kt +++ b/src/main/kotlin/id/walt/nftkit/utilis/providers/ProviderFactory.kt @@ -1,6 +1,5 @@ package id.walt.nftkit.utilis.providers -import id.walt.nftkit.services.Chain import id.walt.nftkit.services.EVMChain object ProviderFactory { @@ -13,6 +12,7 @@ object ProviderFactory { EVMChain.MUMBAI -> MumbaiWeb3() EVMChain.ASTAR -> AstarWeb3() EVMChain.MOONBEAM -> MoonbeamWeb3() + EVMChain.SHIMMEREVM -> IotaWeb3() } } diff --git a/src/main/resources/walt-default.yaml b/src/main/resources/walt-default.yaml index 5f1644b1..495315c1 100644 --- a/src/main/resources/walt-default.yaml +++ b/src/main/resources/walt-default.yaml @@ -21,10 +21,11 @@ providers: moonbeam: "https://rpc.api.moonbeam.network" unique: "https://rpc.unique.network" opal: "https://rpc-opal.unique.network" + shimmerevm: https://json-rpc.evm.testnet.shimmer.network -privateKey: "bd4cb3e507f342ee3a710370cef39dda48f17b0a158b0b8dd3f000fbd5b2c2d9" - +#privateKey: "bd4cb3e507f342ee3a710370cef39dda48f17b0a158b0b8dd3f000fbd5b2c2d9" +privateKey: "fe96ea369abac7818a890da598d40e3e4709f1150e3ff35910f77f63484cffba" #privateKey: "a1fcab9b58015f452c9a89d4cde4807a80111ab27142730bfb96be936e576be1" keys: diff --git a/src/main/solidity/soulbound.sol b/src/main/solidity/soulbound.sol new file mode 100644 index 00000000..b3d42e5c --- /dev/null +++ b/src/main/solidity/soulbound.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; + +contract SoulBoundTest is ERC721, ERC721URIStorage, Ownable { + using Counters for Counters.Counter; + + Counters.Counter private _tokenIdCounter; + + constructor() ERC721("SoulBoundTest", "SBT") {} + + function safeMint(address to, string memory uri) public onlyOwner { + uint256 tokenId = _tokenIdCounter.current(); + _tokenIdCounter.increment(); + _safeMint(to, tokenId); + _setTokenURI(tokenId, uri); + } + + function _beforeTokenTransfer( + address from, + address to, + uint256 tokenId + ) internal override virtual { + require(from == address(0), "Err: token transfer is BLOCKED"); + super._beforeTokenTransfer(from, to, tokenId); + } + + // The following functions are overrides required by Solidity. + + function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) { + super._burn(tokenId); + } + + function tokenURI(uint256 tokenId) + public + view + override(ERC721, ERC721URIStorage) + returns (string memory) + { + return super.tokenURI(tokenId); + } +} \ No newline at end of file