From cec0fa2edd5402f04fb8759af514442cec5fb309 Mon Sep 17 00:00:00 2001 From: grapebaba <281165273@qq.com> Date: Sun, 4 Dec 2022 13:52:14 +0800 Subject: [PATCH 1/2] feat: add get transactions api. Signed-off-by: grapebaba <281165273@qq.com> --- README.md | 12 +- .../java/io/sui/QueryClientImplIntTests.java | 25 ++ src/main/java/io/sui/clients/QueryClient.java | 14 + .../java/io/sui/clients/QueryClientImpl.java | 12 + .../java/io/sui/jsonrpc/GsonJsonHandler.java | 16 ++ .../sui/models/transactions/MoveFunction.java | 123 ++++++++ .../PaginatedTransactionDigests.java | 98 +++++++ .../models/transactions/TransactionQuery.java | 270 ++++++++++++++++++ .../io/sui/clients/QueryClientImplTests.java | 23 ++ .../resources/mockdata/getTransactions.json | 10 + 10 files changed, 597 insertions(+), 6 deletions(-) create mode 100644 src/main/java/io/sui/models/transactions/MoveFunction.java create mode 100644 src/main/java/io/sui/models/transactions/PaginatedTransactionDigests.java create mode 100644 src/main/java/io/sui/models/transactions/TransactionQuery.java create mode 100644 src/test/resources/mockdata/getTransactions.json diff --git a/README.md b/README.md index 5f4eb78..40c709c 100644 --- a/README.md +++ b/README.md @@ -97,24 +97,24 @@ TODO - [x] sui_getRawObject - [x] sui_getTotalTransactionNumber - [x] sui_getTransaction -- [ ] sui_getTransactions +- [x] sui_getTransactions - [x] sui_getTransactionsInRange - [x] sui_mergeCoins -- [x] sui_moveCall +- [ ] sui_moveCall - [x] sui_pay - [x] sui_payAllSui - [x] sui_paySui -- [x] sui_publish +- [ ] sui_publish - [x] sui_splitCoin - [x] sui_splitCoinEqual - [ ] sui_subscribeEvent - [x] sui_transferObject - [x] sui_transferSui -- [ ] sui_tryGetPastObject +- [x] sui_tryGetPastObject ## Examples -### create client +### create query client ```java final String BASE_URL="http://localhost:9000"; @@ -122,7 +122,7 @@ final JsonHandler jsonHandler=new GsonJsonHandler(); final JsonRpcClientProvider jsonRpcClientProvider= new OkHttpJsonRpcClientProvider(BASE_URL,jsonHandler); -final SuiClient client=new SuiClientImpl(jsonRpcClientProvider); +final QueryClient client=new QueryClientImpl(jsonRpcClientProvider); ``` ### sui_getCommitteeInfo diff --git a/src/integrationTest/java/io/sui/QueryClientImplIntTests.java b/src/integrationTest/java/io/sui/QueryClientImplIntTests.java index 34cd093..efe39b6 100644 --- a/src/integrationTest/java/io/sui/QueryClientImplIntTests.java +++ b/src/integrationTest/java/io/sui/QueryClientImplIntTests.java @@ -35,6 +35,10 @@ import io.sui.models.objects.MoveNormalizedStruct; import io.sui.models.objects.ObjectResponse; import io.sui.models.objects.SuiObjectInfo; +import io.sui.models.transactions.PaginatedTransactionDigests; +import io.sui.models.transactions.TransactionQuery; +import io.sui.models.transactions.TransactionQuery.AllQuery; +import io.sui.models.transactions.TransactionQuery.FromAddressQuery; import io.sui.models.transactions.TransactionResponse; import java.util.List; import java.util.Map; @@ -440,4 +444,25 @@ void tryGetPastObject() throws ExecutionException, InterruptedException { client.tryGetPastObject("0x163e344adfb74793481c77661f463811b990fe2a", 1); System.out.println(res1.get()); } + + /** + * Gets transactions. + * + * @throws ExecutionException the execution exception + * @throws InterruptedException the interrupted exception + */ + @Test + @DisplayName("Test getTransactions.") + void getTransactions() throws ExecutionException, InterruptedException { + TransactionQuery query = AllQuery.All; + CompletableFuture res = + client.getTransactions(query, null, 10, false); + System.out.println(res.get()); + + FromAddressQuery query1 = new FromAddressQuery(); + query1.setFromAddress("0xea79464d86786b7a7a63e3f13f798f29f5e65947"); + CompletableFuture res1 = + client.getTransactions(query1, null, 10, false); + System.out.println(res1.get()); + } } diff --git a/src/main/java/io/sui/clients/QueryClient.java b/src/main/java/io/sui/clients/QueryClient.java index 70f3b22..fdb2364 100644 --- a/src/main/java/io/sui/clients/QueryClient.java +++ b/src/main/java/io/sui/clients/QueryClient.java @@ -27,6 +27,8 @@ import io.sui.models.objects.MoveNormalizedStruct; import io.sui.models.objects.ObjectResponse; import io.sui.models.objects.SuiObjectInfo; +import io.sui.models.transactions.PaginatedTransactionDigests; +import io.sui.models.transactions.TransactionQuery; import io.sui.models.transactions.TransactionResponse; import java.util.List; import java.util.Map; @@ -175,4 +177,16 @@ CompletableFuture getNormalizedMoveStruct( * @return the completable future */ CompletableFuture tryGetPastObject(String objectId, long version); + + /** + * Gets transactions. + * + * @param query the query + * @param cursor the cursor + * @param limit the limit + * @param isDescOrder the is desc order + * @return the transactions + */ + CompletableFuture getTransactions( + TransactionQuery query, String cursor, int limit, boolean isDescOrder); } diff --git a/src/main/java/io/sui/clients/QueryClientImpl.java b/src/main/java/io/sui/clients/QueryClientImpl.java index eaf9f6b..6b987f3 100644 --- a/src/main/java/io/sui/clients/QueryClientImpl.java +++ b/src/main/java/io/sui/clients/QueryClientImpl.java @@ -31,6 +31,8 @@ import io.sui.models.objects.MoveNormalizedStruct; import io.sui.models.objects.ObjectResponse; import io.sui.models.objects.SuiObjectInfo; +import io.sui.models.transactions.PaginatedTransactionDigests; +import io.sui.models.transactions.TransactionQuery; import io.sui.models.transactions.TransactionResponse; import java.util.List; import java.util.Map; @@ -206,4 +208,14 @@ public CompletableFuture tryGetPastObject(String objectId, long return this.jsonRpcClientProvider.callAndUnwrapResponse( "/sui_tryGetPastObject", request, new TypeToken() {}.getType()); } + + @Override + public CompletableFuture getTransactions( + TransactionQuery query, String cursor, int limit, boolean isDescOrder) { + final JsonRpc20Request request = + this.jsonRpcClientProvider.createJsonRpc20Request( + "sui_getTransactions", Lists.newArrayList(query, cursor, limit, isDescOrder)); + return this.jsonRpcClientProvider.callAndUnwrapResponse( + "/sui_getTransactions", request, new TypeToken() {}.getType()); + } } diff --git a/src/main/java/io/sui/jsonrpc/GsonJsonHandler.java b/src/main/java/io/sui/jsonrpc/GsonJsonHandler.java index c705dd1..d6dcf0f 100644 --- a/src/main/java/io/sui/jsonrpc/GsonJsonHandler.java +++ b/src/main/java/io/sui/jsonrpc/GsonJsonHandler.java @@ -64,6 +64,7 @@ import io.sui.models.transactions.ParsedTransactionResponseKind.ParsedPublishResponseKind; import io.sui.models.transactions.ParsedTransactionResponseKind.ParsedSplitCoinResponseKind; import io.sui.models.transactions.TransactionKind; +import io.sui.models.transactions.TransactionQuery; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; @@ -479,6 +480,20 @@ public InputObjectKind deserialize( } } + /** The type Transaction query serializer. */ + public class TransactionQuerySerializer implements JsonSerializer { + + @Override + public JsonElement serialize( + TransactionQuery src, Type typeOfSrc, JsonSerializationContext context) { + if (src instanceof TransactionQuery.AllQuery) { + return new JsonPrimitive(AllQuery.All.name()); + } + + return gson.toJsonTree(src, typeOfSrc); + } + } + private final Gson gson; /** Instantiates a new Gson json handler. */ @@ -509,6 +524,7 @@ AuthorityQuorumSignInfo.class, new AuthorityQuorumSignInfoDeserializer()) .registerTypeAdapter(CommitteeInfo.class, new CommitteeInfoDeserializer()) .registerTypeAdapter(MoveFunctionArgType.class, new MoveFunctionArgTypeDeserializer()) .registerTypeAdapter(InputObjectKind.class, new InputObjectKindDeserializer()) + .registerTypeAdapter(TransactionQuery.class, new TransactionQuerySerializer()) .create(); } diff --git a/src/main/java/io/sui/models/transactions/MoveFunction.java b/src/main/java/io/sui/models/transactions/MoveFunction.java new file mode 100644 index 0000000..50f6ae1 --- /dev/null +++ b/src/main/java/io/sui/models/transactions/MoveFunction.java @@ -0,0 +1,123 @@ +/* + * Copyright 2022 281165273grape@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package io.sui.models.transactions; + + +import java.util.Objects; + +/** + * The type Move function. + * + * @author grapebaba + * @since 2022.11 + */ +public class MoveFunction { + + private String suiPackage; + + private String module; + + private String function; + + /** + * Gets sui package. + * + * @return the sui package + */ + public String getSuiPackage() { + return suiPackage; + } + + /** + * Sets sui package. + * + * @param suiPackage the sui package + */ + public void setSuiPackage(String suiPackage) { + this.suiPackage = suiPackage; + } + + /** + * Gets module. + * + * @return the module + */ + public String getModule() { + return module; + } + + /** + * Sets module. + * + * @param module the module + */ + public void setModule(String module) { + this.module = module; + } + + /** + * Gets function. + * + * @return the function + */ + public String getFunction() { + return function; + } + + /** + * Sets function. + * + * @param function the function + */ + public void setFunction(String function) { + this.function = function; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof MoveFunction)) { + return false; + } + MoveFunction that = (MoveFunction) o; + return suiPackage.equals(that.suiPackage) + && module.equals(that.module) + && function.equals(that.function); + } + + @Override + public int hashCode() { + return Objects.hash(suiPackage, module, function); + } + + @Override + public String toString() { + return "MoveFunction{" + + "suiPackage='" + + suiPackage + + '\'' + + ", module='" + + module + + '\'' + + ", function='" + + function + + '\'' + + '}'; + } +} diff --git a/src/main/java/io/sui/models/transactions/PaginatedTransactionDigests.java b/src/main/java/io/sui/models/transactions/PaginatedTransactionDigests.java new file mode 100644 index 0000000..9aa01aa --- /dev/null +++ b/src/main/java/io/sui/models/transactions/PaginatedTransactionDigests.java @@ -0,0 +1,98 @@ +/* + * Copyright 2022 281165273grape@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package io.sui.models.transactions; + + +import java.util.List; +import java.util.Objects; + +/** + * The type Paginated transaction digests. + * + * @author grapebaba + * @since 2022.11 + */ +public class PaginatedTransactionDigests { + + private List data; + + private String nextCursor; + + /** + * Gets data. + * + * @return the data + */ + public List getData() { + return data; + } + + /** + * Sets data. + * + * @param data the data + */ + public void setData(List data) { + this.data = data; + } + + /** + * Gets next cursor. + * + * @return the next cursor + */ + public String getNextCursor() { + return nextCursor; + } + + /** + * Sets next cursor. + * + * @param nextCursor the next cursor + */ + public void setNextCursor(String nextCursor) { + this.nextCursor = nextCursor; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PaginatedTransactionDigests)) { + return false; + } + PaginatedTransactionDigests that = (PaginatedTransactionDigests) o; + return data.equals(that.data) && nextCursor.equals(that.nextCursor); + } + + @Override + public String toString() { + return "PaginatedTransactionDigests{" + + "data=" + + data + + ", nextCursor='" + + nextCursor + + '\'' + + '}'; + } + + @Override + public int hashCode() { + return Objects.hash(data, nextCursor); + } +} diff --git a/src/main/java/io/sui/models/transactions/TransactionQuery.java b/src/main/java/io/sui/models/transactions/TransactionQuery.java new file mode 100644 index 0000000..d1d26e3 --- /dev/null +++ b/src/main/java/io/sui/models/transactions/TransactionQuery.java @@ -0,0 +1,270 @@ +/* + * Copyright 2022 281165273grape@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +package io.sui.models.transactions; + + +import java.util.Objects; + +/** + * The interface Transaction query. + * + * @author grapebaba + * @since 2022.11 + */ +public interface TransactionQuery { + + /** The enum All query. */ + enum AllQuery implements TransactionQuery { + /** All all query. */ + All + } + + /** The type Move function query. */ + class MoveFunctionQuery implements TransactionQuery { + + @SuppressWarnings("checkstyle:MemberName") + private MoveFunction MoveFunction; + + /** + * Gets move function. + * + * @return the move function + */ + public MoveFunction getMoveFunction() { + return MoveFunction; + } + + /** + * Sets move function. + * + * @param moveFunction the move function + */ + public void setMoveFunction(MoveFunction moveFunction) { + MoveFunction = moveFunction; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof MoveFunctionQuery)) { + return false; + } + MoveFunctionQuery that = (MoveFunctionQuery) o; + return MoveFunction.equals(that.MoveFunction); + } + + @Override + public int hashCode() { + return Objects.hash(MoveFunction); + } + + @Override + public String toString() { + return "MoveFunctionQuery{" + "MoveFunction=" + MoveFunction + '}'; + } + } + + /** The type Input object query. */ + class InputObjectQuery implements TransactionQuery { + + @SuppressWarnings("checkstyle:MemberName") + private String InputObject; + + /** + * Gets input object. + * + * @return the input object + */ + public String getInputObject() { + return InputObject; + } + + /** + * Sets input object. + * + * @param inputObject the input object + */ + public void setInputObject(String inputObject) { + InputObject = inputObject; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof InputObjectQuery)) { + return false; + } + InputObjectQuery that = (InputObjectQuery) o; + return InputObject.equals(that.InputObject); + } + + @Override + public int hashCode() { + return Objects.hash(InputObject); + } + + @Override + public String toString() { + return "InputObjectQuery{" + "InputObject='" + InputObject + '\'' + '}'; + } + } + + /** The type Mutated object query. */ + class MutatedObjectQuery implements TransactionQuery { + + @SuppressWarnings("checkstyle:MemberName") + private String MutatedObject; + + /** + * Gets mutated object. + * + * @return the mutated object + */ + public String getMutatedObject() { + return MutatedObject; + } + + /** + * Sets mutated object. + * + * @param mutatedObject the mutated object + */ + public void setMutatedObject(String mutatedObject) { + MutatedObject = mutatedObject; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof MutatedObjectQuery)) { + return false; + } + MutatedObjectQuery that = (MutatedObjectQuery) o; + return MutatedObject.equals(that.MutatedObject); + } + + @Override + public int hashCode() { + return Objects.hash(MutatedObject); + } + + @Override + public String toString() { + return "MutatedObjectQuery{" + "MutatedObject='" + MutatedObject + '\'' + '}'; + } + } + + /** The type From address query. */ + class FromAddressQuery implements TransactionQuery { + + @SuppressWarnings("checkstyle:MemberName") + private String FromAddress; + + /** + * Gets from address. + * + * @return the from address + */ + public String getFromAddress() { + return FromAddress; + } + + /** + * Sets from address. + * + * @param fromAddress the from address + */ + public void setFromAddress(String fromAddress) { + FromAddress = fromAddress; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof FromAddressQuery)) { + return false; + } + FromAddressQuery that = (FromAddressQuery) o; + return FromAddress.equals(that.FromAddress); + } + + @Override + public int hashCode() { + return Objects.hash(FromAddress); + } + + @Override + public String toString() { + return "FromAddressQuery{" + "FromAddress='" + FromAddress + '\'' + '}'; + } + } + + /** The type To address query. */ + class ToAddressQuery implements TransactionQuery { + + @SuppressWarnings("checkstyle:MemberName") + private String ToAddress; + + /** + * Gets to address. + * + * @return the to address + */ + public String getToAddress() { + return ToAddress; + } + + /** + * Sets to address. + * + * @param toAddress the to address + */ + public void setToAddress(String toAddress) { + ToAddress = toAddress; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ToAddressQuery)) { + return false; + } + ToAddressQuery that = (ToAddressQuery) o; + return ToAddress.equals(that.ToAddress); + } + + @Override + public int hashCode() { + return Objects.hash(ToAddress); + } + + @Override + public String toString() { + return "ToAddressQuery{" + "ToAddress='" + ToAddress + '\'' + '}'; + } + } +} diff --git a/src/test/java/io/sui/clients/QueryClientImplTests.java b/src/test/java/io/sui/clients/QueryClientImplTests.java index df5baa5..02c795c 100644 --- a/src/test/java/io/sui/clients/QueryClientImplTests.java +++ b/src/test/java/io/sui/clients/QueryClientImplTests.java @@ -60,7 +60,10 @@ import io.sui.models.objects.SuiObjectRef; import io.sui.models.transactions.ExecutionStatus.ExecutionStatusType; import io.sui.models.transactions.MoveCall; +import io.sui.models.transactions.PaginatedTransactionDigests; import io.sui.models.transactions.TransactionKind; +import io.sui.models.transactions.TransactionQuery; +import io.sui.models.transactions.TransactionQuery.AllQuery; import io.sui.models.transactions.TransactionResponse; import java.io.IOException; import java.math.BigInteger; @@ -218,6 +221,10 @@ public MockResponse dispatch(RecordedRequest request) { return getMockResponse("mockdata/tryGetPastObject.json"); } } + + if ("/sui_getTransactions".equals(request.getPath())) { + return getMockResponse("mockdata/getTransactions.json"); + } return new MockResponse().setResponseCode(404); } }; @@ -648,4 +655,20 @@ void tryGetPastObject() throws ExecutionException, InterruptedException { assertEquals( 0L, ((ObjectIdHigherVersionResponseDetails) res1.get().getDetails()).getLatest_version()); } + + /** + * Gets transactions. + * + * @throws ExecutionException the execution exception + * @throws InterruptedException the interrupted exception + */ + @Test + @DisplayName("Test getTransactions.") + void getTransactions() throws ExecutionException, InterruptedException { + TransactionQuery query = AllQuery.All; + CompletableFuture res = + client.getTransactions(query, null, 10, false); + System.out.println(res.get()); + assertEquals("9Kcsc7dJ72oDpyWcwR6ZXqkKXQke4mTGG1UmN2LrVdwj", res.get().getData().get(0)); + } } diff --git a/src/test/resources/mockdata/getTransactions.json b/src/test/resources/mockdata/getTransactions.json new file mode 100644 index 0000000..bb24640 --- /dev/null +++ b/src/test/resources/mockdata/getTransactions.json @@ -0,0 +1,10 @@ +{ + "jsonrpc": "2.0", + "result": { + "data": [ + "9Kcsc7dJ72oDpyWcwR6ZXqkKXQke4mTGG1UmN2LrVdwj" + ], + "nextCursor": null + }, + "id": 1 +} \ No newline at end of file From a318d043a9fa9ab554ca6f716658286d3fd995c7 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 4 Dec 2022 05:59:44 +0000 Subject: [PATCH 2/2] commit badge --- .github/badges/branches.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/badges/branches.svg b/.github/badges/branches.svg index 95209ac..5dc08e3 100644 --- a/.github/badges/branches.svg +++ b/.github/badges/branches.svg @@ -1 +1 @@ -branches40% \ No newline at end of file +branches39.5% \ No newline at end of file