Skip to content

Commit

Permalink
Merge pull request #142 from onflow/get-collection-by-id-endpoints
Browse files Browse the repository at this point in the history
Setup get collection endpoint
  • Loading branch information
franklywatson authored Nov 7, 2024
2 parents 223945b + 1faecd9 commit 75cdb79
Show file tree
Hide file tree
Showing 13 changed files with 121 additions and 4 deletions.
3 changes: 3 additions & 0 deletions java-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -21,4 +24,14 @@ public FlowCollection getCollectionById(FlowId collectionId) {
throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable());
}
}

public List<FlowTransaction> getFullCollectionById(FlowId collectionId) {
AccessApiCallResponse<List<FlowTransaction>> response = accessAPI.getFullCollectionById(collectionId);
if (response instanceof AccessApiCallResponse.Success) {
return ((AccessApiCallResponse.Success<List<FlowTransaction>>) response).getData();
} else {
AccessApiCallResponse.Error errorResponse = (AccessApiCallResponse.Error) response;
throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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<FlowTransaction> 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");
}
}
3 changes: 3 additions & 0 deletions kotlin-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<FlowTransaction> =
when (val response = accessAPI.getFullCollectionById(collectionId)) {
is AccessApiCallResponse.Success -> response.data
is AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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<FlowTransaction> = 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")
}
}
2 changes: 2 additions & 0 deletions sdk/src/main/kotlin/org/onflow/flow/sdk/AsyncFlowAccessApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ interface AsyncFlowAccessApi {

fun getCollectionById(id: FlowId): CompletableFuture<FlowAccessApi.AccessApiCallResponse<FlowCollection?>>

fun getFullCollectionById(id: FlowId): CompletableFuture<FlowAccessApi.AccessApiCallResponse<List<FlowTransaction>>>

fun sendTransaction(transaction: FlowTransaction): CompletableFuture<FlowAccessApi.AccessApiCallResponse<FlowId>>

fun getTransactionById(id: FlowId): CompletableFuture<FlowAccessApi.AccessApiCallResponse<FlowTransaction?>>
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/main/kotlin/org/onflow/flow/sdk/FlowAccessApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ interface FlowAccessApi {

fun getCollectionById(id: FlowId): AccessApiCallResponse<FlowCollection>

fun getFullCollectionById(id: FlowId): AccessApiCallResponse<List<FlowTransaction>>

fun sendTransaction(transaction: FlowTransaction): AccessApiCallResponse<FlowId>

fun getTransactionById(id: FlowId): AccessApiCallResponse<FlowTransaction>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,20 @@ class AsyncFlowAccessApiImpl(
errorMessage = "Failed to get collection by ID"
)

override fun getFullCollectionById(id: FlowId): CompletableFuture<FlowAccessApi.AccessApiCallResponse<List<FlowTransaction>>> =
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<FlowAccessApi.AccessApiCallResponse<FlowId>> =
handleApiCall(
apiCall = {
Expand Down
13 changes: 13 additions & 0 deletions sdk/src/main/kotlin/org/onflow/flow/sdk/impl/FlowAccessApiImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ class FlowAccessApiImpl(
FlowAccessApi.AccessApiCallResponse.Error("Failed to get collection by ID", e)
}

override fun getFullCollectionById(id: FlowId): FlowAccessApi.AccessApiCallResponse<List<FlowTransaction>> =
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<FlowId> =
try {
val ret = api.sendTransaction(
Expand Down
12 changes: 12 additions & 0 deletions sdk/src/test/kotlin/org/onflow/flow/sdk/FlowAccessApiTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ class AsyncFlowAccessApiImplTest {
.setCollection(mockCollection.builder().build())
.build()

fun fullCollectionResponse(transactions: List<FlowTransaction>) = Access.FullCollectionResponse
.newBuilder()
.addAllTransactions(transactions.map { it.builder().build() })
.build()

fun executionResultResponse(mockExecutionResult: FlowExecutionResult) = Access.ExecutionResultByIDResponse
.newBuilder()
.setExecutionResult(mockExecutionResult.builder().build())
Expand Down Expand Up @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit 75cdb79

Please sign in to comment.