Skip to content

Commit 4abe166

Browse files
committed
rest calls simplified
1 parent 0a0daf7 commit 4abe166

File tree

1 file changed

+98
-104
lines changed

1 file changed

+98
-104
lines changed

hedera-spring/src/main/java/com/openelements/hedera/spring/implementation/MirrorNodeClientImpl.java

Lines changed: 98 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.io.IOException;
1515
import java.net.URI;
1616
import java.util.List;
17+
import java.util.Map;
1718
import java.util.Objects;
1819
import java.util.Optional;
1920
import java.util.Spliterator;
@@ -33,22 +34,99 @@ public class MirrorNodeClientImpl implements MirrorNodeClient {
3334

3435
private final RestClient restClient;
3536

36-
private final String mirrorNodeEndpoint;
37+
private final String mirrorNodeEndpointScheme = "https";
38+
39+
private final String mirrorNodeEndpointHost;
40+
41+
private final String mirrorNodeEndpointPort;
42+
3743

3844
public MirrorNodeClientImpl(@NonNull final Client client) {
3945
Objects.requireNonNull(client, "client must not be null");
4046
final List<String> mirrorNetwork = client.getMirrorNetwork();
4147
if (mirrorNetwork.isEmpty()) {
4248
throw new IllegalArgumentException("No mirror network is configured");
4349
}
44-
mirrorNodeEndpoint = "https://" + mirrorNetwork.get(0);
50+
mirrorNodeEndpointHost = mirrorNetwork.get(0).split("\\:")[0];
51+
mirrorNodeEndpointPort = mirrorNetwork.get(0).split("\\:")[1];
4552
objectMapper = new ObjectMapper();
4653
restClient = RestClient.create();
4754
}
4855

56+
@Override
57+
public List<Nft> queryNftsByAccount(@NonNull final AccountId accountId) throws HederaException {
58+
Objects.requireNonNull(accountId, "accountId must not be null");
59+
final JsonNode jsonNode = doGetCall("/api/v1/accounts/" + accountId + "/nfts");
60+
return jsonNodeToNftList(jsonNode);
61+
}
62+
63+
@Override
64+
public List<Nft> queryNftsByAccountAndTokenId(@NonNull final AccountId accountId, @NonNull final TokenId tokenId)
65+
throws HederaException {
66+
Objects.requireNonNull(accountId, "accountId must not be null");
67+
Objects.requireNonNull(tokenId, "tokenId must not be null");
68+
final JsonNode jsonNode = doGetCall("/api/v1/tokens/" + tokenId + "/nfts", Map.of("account.id", accountId));
69+
return jsonNodeToNftList(jsonNode);
70+
}
71+
72+
@Override
73+
public List<Nft> queryNftsByTokenId(@NonNull TokenId tokenId) throws HederaException {
74+
Objects.requireNonNull(tokenId, "tokenId must not be null");
75+
final JsonNode jsonNode = doGetCall("/api/v1/tokens/" + tokenId + "/nfts");
76+
return jsonNodeToNftList(jsonNode);
77+
}
78+
79+
@Override
80+
public Optional<Nft> queryNftsByTokenIdAndSerial(@NonNull final TokenId tokenId, @NonNull final long serialNumber)
81+
throws HederaException {
82+
Objects.requireNonNull(tokenId, "tokenId must not be null");
83+
if (serialNumber <= 0) {
84+
throw new IllegalArgumentException("serialNumber must be positive");
85+
}
86+
final JsonNode jsonNode = doGetCall("/api/v1/tokens/" + tokenId + "/nfts/" + serialNumber);
87+
return jsonNodeToOptionalNft(jsonNode);
88+
}
89+
90+
@Override
91+
public Optional<Nft> queryNftsByAccountAndTokenIdAndSerial(@NonNull final AccountId accountId,
92+
@NonNull final TokenId tokenId, final long serialNumber) throws HederaException {
93+
Objects.requireNonNull(accountId, "accountId must not be null");
94+
return queryNftsByTokenIdAndSerial(tokenId, serialNumber)
95+
.filter(nft -> Objects.equals(nft.owner(), accountId));
96+
}
97+
98+
@Override
99+
public Optional<TransactionInfo> queryTransaction(@NonNull final String transactionId) throws HederaException {
100+
Objects.requireNonNull(transactionId, "transactionId must not be null");
101+
final JsonNode jsonNode = doGetCall("/api/v1/transactions/" + transactionId);
102+
if (jsonNode == null || !jsonNode.fieldNames().hasNext()) {
103+
return Optional.empty();
104+
}
105+
return Optional.of(new TransactionInfo(transactionId));
106+
}
107+
108+
private JsonNode doGetCall(String path, Map<String, ?> params) throws HederaException {
109+
return doGetCall(builder -> {
110+
UriBuilder uriBuilder = builder.path(path);
111+
for (Map.Entry<String, ?> entry : params.entrySet()) {
112+
uriBuilder = uriBuilder.queryParam(entry.getKey(), entry.getValue());
113+
}
114+
return uriBuilder.build();
115+
});
116+
}
117+
118+
private JsonNode doGetCall(String path) throws HederaException {
119+
return doGetCall(builder -> builder.path(path).build());
120+
}
121+
49122
private JsonNode doGetCall(Function<UriBuilder, URI> uriFunction) throws HederaException {
50123
final ResponseEntity<String> responseEntity = restClient.get()
51-
.uri(uriFunction)
124+
.uri(uriBuilder -> {
125+
final UriBuilder withEndpoint = uriBuilder.scheme(mirrorNodeEndpointScheme)
126+
.host(mirrorNodeEndpointHost)
127+
.port(mirrorNodeEndpointPort);
128+
return uriFunction.apply(withEndpoint);
129+
})
52130
.accept(MediaType.APPLICATION_JSON)
53131
.retrieve()
54132
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
@@ -59,7 +137,7 @@ private JsonNode doGetCall(Function<UriBuilder, URI> uriFunction) throws HederaE
59137
.toEntity(String.class);
60138
final String body = responseEntity.getBody();
61139
try {
62-
if(HttpStatus.NOT_FOUND.equals(responseEntity.getStatusCode())) {
140+
if (HttpStatus.NOT_FOUND.equals(responseEntity.getStatusCode())) {
63141
return objectMapper.readTree("{}");
64142
}
65143
return objectMapper.readTree(body);
@@ -68,55 +146,8 @@ private JsonNode doGetCall(Function<UriBuilder, URI> uriFunction) throws HederaE
68146
}
69147
}
70148

71-
@Override
72-
public List<Nft> queryNftsByAccount(@NonNull final AccountId accountId) throws HederaException {
73-
Objects.requireNonNull(accountId, "accountId must not be null");
74-
final String host = mirrorNodeEndpoint.substring(8).split("\\:")[0];
75-
final String port = mirrorNodeEndpoint.substring(8).split("\\:")[1];
76-
77-
final JsonNode jsonNode = doGetCall(builder ->
78-
builder
79-
.scheme("https")
80-
.host(host)
81-
.port(port)
82-
.path("/api/v1/accounts/" + accountId + "/nfts")
83-
.build()
84-
);
85-
return parseJsonToList(jsonNode);
86-
}
87-
88-
@Override
89-
public List<Nft> queryNftsByAccountAndTokenId(@NonNull final AccountId accountId, @NonNull final TokenId tokenId) throws HederaException {
90-
Objects.requireNonNull(accountId, "accountId must not be null");
91-
Objects.requireNonNull(tokenId, "tokenId must not be null");
92-
final String host = mirrorNodeEndpoint.substring(8).split("\\:")[0];
93-
final String port = mirrorNodeEndpoint.substring(8).split("\\:")[1];
94-
final JsonNode jsonNode = doGetCall(builder -> builder
95-
.scheme("https")
96-
.host(host)
97-
.port(port)
98-
.path("/api/v1/tokens/" + tokenId + "/nfts")
99-
.queryParam("account.id", accountId)
100-
.build());
101-
return parseJsonToList(jsonNode);
102-
}
103-
104-
@Override
105-
public List<Nft> queryNftsByTokenId(@NonNull TokenId tokenId) throws HederaException {
106-
Objects.requireNonNull(tokenId, "tokenId must not be null");
107-
final String host = mirrorNodeEndpoint.substring(8).split("\\:")[0];
108-
final String port = mirrorNodeEndpoint.substring(8).split("\\:")[1];
109-
final JsonNode jsonNode = doGetCall(builder -> builder
110-
.scheme("https")
111-
.host(host)
112-
.port(port)
113-
.path("/api/v1/tokens/" + tokenId + "/nfts")
114-
.build());
115-
return parseJsonToList(jsonNode);
116-
}
117-
118-
private List<Nft> parseJsonToList(final JsonNode rootNode) {
119-
if(rootNode == null || !rootNode.fieldNames().hasNext()) {
149+
private List<Nft> jsonNodeToNftList(final JsonNode rootNode) {
150+
if (rootNode == null || !rootNode.fieldNames().hasNext()) {
120151
return List.of();
121152
}
122153
return StreamSupport.stream(
@@ -130,64 +161,27 @@ private List<Nft> parseJsonToList(final JsonNode rootNode) {
130161
}).toList();
131162
}
132163

164+
private Optional<Nft> jsonNodeToOptionalNft(final JsonNode jsonNode) throws HederaException {
165+
if (jsonNode == null || !jsonNode.fieldNames().hasNext()) {
166+
return Optional.empty();
167+
}
168+
try {
169+
return Optional.of(jsonNodeToNft(jsonNode));
170+
} catch (final Exception e) {
171+
throw new HederaException("Error parsing NFT from JSON '" + jsonNode + "'", e);
172+
}
173+
}
174+
133175
private Nft jsonNodeToNft(final JsonNode jsonNode) throws IOException {
176+
try {
134177
final TokenId parsedTokenId = TokenId.fromString(jsonNode.get("token_id").asText());
135178
final AccountId account = AccountId.fromString(jsonNode.get("account_id").asText());
136179
final long serial = jsonNode.get("serial_number").asLong();
137180
final byte[] metadata = jsonNode.get("metadata").binaryValue();
138181
return new Nft(parsedTokenId, serial, account, metadata);
139-
}
140-
141-
@Override
142-
public Optional<Nft> queryNftsByTokenIdAndSerial(@NonNull final TokenId tokenId, @NonNull final long serialNumber) throws HederaException {
143-
Objects.requireNonNull(tokenId, "tokenId must not be null");
144-
if(serialNumber <= 0) {
145-
throw new IllegalArgumentException("serialNumber must be positive");
146-
}
147-
final String body = restClient.get()
148-
.uri(mirrorNodeEndpoint + "/api/v1/tokens/" + tokenId + "/nfts/" + serialNumber)
149-
.accept(MediaType.APPLICATION_JSON)
150-
.retrieve()
151-
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
152-
if (!HttpStatus.NOT_FOUND.equals(response.getStatusCode())) {
153-
throw new RuntimeException("Client error: " + response.getStatusText());
154-
}
155-
}).body(String.class);
156-
if(body == null || body.equals("{\"_status\":{\"messages\":[{\"message\":\"Not found\"}]}}")) {
157-
return Optional.empty();
158-
}
159-
try {
160-
JsonNode jsonNode = objectMapper.readTree(body);
161-
return Optional.ofNullable(jsonNodeToNft(jsonNode));
162-
} catch (IOException e) {
163-
throw new HederaException("Error parsing body as JSON: " + body, e);
182+
} catch (final Exception e) {
183+
throw new IllegalArgumentException("Error parsing NFT from JSON '" + jsonNode + "'", e);
164184
}
165185
}
166186

167-
@Override
168-
public Optional<Nft> queryNftsByAccountAndTokenIdAndSerial(@NonNull final AccountId accountId, @NonNull final TokenId tokenId, final long serialNumber) throws HederaException {
169-
Objects.requireNonNull(accountId, "accountId must not be null");
170-
return queryNftsByTokenIdAndSerial(tokenId, serialNumber)
171-
.filter(nft -> Objects.equals(nft.owner(), accountId));
172-
}
173-
174-
@Override
175-
public Optional<TransactionInfo> queryTransaction(@NonNull final String transactionId) throws HederaException {
176-
Objects.requireNonNull(transactionId, "transactionId must not be null");
177-
final ResponseEntity<String> entity = restClient.get()
178-
.uri(mirrorNodeEndpoint + "/api/v1/transactions/" + transactionId)
179-
.accept(MediaType.APPLICATION_JSON)
180-
.retrieve()
181-
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
182-
if (!HttpStatus.NOT_FOUND.equals(response.getStatusCode())) {
183-
throw new RuntimeException("Client error: " + response.getStatusText());
184-
}
185-
}).toEntity(String.class);
186-
if(HttpStatus.NOT_FOUND.equals(entity.getStatusCode())) {
187-
return Optional.empty();
188-
}
189-
final String body = entity.getBody();
190-
//TODO: JSON PARSING
191-
return Optional.of(new TransactionInfo(transactionId));
192-
}
193187
}

0 commit comments

Comments
 (0)