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/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/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/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()); + } + } +} 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/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/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") + } } 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 95% 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..9759f75 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 @@ -9,7 +9,7 @@ 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..f59b6aa --- /dev/null +++ b/kotlin-example/src/test/kotlin/org/onflow/examples/kotlin/getProtocolState/GetProtocolStateAccessAPIConnectorTest.kt @@ -0,0 +1,52 @@ +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")) + } +} 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( 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..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> @@ -64,6 +66,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..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 @@ -76,6 +78,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..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 = { @@ -452,6 +466,34 @@ 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..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( @@ -441,6 +454,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..422b1b2 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 @@ -228,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) @@ -392,6 +406,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..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()) @@ -593,6 +608,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..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() @@ -577,6 +588,40 @@ 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()