diff --git a/.gitignore b/.gitignore
index b3db3e2..c0d8a16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+application.yml
HELP.md
.gradle
build/
diff --git a/build.gradle b/build.gradle
index a58b4dc..6b0a4e1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -31,10 +31,16 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// swagger
+ implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0")
+
+ //web3j
+ implementation 'org.web3j:core:4.9.6'
+
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'
// s3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
+
}
tasks.named('test') {
diff --git a/src/main/java/zerobibim/flory/domain/contract/NFT.java b/src/main/java/zerobibim/flory/domain/contract/NFT.java
new file mode 100644
index 0000000..5705323
--- /dev/null
+++ b/src/main/java/zerobibim/flory/domain/contract/NFT.java
@@ -0,0 +1,428 @@
+package zerobibim.flory.domain.contract;
+
+import io.reactivex.Flowable;
+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.Address;
+import org.web3j.abi.datatypes.Bool;
+import org.web3j.abi.datatypes.Event;
+import org.web3j.abi.datatypes.Function;
+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.ens.EnsResolver;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.Web3jService;
+import org.web3j.protocol.core.DefaultBlockParameter;
+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 org.web3j.tx.gas.StaticGasProvider;
+
+/**
+ *
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.5.0.
+ */
+@SuppressWarnings("rawtypes")
+public class NFT extends Contract {
+ public static final String BINARY = "Bin file was not provided";
+
+ public static final String FUNC_CANNOT_TRANSFER_TO_ZERO_ADDRESS = "CANNOT_TRANSFER_TO_ZERO_ADDRESS";
+
+ public static final String FUNC_NOT_CURRENT_OWNER = "NOT_CURRENT_OWNER";
+
+ 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_MINT = "mint";
+
+ 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_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 NFT(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
+ super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
+ }
+
+ @Deprecated
+ protected NFT(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+ super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+ }
+
+
+
+ public static List getApprovalEvents(TransactionReceipt transactionReceipt) {
+ List valueList = staticExtractEventParametersWithLog(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 static ApprovalEventResponse getApprovalEventFromLog(Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(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(EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getApprovalEventFromLog(log));
+ }
+
+ 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 (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 static ApprovalForAllEventResponse getApprovalForAllEventFromLog(Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(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(EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getApprovalForAllEventFromLog(log));
+ }
+
+ 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 getOwnershipTransferredEvents(TransactionReceipt transactionReceipt) {
+ List valueList = staticExtractEventParametersWithLog(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 static OwnershipTransferredEventResponse getOwnershipTransferredEventFromLog(Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(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(EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getOwnershipTransferredEventFromLog(log));
+ }
+
+ 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 getTransferEvents(TransactionReceipt transactionReceipt) {
+ List valueList = staticExtractEventParametersWithLog(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 static TransferEventResponse getTransferEventFromLog(Log log) {
+ Contract.EventValuesWithLog eventValues = staticExtractEventParametersWithLog(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(EthFilter filter) {
+ return web3j.ethLogFlowable(filter).map(log -> getTransferEventFromLog(log));
+ }
+
+ 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 CANNOT_TRANSFER_TO_ZERO_ADDRESS() {
+ final Function function = new Function(FUNC_CANNOT_TRANSFER_TO_ZERO_ADDRESS,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall NOT_CURRENT_OWNER() {
+ final Function function = new Function(FUNC_NOT_CURRENT_OWNER,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall approve(String _approved, BigInteger _tokenId) {
+ final Function function = new Function(
+ FUNC_APPROVE,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, _approved),
+ new org.web3j.abi.datatypes.generated.Uint256(_tokenId)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall balanceOf(String _owner) {
+ final Function function = new Function(FUNC_BALANCEOF,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, _owner)),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, BigInteger.class);
+ }
+
+ public RemoteFunctionCall getApproved(BigInteger _tokenId) {
+ final Function function = new Function(FUNC_GETAPPROVED,
+ Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(_tokenId)),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall isApprovedForAll(String _owner, String _operator) {
+ final Function function = new Function(FUNC_ISAPPROVEDFORALL,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, _owner),
+ new org.web3j.abi.datatypes.Address(160, _operator)),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, Boolean.class);
+ }
+
+ public RemoteFunctionCall mint(String _to, BigInteger _tokenId, String _uri) {
+ final Function function = new Function(
+ FUNC_MINT,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, _to),
+ new org.web3j.abi.datatypes.generated.Uint256(_tokenId),
+ new org.web3j.abi.datatypes.Utf8String(_uri)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ public RemoteFunctionCall name() {
+ final Function function = new Function(FUNC_NAME,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall owner() {
+ final Function function = new Function(FUNC_OWNER,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall ownerOf(BigInteger _tokenId) {
+ final Function function = new Function(FUNC_OWNEROF,
+ Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(_tokenId)),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall safeTransferFrom(String _from, String _to, BigInteger _tokenId) {
+ final Function function = new 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 Function function = new 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 Function function = new 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(byte[] _interfaceID) {
+ final Function function = new 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 Function function = new Function(FUNC_SYMBOL,
+ Arrays.asList(),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall tokenURI(BigInteger _tokenId) {
+ final Function function = new Function(FUNC_TOKENURI,
+ Arrays.asList(new org.web3j.abi.datatypes.generated.Uint256(_tokenId)),
+ Arrays.>asList(new TypeReference() {}));
+ return executeRemoteCallSingleValueReturn(function, String.class);
+ }
+
+ public RemoteFunctionCall transferFrom(String _from, String _to, BigInteger _tokenId) {
+ final Function function = new 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 Function function = new Function(
+ FUNC_TRANSFEROWNERSHIP,
+ Arrays.asList(new org.web3j.abi.datatypes.Address(160, _newOwner)),
+ Collections.>emptyList());
+ return executeRemoteCallTransaction(function);
+ }
+
+ @Deprecated
+ public static NFT load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
+ return new NFT(contractAddress, web3j, credentials, gasPrice, gasLimit);
+ }
+ @Deprecated
+ public static NFT load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
+ return new NFT(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
+ }
+
+
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/zerobibim/flory/domain/contract/controller/NftController.java b/src/main/java/zerobibim/flory/domain/contract/controller/NftController.java
new file mode 100644
index 0000000..70a11e9
--- /dev/null
+++ b/src/main/java/zerobibim/flory/domain/contract/controller/NftController.java
@@ -0,0 +1,32 @@
+package zerobibim.flory.domain.contract.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import zerobibim.flory.domain.contract.NFT;
+import zerobibim.flory.domain.contract.NFT.*;
+
+import java.math.BigInteger;
+
+@RestController
+@RequestMapping("/api/nft")
+public class NftController {
+ private final NFT nft;
+
+ @Autowired
+ public NftController(NFT nft) {
+ this.nft = nft;
+ }
+
+ // Define your API endpoints here
+ @PostMapping("/mint")
+ public String mintToken(@RequestParam String to, @RequestParam BigInteger tokenId, @RequestParam String uri) {
+ try {
+ // Mint a new token
+ return "Token minted successfully";
+ } catch (Exception e) {
+ // Handle exceptions appropriately (e.g., log the error)
+ return "Error minting token: " + e.getMessage();
+ }
+ }
+}
diff --git a/src/main/java/zerobibim/flory/domain/contract/dto/NFTRequestDto.java b/src/main/java/zerobibim/flory/domain/contract/dto/NFTRequestDto.java
new file mode 100644
index 0000000..f9e1aa2
--- /dev/null
+++ b/src/main/java/zerobibim/flory/domain/contract/dto/NFTRequestDto.java
@@ -0,0 +1,16 @@
+package zerobibim.flory.domain.contract.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+public class NFTRequestDto {
+ @Getter
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class MemberNFTInfo {
+ private String walletAddress;
+ private String ipfsUrl;
+ }
+
+}
diff --git a/src/main/java/zerobibim/flory/domain/contract/service/IPFSPhotoService.java b/src/main/java/zerobibim/flory/domain/contract/service/IPFSPhotoService.java
new file mode 100644
index 0000000..17ff022
--- /dev/null
+++ b/src/main/java/zerobibim/flory/domain/contract/service/IPFSPhotoService.java
@@ -0,0 +1,38 @@
+package zerobibim.flory.domain.contract.service;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import okhttp3.*;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.IOException;
+
+@Service
+public class IPFSPhotoService {
+
+ @Value("${pinata.JWT}")
+ private String PINATE_JWT;
+ public String insertIpfs(Long memberPhotoId) throws IOException {
+
+ OkHttpClient client = new OkHttpClient();
+
+ MediaType mediaType = MediaType.parse("application/json");
+ RequestBody body = RequestBody.create(mediaType, "{\"pinataContent\":{\"name\": \"" +memberPhoto.getName() + "\""
+ + ",\"description\":\"" + memberPhoto.getDescription() + "\",\"image\":\"" + memberPhoto.getImageUrl() + "\"}}");
+
+ Request request = new Request.Builder()
+ .url("https://api.pinata.cloud/pinning/pinJSONToIPFS")
+ .post(body)
+ .addHeader("Authorization", PINATA_JWT)
+ .addHeader("accept", "application/json")
+ .addHeader("content-type", "application/json")
+ .build();
+
+ ResponseBody responsebody = client.newCall(request).execute().body();
+ ObjectMapper mapper = new ObjectMapper();
+ assert responsebody != null;
+ JsonNode jsonNode = mapper.readTree(responsebody.byteStream());
+ return jsonNode.get("IpfsHash").asText();
+ }
+}
diff --git a/src/main/java/zerobibim/flory/domain/contract/service/Web3jService.java b/src/main/java/zerobibim/flory/domain/contract/service/Web3jService.java
new file mode 100644
index 0000000..75e72a6
--- /dev/null
+++ b/src/main/java/zerobibim/flory/domain/contract/service/Web3jService.java
@@ -0,0 +1,34 @@
+package zerobibim.flory.domain.contract.service;
+
+import org.springframework.beans.factory.annotation.Value;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.web3j.abi.EventEncoder;
+import org.web3j.abi.datatypes.generated.Uint256;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.DefaultBlockParameter;
+import org.web3j.protocol.core.DefaultBlockParameterName;
+import org.web3j.protocol.core.methods.response.*;
+import zerobibim.flory.domain.contract.NFT;
+import zerobibim.flory.domain.contract.dto.NFTRequestDto;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.concurrent.ExecutionException;
+
+@Slf4j
+@RequiredArgsConstructor
+@Service("web3jService")
+public class Web3jService {
+
+ private final NFT nft;
+
+ public TransactionReceipt nftCreate(NFTRequestDto.MemberNFTInfo memberNFTInfo) throws Exception {
+
+ return nft.mint(memberNFTInfo.getWalletAddress(), "ipfs://" +)
+ .sendAsync()
+ .get();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/zerobibim/flory/global/config/Web3jConfig.java b/src/main/java/zerobibim/flory/global/config/Web3jConfig.java
new file mode 100644
index 0000000..c107af1
--- /dev/null
+++ b/src/main/java/zerobibim/flory/global/config/Web3jConfig.java
@@ -0,0 +1,47 @@
+package zerobibim.flory.global.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.web3j.crypto.Credentials;
+import org.web3j.crypto.ECKeyPair;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.http.HttpService;
+import org.web3j.tx.Contract;
+import org.web3j.tx.gas.StaticGasProvider;
+import zerobibim.flory.domain.contract.NFT;
+
+import java.math.BigInteger;
+
+@Configuration
+public class Web3jConfig {
+
+ @Value("${infura.API_URL}")
+ private String INFURA_API_URL;
+
+ @Value("${metamask.PRIVATE_KEY}")
+ private String PRIVATE_KEY;
+
+ @Value("${metamask.CONTRACT_ADDRESS}")
+ private String CONTRACT_ADDRESS;
+
+ @Bean
+ public Web3j web3j() {
+ return Web3j.build(new HttpService(INFURA_API_URL));
+ }
+
+ @Bean
+ public Credentials credentials() {
+ BigInteger privateKeyInBT = new BigInteger(PRIVATE_KEY, 16);
+ return Credentials.create(ECKeyPair.create(privateKeyInBT));
+ }
+
+ @Bean
+ public NFT nft() {
+ BigInteger gasPrice = Contract.GAS_PRICE;
+ BigInteger gasLimit = Contract.GAS_LIMIT;
+ //StaticGasProvider gasProvider = new StaticGasProvider(gasPrice, gasLimit);
+
+ return NFT.load(CONTRACT_ADDRESS, web3j(), credentials(), gasPrice, gasLimit);
+ }
+}
\ No newline at end of file