From a30bef47ebe630ea07be68f002d9768755b23fa0 Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Sat, 2 Nov 2024 22:18:25 +0900 Subject: [PATCH 1/9] Setup new endpoints and unit tests --- .../org/onflow/flow/sdk/AsyncFlowAccessApi.kt | 4 +++ .../org/onflow/flow/sdk/FlowAccessApi.kt | 4 +++ .../flow/sdk/impl/AsyncFlowAccessApiImpl.kt | 14 ++++++++++ .../onflow/flow/sdk/impl/FlowAccessApiImpl.kt | 26 +++++++++++++++++++ .../org/onflow/flow/sdk/FlowAccessApiTest.kt | 24 +++++++++++++++++ .../sdk/impl/AsyncFlowAccessApiImplTest.kt | 18 +++++++++++++ .../flow/sdk/impl/FlowAccessApiImplTest.kt | 20 ++++++++++++++ 7 files changed, 110 insertions(+) diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt index 85d658d..66d31bf 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt @@ -64,6 +64,10 @@ interface AsyncFlowAccessApi { fun getLatestProtocolStateSnapshot(): CompletableFuture> + fun getProtocolStateSnapshotByBlockId(blockId: FlowId): CompletableFuture> + + fun getProtocolStateSnapshotByHeight(height: Long): CompletableFuture> + fun getNodeVersionInfo(): CompletableFuture> fun getTransactionsByBlockId(id: FlowId): CompletableFuture>> diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt index d736e3c..b160efd 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt @@ -76,6 +76,10 @@ interface FlowAccessApi { fun getLatestProtocolStateSnapshot(): AccessApiCallResponse + fun getProtocolStateSnapshotByBlockId(blockId: FlowId): AccessApiCallResponse + + fun getProtocolStateSnapshotByHeight(height: Long): AccessApiCallResponse + fun getNodeVersionInfo(): AccessApiCallResponse fun getTransactionsByBlockId(id: FlowId): AccessApiCallResponse> diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt index 2dc448b..fd65dc7 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt @@ -452,6 +452,20 @@ class AsyncFlowAccessApiImpl( errorMessage = "Failed to get latest protocol state snapshot" ) + override fun getProtocolStateSnapshotByHeight(height: Long): CompletableFuture> = + handleApiCall( + apiCall = { api.getProtocolStateSnapshotByHeight(Access.GetProtocolStateSnapshotByHeightRequest.newBuilder().setBlockHeight(height).build()) }, + transform = { FlowSnapshot(it.serializedSnapshot.toByteArray()) }, + errorMessage = "Failed to get protocol state snapshot by height" + ) + + override fun getProtocolStateSnapshotByBlockId(blockId: FlowId): CompletableFuture> = + handleApiCall( + apiCall = { api.getProtocolStateSnapshotByBlockID(Access.GetProtocolStateSnapshotByBlockIDRequest.newBuilder().setBlockId(blockId.byteStringValue).build()) }, + transform = { FlowSnapshot(it.serializedSnapshot.toByteArray()) }, + errorMessage = "Failed to get protocol state snapshot by block ID" + ) + override fun getNodeVersionInfo(): CompletableFuture> = handleApiCall( apiCall = { api.getNodeVersionInfo(Access.GetNodeVersionInfoRequest.newBuilder().build()) }, diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt index 87a63a2..75ef414 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt @@ -441,6 +441,32 @@ class FlowAccessApiImpl( FlowAccessApi.AccessApiCallResponse.Error("Failed to get latest protocol state snapshot", e) } + override fun getProtocolStateSnapshotByBlockId(blockId: FlowId): FlowAccessApi.AccessApiCallResponse = + try { + val ret = api.getProtocolStateSnapshotByBlockID( + Access.GetProtocolStateSnapshotByBlockIDRequest + .newBuilder() + .setBlockId(blockId.byteStringValue) + .build() + ) + FlowAccessApi.AccessApiCallResponse.Success(FlowSnapshot(ret.serializedSnapshot.toByteArray())) + } catch (e: Exception) { + FlowAccessApi.AccessApiCallResponse.Error("Failed to get protocol state snapshot by block ID", e) + } + + override fun getProtocolStateSnapshotByHeight(height: Long): FlowAccessApi.AccessApiCallResponse = + try { + val ret = api.getProtocolStateSnapshotByHeight( + Access.GetProtocolStateSnapshotByHeightRequest + .newBuilder() + .setBlockHeight(height) + .build() + ) + FlowAccessApi.AccessApiCallResponse.Success(FlowSnapshot(ret.serializedSnapshot.toByteArray())) + } catch (e: Exception) { + FlowAccessApi.AccessApiCallResponse.Error("Failed to get protocol state snapshot by height", e) + } + override fun getNodeVersionInfo(): FlowAccessApi.AccessApiCallResponse = try { val ret = api.getNodeVersionInfo( diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt index 5d392e4..ede75a6 100644 --- a/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt @@ -9,6 +9,8 @@ import kotlinx.coroutines.runBlocking import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test import org.mockito.Mockito.* +import org.onflow.flow.sdk.impl.AsyncFlowAccessApiImplTest.Companion.HEIGHT +import org.onflow.flow.sdk.impl.AsyncFlowAccessApiImplTest.Companion.blockId import org.onflow.protobuf.access.Access import org.onflow.protobuf.entities.AccountOuterClass import org.onflow.protobuf.entities.BlockExecutionDataOuterClass @@ -392,6 +394,28 @@ class FlowAccessApiTest { assertEquals(FlowAccessApi.AccessApiCallResponse.Success(snapshot), result) } + @Test + fun `Test getProtocolStateSnapshotByBlockId`() { + val flowAccessApi = mock(FlowAccessApi::class.java) + val snapshot = FlowSnapshot("snapshot".toByteArray()) + `when`(flowAccessApi.getProtocolStateSnapshotByBlockId(blockId)).thenReturn(FlowAccessApi.AccessApiCallResponse.Success(snapshot)) + + val result = flowAccessApi.getProtocolStateSnapshotByBlockId(blockId) + + assertEquals(FlowAccessApi.AccessApiCallResponse.Success(snapshot), result) + } + + @Test + fun `Test getProtocolStateSnapshotByHeight`() { + val flowAccessApi = mock(FlowAccessApi::class.java) + val snapshot = FlowSnapshot("snapshot".toByteArray()) + `when`(flowAccessApi.getProtocolStateSnapshotByHeight(HEIGHT)).thenReturn(FlowAccessApi.AccessApiCallResponse.Success(snapshot)) + + val result = flowAccessApi.getProtocolStateSnapshotByHeight(HEIGHT) + + assertEquals(FlowAccessApi.AccessApiCallResponse.Success(snapshot), result) + } + @Test fun `Test getTransactionsByBlockId`() { val flowAccessApi = mock(FlowAccessApi::class.java) diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt index 5d73161..0e8ce15 100644 --- a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt @@ -593,6 +593,24 @@ class AsyncFlowAccessApiImplTest { assertSuccess(result, mockFlowSnapshot) } + @Test + fun `test getProtocolStateSnapshotByBlockId`() { + val mockFlowSnapshot = FlowSnapshot("test_serialized_snapshot".toByteArray()) + `when`(api.getProtocolStateSnapshotByBlockID(any())).thenReturn(setupFutureMock(MockResponseFactory.protocolStateSnapshotResponse())) + + val result = asyncFlowAccessApi.getProtocolStateSnapshotByBlockId(blockId).get() + assertSuccess(result, mockFlowSnapshot) + } + + @Test + fun `test getProtocolStateSnapshotByHeight`() { + val mockFlowSnapshot = FlowSnapshot("test_serialized_snapshot".toByteArray()) + `when`(api.getProtocolStateSnapshotByHeight(any())).thenReturn(setupFutureMock(MockResponseFactory.protocolStateSnapshotResponse())) + + val result = asyncFlowAccessApi.getProtocolStateSnapshotByHeight(HEIGHT).get() + assertSuccess(result, mockFlowSnapshot) + } + @Test fun `test getNodeVersionInfo`() { val mockNodeVersionInfo = createMockNodeVersionInfo() diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt index f172e63..6fee43e 100644 --- a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt @@ -577,6 +577,26 @@ class FlowAccessApiImplTest { assertResultSuccess(result) { assertEquals(mockFlowSnapshot, it) } } + @Test + fun `Test getProtocolStateSnapshotByBlockId`() { + val mockFlowSnapshot = FlowSnapshot("test_serialized_snapshot".toByteArray()) + + `when`(mockApi.getProtocolStateSnapshotByBlockID(Access.GetProtocolStateSnapshotByBlockIDRequest.newBuilder().setBlockId(blockId.byteStringValue).build())).thenReturn(AsyncFlowAccessApiImplTest.MockResponseFactory.protocolStateSnapshotResponse()) + + val result = flowAccessApiImpl.getProtocolStateSnapshotByBlockId(blockId) + assertResultSuccess(result) { assertEquals(mockFlowSnapshot, it) } + } + + @Test + fun `Test getProtocolStateSnapshotByHeight`() { + val mockFlowSnapshot = FlowSnapshot("test_serialized_snapshot".toByteArray()) + + `when`(mockApi.getProtocolStateSnapshotByHeight(Access.GetProtocolStateSnapshotByHeightRequest.newBuilder().setBlockHeight(HEIGHT).build())).thenReturn(AsyncFlowAccessApiImplTest.MockResponseFactory.protocolStateSnapshotResponse()) + + val result = flowAccessApiImpl.getProtocolStateSnapshotByHeight(HEIGHT) + assertResultSuccess(result) { assertEquals(mockFlowSnapshot, it) } + } + @Test fun `Test getNodeVersionInfo`() { val mockNodeVersionInfo = createMockNodeVersionInfo() From f79bb7c1004932ec648688fe9c0c2dcd5d31c86a Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Sat, 2 Nov 2024 22:30:30 +0900 Subject: [PATCH 2/9] Kotlin example --- .../GetProtocolStateAccessAPIConnector.kt | 27 ++++++++++ ...GetNetworkParamsAccessAPIConnectorTest.kt} | 3 +- .../GetProtocolStateAccessAPIConnectorTest.kt | 54 +++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnector.kt rename kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/{GetNetworkParametersAccessAPIConnectorTest.kt => GetNetworkParamsAccessAPIConnectorTest.kt} (88%) create mode 100644 kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt diff --git a/kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnector.kt b/kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnector.kt new file mode 100644 index 0000000..ee41506 --- /dev/null +++ b/kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnector.kt @@ -0,0 +1,27 @@ +package org.onflow.examples.kotlin.getProtocolState + +import org.onflow.flow.sdk.FlowAccessApi +import org.onflow.flow.sdk.FlowId +import org.onflow.flow.sdk.FlowSnapshot + +internal class GetProtocolStateAccessAPIConnector( + private val accessAPI: FlowAccessApi +) { + fun getLatestProtocolStateSnapshot(): FlowSnapshot = + when (val response = accessAPI.getLatestProtocolStateSnapshot()) { + is FlowAccessApi.AccessApiCallResponse.Success -> response.data + is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) + } + + fun getProtocolStateSnapshotByBlockId(blockId: FlowId): FlowSnapshot = + when (val response = accessAPI.getProtocolStateSnapshotByBlockId(blockId)) { + is FlowAccessApi.AccessApiCallResponse.Success -> response.data + is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) + } + + fun getProtocolStateSnapshotByHeight(height: Long): FlowSnapshot = + when (val response = accessAPI.getProtocolStateSnapshotByHeight(height)) { + is FlowAccessApi.AccessApiCallResponse.Success -> response.data + is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) + } +} diff --git a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParametersAccessAPIConnectorTest.kt b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParamsAccessAPIConnectorTest.kt similarity index 88% rename from kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParametersAccessAPIConnectorTest.kt rename to kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParamsAccessAPIConnectorTest.kt index c89ff30..af260b7 100644 --- a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParametersAccessAPIConnectorTest.kt +++ b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParamsAccessAPIConnectorTest.kt @@ -3,13 +3,14 @@ package org.onflow.examples.kotlin.getNetworkParams import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import org.onflow.examples.kotlin.getProtocolState.GetProtocolStateAccessAPIConnector import org.onflow.flow.common.test.FlowEmulatorProjectTest import org.onflow.flow.common.test.FlowTestClient import org.onflow.flow.sdk.FlowAccessApi import org.onflow.flow.sdk.FlowChainId @FlowEmulatorProjectTest(flowJsonLocation = "../flow/flow.json") -internal class GetNetworkParametersAccessAPIConnectorTest { +internal class GetNetworkParamsAccessAPIConnectorTest { @FlowTestClient lateinit var accessAPI: FlowAccessApi diff --git a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt new file mode 100644 index 0000000..906e653 --- /dev/null +++ b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt @@ -0,0 +1,54 @@ +package org.onflow.examples.kotlin.getProtocolState + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.onflow.flow.common.test.FlowEmulatorProjectTest +import org.onflow.flow.common.test.FlowTestClient +import org.onflow.flow.sdk.FlowAccessApi +import org.onflow.flow.sdk.FlowBlock +import org.onflow.flow.sdk.FlowSnapshot + +@FlowEmulatorProjectTest(flowJsonLocation = "../flow/flow.json") +internal class GetProtocolStateAccessAPIConnectorTest { + @FlowTestClient + lateinit var accessAPI: FlowAccessApi + lateinit var block: FlowBlock + + private lateinit var protocolStateConnector: GetProtocolStateAccessAPIConnector + + @BeforeEach + fun setup() { + protocolStateConnector = GetProtocolStateAccessAPIConnector(accessAPI) + } + + @Test + fun `Can get latest protocol state snapshot`() { + val latestSnapshot: FlowSnapshot = protocolStateConnector.getLatestProtocolStateSnapshot() + assertNotNull(latestSnapshot, "Latest snapshot should not be null") + } + + @Test + fun `Can get protocol state snapshot by blockId`() { + + block = when (val response = accessAPI.getLatestBlock()) { + is FlowAccessApi.AccessApiCallResponse.Success -> response.data + is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) + } + + val latestSnapshot: FlowSnapshot = protocolStateConnector.getProtocolStateSnapshotByBlockId(block.id) + assertNotNull(latestSnapshot, ("Snapshot should not be null")) + } + + @Test + fun `Can get protocol state snapshot by height`() { + + block = when (val response = accessAPI.getLatestBlock()) { + is FlowAccessApi.AccessApiCallResponse.Success -> response.data + is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) + } + + val latestSnapshot: FlowSnapshot = protocolStateConnector.getProtocolStateSnapshotByHeight(block.height) + assertNotNull(latestSnapshot, ("Snapshot should not be null")) + } +} From 26ae86adfc602065e9fafa84fc2610aeb7dcb65a Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Mon, 4 Nov 2024 00:19:02 +0900 Subject: [PATCH 3/9] Add Java examples --- .../GetProtocolStateAccessAPIConnector.java | 43 +++++++++++++++ ...etProtocolStateAccessAPIConnectorTest.java | 55 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 java-example/src/main/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnector.java create mode 100644 java-example/src/test/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnectorTest.java diff --git a/java-example/src/main/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnector.java b/java-example/src/main/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnector.java new file mode 100644 index 0000000..9ceee1d --- /dev/null +++ b/java-example/src/main/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnector.java @@ -0,0 +1,43 @@ +package org.onflow.examples.java.getProtocolState; + +import org.onflow.flow.sdk.FlowAccessApi; +import org.onflow.flow.sdk.FlowId; +import org.onflow.flow.sdk.FlowSnapshot; + +public class GetProtocolStateAccessAPIConnector { + private final FlowAccessApi accessAPI; + + public GetProtocolStateAccessAPIConnector(FlowAccessApi accessAPI) { + this.accessAPI = accessAPI; + } + + public FlowSnapshot getLatestProtocolStateSnapshot() { + FlowAccessApi.AccessApiCallResponse response = accessAPI.getLatestProtocolStateSnapshot(); + if (response instanceof FlowAccessApi.AccessApiCallResponse.Success) { + return ((FlowAccessApi.AccessApiCallResponse.Success) response).getData(); + } else { + FlowAccessApi.AccessApiCallResponse.Error errorResponse = (FlowAccessApi.AccessApiCallResponse.Error) response; + throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable()); + } + } + + public FlowSnapshot getProtocolStateSnapshotByBlockId(FlowId blockId) { + FlowAccessApi.AccessApiCallResponse response = accessAPI.getProtocolStateSnapshotByBlockId(blockId); + if (response instanceof FlowAccessApi.AccessApiCallResponse.Success) { + return ((FlowAccessApi.AccessApiCallResponse.Success) response).getData(); + } else { + FlowAccessApi.AccessApiCallResponse.Error errorResponse = (FlowAccessApi.AccessApiCallResponse.Error) response; + throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable()); + } + } + + public FlowSnapshot getProtocolStateSnapshotByHeight(Long height) { + FlowAccessApi.AccessApiCallResponse response = accessAPI.getProtocolStateSnapshotByHeight(height); + if (response instanceof FlowAccessApi.AccessApiCallResponse.Success) { + return ((FlowAccessApi.AccessApiCallResponse.Success) response).getData(); + } else { + FlowAccessApi.AccessApiCallResponse.Error errorResponse = (FlowAccessApi.AccessApiCallResponse.Error) response; + throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable()); + } + } +} diff --git a/java-example/src/test/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnectorTest.java b/java-example/src/test/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnectorTest.java new file mode 100644 index 0000000..0288f98 --- /dev/null +++ b/java-example/src/test/java/org/onflow/examples/java/getProtocolState/GetProtocolStateAccessAPIConnectorTest.java @@ -0,0 +1,55 @@ +package org.onflow.examples.java.getProtocolState; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.onflow.flow.common.test.FlowEmulatorProjectTest; +import org.onflow.flow.common.test.FlowTestClient; +import org.onflow.flow.sdk.FlowAccessApi; +import org.onflow.flow.sdk.FlowBlock; +import org.onflow.flow.sdk.FlowSnapshot; + +import static org.junit.jupiter.api.Assertions.*; + +@FlowEmulatorProjectTest(flowJsonLocation = "../flow/flow.json") +public class GetProtocolStateAccessAPIConnectorTest { + @FlowTestClient + private FlowAccessApi accessAPI; + private FlowBlock block; + + private GetProtocolStateAccessAPIConnector protocolStateConnector; + + @BeforeEach + public void setup() { + protocolStateConnector = new GetProtocolStateAccessAPIConnector(accessAPI); + } + + @Test + public void canGetLatestProtocolStateSnapshot() { + FlowSnapshot latestSnapshot = protocolStateConnector.getLatestProtocolStateSnapshot(); + assertNotNull(latestSnapshot, "Latest snapshot should not be null"); + } + + @Test + public void canGetProtocolStateSnapshotByBlockId() { + block = getLatestBlock(); + FlowSnapshot snapshot = protocolStateConnector.getProtocolStateSnapshotByBlockId(block.getId()); + assertNotNull(snapshot, "Snapshot should not be null"); + } + + @Test + public void canGetProtocolStateSnapshotByHeight() { + block = getLatestBlock(); + FlowSnapshot snapshot = protocolStateConnector.getProtocolStateSnapshotByHeight(block.getHeight()); + assertNotNull(snapshot, "Snapshot should not be null"); + } + + private FlowBlock getLatestBlock() { + FlowAccessApi.AccessApiCallResponse response = accessAPI.getLatestBlock(true, false); + if (response instanceof FlowAccessApi.AccessApiCallResponse.Success) { + return ((FlowAccessApi.AccessApiCallResponse.Success) response).getData(); + } else { + FlowAccessApi.AccessApiCallResponse.Error errorResponse = (FlowAccessApi.AccessApiCallResponse.Error) response; + throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable()); + } + } +} From 81934027c861d51562137ff4cd21b5677df84250 Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Mon, 4 Nov 2024 00:25:04 +0900 Subject: [PATCH 4/9] Lint --- .../GetNetworkParamsAccessAPIConnectorTest.kt | 1 - .../GetProtocolStateAccessAPIConnectorTest.kt | 2 -- .../flow/sdk/impl/AsyncFlowAccessApiImpl.kt | 18 ++++++++++++++++-- .../flow/sdk/impl/FlowAccessApiImplTest.kt | 18 ++++++++++++++++-- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParamsAccessAPIConnectorTest.kt b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParamsAccessAPIConnectorTest.kt index af260b7..9759f75 100644 --- a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParamsAccessAPIConnectorTest.kt +++ b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getNetworkParams/GetNetworkParamsAccessAPIConnectorTest.kt @@ -3,7 +3,6 @@ package org.onflow.examples.kotlin.getNetworkParams import org.junit.jupiter.api.Assertions.* import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import org.onflow.examples.kotlin.getProtocolState.GetProtocolStateAccessAPIConnector import org.onflow.flow.common.test.FlowEmulatorProjectTest import org.onflow.flow.common.test.FlowTestClient import org.onflow.flow.sdk.FlowAccessApi diff --git a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt index 906e653..f59b6aa 100644 --- a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt +++ b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt @@ -30,7 +30,6 @@ internal class GetProtocolStateAccessAPIConnectorTest { @Test fun `Can get protocol state snapshot by blockId`() { - block = when (val response = accessAPI.getLatestBlock()) { is FlowAccessApi.AccessApiCallResponse.Success -> response.data is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) @@ -42,7 +41,6 @@ internal class GetProtocolStateAccessAPIConnectorTest { @Test fun `Can get protocol state snapshot by height`() { - block = when (val response = accessAPI.getLatestBlock()) { is FlowAccessApi.AccessApiCallResponse.Success -> response.data is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt index fd65dc7..853b110 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt @@ -454,14 +454,28 @@ class AsyncFlowAccessApiImpl( override fun getProtocolStateSnapshotByHeight(height: Long): CompletableFuture> = handleApiCall( - apiCall = { api.getProtocolStateSnapshotByHeight(Access.GetProtocolStateSnapshotByHeightRequest.newBuilder().setBlockHeight(height).build()) }, + apiCall = { + api.getProtocolStateSnapshotByHeight( + Access.GetProtocolStateSnapshotByHeightRequest + .newBuilder() + .setBlockHeight(height) + .build() + ) + }, transform = { FlowSnapshot(it.serializedSnapshot.toByteArray()) }, errorMessage = "Failed to get protocol state snapshot by height" ) override fun getProtocolStateSnapshotByBlockId(blockId: FlowId): CompletableFuture> = handleApiCall( - apiCall = { api.getProtocolStateSnapshotByBlockID(Access.GetProtocolStateSnapshotByBlockIDRequest.newBuilder().setBlockId(blockId.byteStringValue).build()) }, + apiCall = { + api.getProtocolStateSnapshotByBlockID( + Access.GetProtocolStateSnapshotByBlockIDRequest + .newBuilder() + .setBlockId(blockId.byteStringValue) + .build() + ) + }, transform = { FlowSnapshot(it.serializedSnapshot.toByteArray()) }, errorMessage = "Failed to get protocol state snapshot by block ID" ) diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt index 6fee43e..908653f 100644 --- a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt @@ -581,7 +581,14 @@ class FlowAccessApiImplTest { fun `Test getProtocolStateSnapshotByBlockId`() { val mockFlowSnapshot = FlowSnapshot("test_serialized_snapshot".toByteArray()) - `when`(mockApi.getProtocolStateSnapshotByBlockID(Access.GetProtocolStateSnapshotByBlockIDRequest.newBuilder().setBlockId(blockId.byteStringValue).build())).thenReturn(AsyncFlowAccessApiImplTest.MockResponseFactory.protocolStateSnapshotResponse()) + `when`( + mockApi.getProtocolStateSnapshotByBlockID( + Access.GetProtocolStateSnapshotByBlockIDRequest + .newBuilder() + .setBlockId(blockId.byteStringValue) + .build() + ) + ).thenReturn(AsyncFlowAccessApiImplTest.MockResponseFactory.protocolStateSnapshotResponse()) val result = flowAccessApiImpl.getProtocolStateSnapshotByBlockId(blockId) assertResultSuccess(result) { assertEquals(mockFlowSnapshot, it) } @@ -591,7 +598,14 @@ class FlowAccessApiImplTest { fun `Test getProtocolStateSnapshotByHeight`() { val mockFlowSnapshot = FlowSnapshot("test_serialized_snapshot".toByteArray()) - `when`(mockApi.getProtocolStateSnapshotByHeight(Access.GetProtocolStateSnapshotByHeightRequest.newBuilder().setBlockHeight(HEIGHT).build())).thenReturn(AsyncFlowAccessApiImplTest.MockResponseFactory.protocolStateSnapshotResponse()) + `when`( + mockApi.getProtocolStateSnapshotByHeight( + Access.GetProtocolStateSnapshotByHeightRequest + .newBuilder() + .setBlockHeight(HEIGHT) + .build() + ) + ).thenReturn(AsyncFlowAccessApiImplTest.MockResponseFactory.protocolStateSnapshotResponse()) val result = flowAccessApiImpl.getProtocolStateSnapshotByHeight(HEIGHT) assertResultSuccess(result) { assertEquals(mockFlowSnapshot, it) } From 223945b9affd73d25a33438e991201e8a6961113 Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Mon, 4 Nov 2024 02:04:48 +0900 Subject: [PATCH 5/9] Add integration tests --- .../transaction/TransactionIntegrationTest.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt b/sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt index 2fd2509..ee41865 100644 --- a/sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt +++ b/sdk/src/intTest/org/onflow/flow/sdk/transaction/TransactionIntegrationTest.kt @@ -33,6 +33,9 @@ class TransactionIntegrationTest { const val BLOCK_HEIGHT_ERROR = "Failed to get block by height" const val ACCOUNT_BY_ADDRESS_ERROR = "Failed to get account by address" const val ACCOUNT_BY_BLOCK_HEIGHT_ERROR = "Failed to get account by block height" + const val PROTOCOL_STATE_HEIGHT_ERROR = "Failed to get protocol state snapshot by height" + const val PROTOCOL_STATE_BLOCK_ERROR = "Failed to get protocol state snapshot by block ID" + const val PROTOCOL_STATE_LATEST_ERROR = "Failed to get latest protocol state snapshot" } private fun safelyHandle(action: () -> Result, errorMessage: String): T = @@ -86,6 +89,35 @@ class TransactionIntegrationTest { assertThat(account.keys).isNotEmpty() } + @Test + fun `Can get latest protocol state snapshot`() { + val snapshot = safelyHandle( + { Result.success(handleResult(accessAPI.getLatestProtocolStateSnapshot(), PROTOCOL_STATE_LATEST_ERROR)) }, + PROTOCOL_STATE_LATEST_ERROR + ) + assertThat(snapshot).isNotNull + } + + @Test + fun `Can get protocol state snapshot by blockId`() { + val latestBlock = getLatestBlock() + val snapshot = safelyHandle( + { Result.success(handleResult(accessAPI.getProtocolStateSnapshotByBlockId(latestBlock.id), PROTOCOL_STATE_HEIGHT_ERROR)) }, + PROTOCOL_STATE_BLOCK_ERROR + ) + assertThat(snapshot).isNotNull + } + + @Test + fun `Can get protocol state snapshot by height`() { + val latestBlock = getLatestBlock() + val snapshot = safelyHandle( + { Result.success(handleResult(accessAPI.getProtocolStateSnapshotByHeight(latestBlock.height), PROTOCOL_STATE_HEIGHT_ERROR)) }, + PROTOCOL_STATE_HEIGHT_ERROR + ) + assertThat(snapshot).isNotNull + } + @Test fun `Can get network parameters`() { val networkParams = safelyHandle( From d1f1811ec88bd250ac0528969ee19a2b4db6754f Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Mon, 4 Nov 2024 18:10:06 +0900 Subject: [PATCH 6/9] Setup get collection endpoint --- .../org/onflow/flow/sdk/AsyncFlowAccessApi.kt | 2 ++ .../org/onflow/flow/sdk/FlowAccessApi.kt | 2 ++ .../flow/sdk/impl/AsyncFlowAccessApiImpl.kt | 14 ++++++++++++++ .../onflow/flow/sdk/impl/FlowAccessApiImpl.kt | 13 +++++++++++++ .../main/kotlin/org/onflow/flow/sdk/models.kt | 18 ++++++++++++++++++ 5 files changed, 49 insertions(+) diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt index 66d31bf..03af937 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt @@ -32,6 +32,8 @@ interface AsyncFlowAccessApi { fun getCollectionById(id: FlowId): CompletableFuture> + fun getFullCollectionById(id: FlowId): CompletableFuture>> + fun sendTransaction(transaction: FlowTransaction): CompletableFuture> fun getTransactionById(id: FlowId): CompletableFuture> diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt index b160efd..ce8de86 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt @@ -44,6 +44,8 @@ interface FlowAccessApi { fun getCollectionById(id: FlowId): AccessApiCallResponse + fun getFullCollectionById(id: FlowId): AccessApiCallResponse> + fun sendTransaction(transaction: FlowTransaction): AccessApiCallResponse fun getTransactionById(id: FlowId): AccessApiCallResponse diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt index 853b110..c7ff3eb 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImpl.kt @@ -285,6 +285,20 @@ class AsyncFlowAccessApiImpl( errorMessage = "Failed to get collection by ID" ) + override fun getFullCollectionById(id: FlowId): CompletableFuture>> = + handleApiCall( + apiCall = { + api.getFullCollectionByID( + Access.GetFullCollectionByIDRequest + .newBuilder() + .setId(id.byteStringValue) + .build() + ) + }, + transform = { fullCollectionResponse -> fullCollectionResponse.transactionsList.map { FlowTransaction.of(it) } }, + errorMessage = "Failed to get full collection by ID" + ) + override fun sendTransaction(transaction: FlowTransaction): CompletableFuture> = handleApiCall( apiCall = { diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt index 75ef414..6f8fd2b 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt @@ -233,6 +233,19 @@ class FlowAccessApiImpl( FlowAccessApi.AccessApiCallResponse.Error("Failed to get collection by ID", e) } + override fun getFullCollectionById(id: FlowId): FlowAccessApi.AccessApiCallResponse> = + try { + val ret = api.getFullCollectionByID( + Access.GetFullCollectionByIDRequest + .newBuilder() + .setId(id.byteStringValue) + .build() + ) + FlowAccessApi.AccessApiCallResponse.Success(ret.transactionsList.map { FlowTransaction.of(it) }) + } catch (e: Exception) { + FlowAccessApi.AccessApiCallResponse.Error("Failed to get full collection by ID", e) + } + override fun sendTransaction(transaction: FlowTransaction): FlowAccessApi.AccessApiCallResponse = try { val ret = api.sendTransaction( diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt index 981b406..eed91b7 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt @@ -1295,6 +1295,24 @@ data class FlowCollection( .addAllTransactionIds(transactionIds.map { it.byteStringValue }) } +data class FlowFullCollection( + val id: FlowId, + val transactionIds: List +) : Serializable { + companion object { + @JvmStatic + fun of(value: CollectionOuterClass.Collection) = FlowCollection( + id = FlowId.of(value.id.toByteArray()), + transactionIds = value.transactionIdsList.map { FlowId.of(it.toByteArray()) } + ) + } + + @JvmOverloads + fun builder(builder: CollectionOuterClass.Collection.Builder = CollectionOuterClass.Collection.newBuilder()): CollectionOuterClass.Collection.Builder = builder + .setId(id.byteStringValue) + .addAllTransactionIds(transactionIds.map { it.byteStringValue }) +} + interface BytesHolder { val bytes: ByteArray val base16Value: String get() = bytes.bytesToHex() From f3b5b55114c4cabec3043299d0f633c3fef59f56 Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Mon, 4 Nov 2024 18:39:25 +0900 Subject: [PATCH 7/9] Working on examples --- java-example/README.md | 3 +++ .../GetCollectionAccessAPIConnector.java | 13 +++++++++++++ .../GetCollectionAccessAPIConnectorTest.java | 14 ++++++++++++++ kotlin-example/README.md | 3 +++ .../GetCollectionAccessAPIConnector.kt | 6 ++++++ .../GetCollectionAccessAPIConnectorTest.kt | 17 +++++++++++++---- 6 files changed, 52 insertions(+), 4 deletions(-) diff --git a/java-example/README.md b/java-example/README.md index 44d7785..f615dee 100644 --- a/java-example/README.md +++ b/java-example/README.md @@ -70,6 +70,9 @@ Below is a list of all Java code examples currently supported in this repo: [Get collections by ID.](src/main/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnector.java) +- Get collection by id +- Get full collection by id (returns all transactions in collection response) + #### Get Execution Data [Get execution data by block ID.](src/main/java/org/onflow/examples/java/getExecutionData/GetExecutionDataAccessAPIConnector.java) diff --git a/java-example/src/main/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnector.java b/java-example/src/main/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnector.java index 318d76b..5c29ebb 100644 --- a/java-example/src/main/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnector.java +++ b/java-example/src/main/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnector.java @@ -4,6 +4,9 @@ import org.onflow.flow.sdk.FlowAccessApi.AccessApiCallResponse; import org.onflow.flow.sdk.FlowCollection; import org.onflow.flow.sdk.FlowId; +import org.onflow.flow.sdk.FlowTransaction; + +import java.util.List; public class GetCollectionAccessAPIConnector { private final FlowAccessApi accessAPI; @@ -21,4 +24,14 @@ public FlowCollection getCollectionById(FlowId collectionId) { throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable()); } } + + public List getFullCollectionById(FlowId collectionId) { + AccessApiCallResponse> response = accessAPI.getFullCollectionById(collectionId); + if (response instanceof AccessApiCallResponse.Success) { + return ((AccessApiCallResponse.Success>) response).getData(); + } else { + AccessApiCallResponse.Error errorResponse = (AccessApiCallResponse.Error) response; + throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable()); + } + } } diff --git a/java-example/src/test/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnectorTest.java b/java-example/src/test/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnectorTest.java index e844ba8..170eb9a 100644 --- a/java-example/src/test/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnectorTest.java +++ b/java-example/src/test/java/org/onflow/examples/java/getCollection/GetCollectionAccessAPIConnectorTest.java @@ -11,6 +11,8 @@ import org.onflow.flow.sdk.crypto.Crypto; import org.onflow.flow.sdk.crypto.PublicKey; +import java.util.List; + import static org.junit.jupiter.api.Assertions.*; @FlowEmulatorProjectTest(flowJsonLocation = "../flow/flow.json") @@ -51,4 +53,16 @@ public void canFetchCollectionById() { assertNotNull(collection, "Collection should not be null"); assertEquals(collectionId, collection.getId(), "Collection ID should match the fetched collection ID"); } + + @Test + public void canFetchFullCollectionById() { + List fullCollectionResponse = connector.getFullCollectionById(collectionId); + + assertNotNull(fullCollectionResponse, "Collection transactions should not be null"); + assertFalse(fullCollectionResponse.isEmpty(), "Collection transactions should not be empty"); + + FlowTransaction firstTransaction = fullCollectionResponse.get(0); + assertNotNull(firstTransaction.getId(), "Transaction ID should not be null"); + assertNotNull(firstTransaction.getScript(), "Transaction script should not be null"); + } } diff --git a/kotlin-example/README.md b/kotlin-example/README.md index ed1a977..a7d5436 100644 --- a/kotlin-example/README.md +++ b/kotlin-example/README.md @@ -71,6 +71,9 @@ Below is a list of all Kotlin code examples currently supported in this repo: [Get collections by ID.](src/main/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnector.kt) +- Get collection by id +- Get full collection by id (returns all transactions in collection response) + #### Get Execution Data [Get execution data by block ID.](src/main/kotlin/org/onflow/examples/kotlin/getExecutionData/GetExecutionDataAccessAPIConnector.kt) diff --git a/kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnector.kt b/kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnector.kt index 030c82e..fc86d18 100644 --- a/kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnector.kt +++ b/kotlin-example/src/main/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnector.kt @@ -11,4 +11,10 @@ class GetCollectionAccessAPIConnector( is AccessApiCallResponse.Success -> response.data is AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) } + + fun getFullCollectionById(collectionId: FlowId): List = + when (val response = accessAPI.getFullCollectionById(collectionId)) { + is AccessApiCallResponse.Success -> response.data + is AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable) + } } diff --git a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnectorTest.kt b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnectorTest.kt index 36a1e0b..53545f9 100644 --- a/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnectorTest.kt +++ b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getCollection/GetCollectionAccessAPIConnectorTest.kt @@ -8,10 +8,7 @@ import org.onflow.flow.common.test.FlowEmulatorProjectTest import org.onflow.flow.common.test.FlowServiceAccountCredentials import org.onflow.flow.common.test.FlowTestClient import org.onflow.flow.common.test.TestAccount -import org.onflow.flow.sdk.FlowAccessApi -import org.onflow.flow.sdk.FlowCollection -import org.onflow.flow.sdk.FlowId -import org.onflow.flow.sdk.SignatureAlgorithm +import org.onflow.flow.sdk.* import org.onflow.flow.sdk.crypto.Crypto @FlowEmulatorProjectTest(flowJsonLocation = "../flow/flow.json") @@ -53,4 +50,16 @@ class GetCollectionAccessAPIConnectorTest { assertNotNull(collection, "Collection should not be null") assertEquals(collectionId, collection.id, "Collection ID should match the fetched collection ID") } + + @Test + fun `Can fetch full collection by ID`() { + val collectionTransactions: List = connector.getFullCollectionById(collectionId) + + assertNotNull(collectionTransactions, "Collection transactions should not be null") + assertTrue(collectionTransactions.isNotEmpty(), "Collection transactions should not be empty") + + val firstTransaction = collectionTransactions.first() + assertNotNull(firstTransaction.id, "Transaction ID should not be null") + assertNotNull(firstTransaction.script, "Transaction script should not be null") + } } From e8d7a66798c8e898e5eca89c28d739fd62f091fb Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Mon, 4 Nov 2024 18:42:05 +0900 Subject: [PATCH 8/9] Working on examples --- .../main/kotlin/org/onflow/flow/sdk/models.kt | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt index eed91b7..981b406 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt @@ -1295,24 +1295,6 @@ data class FlowCollection( .addAllTransactionIds(transactionIds.map { it.byteStringValue }) } -data class FlowFullCollection( - val id: FlowId, - val transactionIds: List -) : Serializable { - companion object { - @JvmStatic - fun of(value: CollectionOuterClass.Collection) = FlowCollection( - id = FlowId.of(value.id.toByteArray()), - transactionIds = value.transactionIdsList.map { FlowId.of(it.toByteArray()) } - ) - } - - @JvmOverloads - fun builder(builder: CollectionOuterClass.Collection.Builder = CollectionOuterClass.Collection.newBuilder()): CollectionOuterClass.Collection.Builder = builder - .setId(id.byteStringValue) - .addAllTransactionIds(transactionIds.map { it.byteStringValue }) -} - interface BytesHolder { val bytes: ByteArray val base16Value: String get() = bytes.bytesToHex() From 1faecd965a622263f774578940673646798415c3 Mon Sep 17 00:00:00 2001 From: Lea Lobanov Date: Tue, 5 Nov 2024 12:31:24 +0900 Subject: [PATCH 9/9] Unit and integration tests --- .../org/onflow/flow/sdk/FlowAccessApiTest.kt | 12 ++++++++++++ .../flow/sdk/impl/AsyncFlowAccessApiImplTest.kt | 15 +++++++++++++++ .../onflow/flow/sdk/impl/FlowAccessApiImplTest.kt | 11 +++++++++++ 3 files changed, 38 insertions(+) diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt index ede75a6..422b1b2 100644 --- a/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt @@ -230,6 +230,18 @@ class FlowAccessApiTest { assertEquals(FlowAccessApi.AccessApiCallResponse.Success(flowCollection), result) } + @Test + fun `Test getFullCollectionById`() { + val flowAccessApi = mock(FlowAccessApi::class.java) + val flowId = FlowId("01") + val flowTransaction = FlowTransaction.of(TransactionOuterClass.Transaction.getDefaultInstance()) + `when`(flowAccessApi.getFullCollectionById(flowId)).thenReturn(FlowAccessApi.AccessApiCallResponse.Success(listOf(flowTransaction))) + + val result = flowAccessApi.getFullCollectionById(flowId) + + assertEquals(FlowAccessApi.AccessApiCallResponse.Success(listOf(flowTransaction)), result) + } + @Test fun `Test sendTransaction`() { val flowAccessApi = mock(FlowAccessApi::class.java) diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt index 0e8ce15..dd87bbb 100644 --- a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/AsyncFlowAccessApiImplTest.kt @@ -158,6 +158,11 @@ class AsyncFlowAccessApiImplTest { .setCollection(mockCollection.builder().build()) .build() + fun fullCollectionResponse(transactions: List) = Access.FullCollectionResponse + .newBuilder() + .addAllTransactions(transactions.map { it.builder().build() }) + .build() + fun executionResultResponse(mockExecutionResult: FlowExecutionResult) = Access.ExecutionResultByIDResponse .newBuilder() .setExecutionResult(mockExecutionResult.builder().build()) @@ -413,6 +418,16 @@ class AsyncFlowAccessApiImplTest { assertSuccess(result, mockCollection) } + @Test + fun `test getFullCollectionById`() { + val collectionId = FlowId("01") + val mockTransaction = FlowTransaction(FlowScript("script"), emptyList(), FlowId.of("01".toByteArray()), 123L, FlowTransactionProposalKey(FlowAddress("02"), 1, 123L), FlowAddress("02"), emptyList()) + `when`(api.getFullCollectionByID(any())).thenReturn(setupFutureMock(MockResponseFactory.fullCollectionResponse(listOf(mockTransaction)))) + + val result = asyncFlowAccessApi.getFullCollectionById(collectionId).get() + assertSuccess(result, listOf(mockTransaction)) + } + @Test fun `test sendTransaction`() { val mockTransaction = FlowTransaction(FlowScript("script"), emptyList(), FlowId.of("01".toByteArray()), 123L, FlowTransactionProposalKey(FlowAddress("02"), 1, 123L), FlowAddress("02"), emptyList()) diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt index 908653f..577c300 100644 --- a/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImplTest.kt @@ -339,6 +339,17 @@ class FlowAccessApiImplTest { assertResultSuccess(result) { assertEquals(mockCollection, it) } } + @Test + fun `Test getFullCollectionById`() { + val collectionId = FlowId("01") + val mockTransaction = createMockTransaction() + + `when`(mockApi.getFullCollectionByID(any())).thenReturn(AsyncFlowAccessApiImplTest.MockResponseFactory.fullCollectionResponse(listOf(mockTransaction))) + + val result = flowAccessApiImpl.getFullCollectionById(collectionId) + assertResultSuccess(result) { assertEquals(listOf(mockTransaction), it) } + } + @Test fun `Test sendTransaction`() { val mockTransaction = createMockTransaction()