Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get tx result by index endpoint #137

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions java-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ Below is a list of all Java code examples currently supported in this repo:

- Get transaction
- Get transaction result
- Get transaction result by index

#### Sending Transactions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,14 @@ public FlowTransactionResult getTransactionResult(FlowId txID) {
throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable());
}
}

public FlowTransactionResult getTransactionResultByIndex(FlowId blockId, Integer index) {
FlowAccessApi.AccessApiCallResponse<FlowTransactionResult> response = accessAPI.getTransactionResultByIndex(blockId, index);
if (response instanceof FlowAccessApi.AccessApiCallResponse.Success) {
return ((FlowAccessApi.AccessApiCallResponse.Success<FlowTransactionResult>) response).getData();
} else {
FlowAccessApi.AccessApiCallResponse.Error errorResponse = (FlowAccessApi.AccessApiCallResponse.Error) response;
throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,9 @@
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.FlowId;
import org.onflow.flow.sdk.FlowTransaction;
import org.onflow.flow.sdk.FlowTransactionResult;
import org.onflow.flow.sdk.FlowTransactionStatus;
import org.onflow.flow.sdk.*;
import org.onflow.flow.sdk.crypto.Crypto;
import org.onflow.flow.sdk.crypto.PublicKey;
import org.onflow.flow.sdk.SignatureAlgorithm;

import static org.junit.jupiter.api.Assertions.*;

Expand All @@ -26,6 +21,7 @@ public class GetTransactionAccessAPIConnectorTest {
private FlowAccessApi accessAPI;
private GetTransactionAccessAPIConnector connector;
private FlowId txID;
private FlowBlock block;

@BeforeEach
public void setup() {
Expand All @@ -38,6 +34,14 @@ public void setup() {
serviceAccount.getFlowAddress(),
publicKey
);

FlowAccessApi.AccessApiCallResponse<FlowBlock> response = accessAPI.getLatestBlock(true, false);
if (response instanceof FlowAccessApi.AccessApiCallResponse.Success) {
block = ((FlowAccessApi.AccessApiCallResponse.Success<FlowBlock>) response).getData();
} else {
FlowAccessApi.AccessApiCallResponse.Error errorResponse = (FlowAccessApi.AccessApiCallResponse.Error) response;
throw new RuntimeException(errorResponse.getMessage(), errorResponse.getThrowable());
}
}

@Test
Expand All @@ -55,4 +59,12 @@ public void canFetchTransactionResult() {
assertNotNull(transactionResult, "Transaction result should not be null");
assertSame(transactionResult.getStatus(), FlowTransactionStatus.SEALED, "Transaction should be sealed");
}

@Test
public void canFetchTransactionResultByIndex() {
FlowTransactionResult transactionResult = connector.getTransactionResultByIndex(block.getId(),0);

assertNotNull(transactionResult, "Transaction result should not be null");
assertSame(transactionResult.getStatus(), FlowTransactionStatus.SEALED, "Transaction should be sealed");
}
}
1 change: 1 addition & 0 deletions kotlin-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Below is a list of all Kotlin code examples currently supported in this repo:

- Get transaction
- Get transaction result
- Get transaction result by index

#### Sending Transactions

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ class GetTransactionAccessAPIConnector(
is FlowAccessApi.AccessApiCallResponse.Success -> response.data
is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable)
}

fun getTransactionResultByIndex(blockId: FlowId, index: Int): FlowTransactionResult =
when (val response = accessAPI.getTransactionResultByIndex(blockId, index)) {
is FlowAccessApi.AccessApiCallResponse.Success -> response.data
is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class GetTransactionAccessAPIConnectorTest {
lateinit var accessAPI: FlowAccessApi

private lateinit var connector: GetTransactionAccessAPIConnector
private lateinit var block: FlowBlock
private lateinit var accessAPIConnector: AccessAPIConnector

private lateinit var txID: FlowId
Expand All @@ -35,6 +36,11 @@ internal class GetTransactionAccessAPIConnectorTest {
serviceAccount.flowAddress,
publicKey
)

block = when (val response = accessAPI.getLatestBlock()) {
is FlowAccessApi.AccessApiCallResponse.Success -> response.data
is FlowAccessApi.AccessApiCallResponse.Error -> throw Exception(response.message, response.throwable)
}
}

@Test
Expand All @@ -52,4 +58,12 @@ internal class GetTransactionAccessAPIConnectorTest {
assertNotNull(transactionResult, "Transaction result should not be null")
assertTrue(transactionResult.status === FlowTransactionStatus.SEALED, "Transaction should be sealed")
}

@Test
fun `Can fetch a transaction result by index`() {
val transactionResult = connector.getTransactionResultByIndex(block.id, 0)

assertNotNull(transactionResult, "Transaction result should not be null")
assertTrue(transactionResult.status === FlowTransactionStatus.SEALED, "Transaction should be sealed")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,58 @@ class TransactionIntegrationTest {
}

@Test
fun `Can parse events`() {
fun `Can get transaction results`() {
val txResult = createAndSubmitAccountCreationTransaction(
accessAPI,
serviceAccount,
"cadence/transaction_creation/transaction_creation_simple_transaction.cdc"
)
assertThat(txResult).isNotNull
assertThat(txResult.status).isEqualTo(FlowTransactionStatus.SEALED)

val latestBlock = try {
handleResult(
accessAPI.getLatestBlock(true),
"Failed to get latest block"
)
} catch (e: Exception) {
fail("Failed to retrieve latest block: ${e.message}")
}

val txResultById = try {
handleResult(
accessAPI.getTransactionResultById(txResult.transactionId),
"Failed to get tx result by id"
)
} catch (e: Exception) {
fail("Failed to retrieve tx result by id: ${e.message}")
}

assertThat(txResultById).isNotNull
assertThat(txResultById.status).isEqualTo(FlowTransactionStatus.SEALED)
assertThat(txResultById.transactionId).isEqualTo(txResult.transactionId)

val txResultByIndex = try {
handleResult(
accessAPI.getTransactionResultByIndex(latestBlock.id, 0),
"Failed to get tx result by index"
)
} catch (e: Exception) {
fail("Failed to retrieve tx result by index: ${e.message}")
}

assertThat(txResultByIndex).isNotNull
assertThat(txResultByIndex.status).isEqualTo(FlowTransactionStatus.SEALED)
assertThat(txResultByIndex.transactionId).isEqualTo(txResultByIndex.transactionId)
}

@Test
fun `Can parse events`() {
val txResult = createAndSubmitAccountCreationTransaction(
accessAPI,
serviceAccount,
"cadence/transaction_creation/transaction_creation_simple_transaction.cdc"
)
assertThat(txResult).isNotNull
assertThat(txResult.status).isEqualTo(FlowTransactionStatus.SEALED)

Expand Down
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 @@ -38,6 +38,8 @@ interface AsyncFlowAccessApi {

fun getTransactionResultById(id: FlowId): CompletableFuture<FlowAccessApi.AccessApiCallResponse<FlowTransactionResult?>>

fun getTransactionResultByIndex(blockId: FlowId, index: Int): CompletableFuture<FlowAccessApi.AccessApiCallResponse<FlowTransactionResult>>

@Deprecated(
message = "Behaves identically to getAccountAtLatestBlock",
replaceWith = ReplaceWith("getAccountAtLatestBlock")
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 @@ -50,6 +50,8 @@ interface FlowAccessApi {

fun getTransactionResultById(id: FlowId): AccessApiCallResponse<FlowTransactionResult>

fun getTransactionResultByIndex(blockId: FlowId, index: Int): AccessApiCallResponse<FlowTransactionResult>

@Deprecated(
message = "Behaves identically to getAccountAtLatestBlock",
replaceWith = ReplaceWith("getAccountAtLatestBlock")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,32 @@ class AsyncFlowAccessApiImpl(
}
}

override fun getTransactionResultByIndex(blockId: FlowId, index: Int): CompletableFuture<FlowAccessApi.AccessApiCallResponse<FlowTransactionResult>> {
return try {
completableFuture(
try {
api.getTransactionResultByIndex(
Access.GetTransactionByIndexRequest
.newBuilder()
.setBlockId(blockId.byteStringValue)
.setIndex(index)
.build()
)
} catch (e: Exception) {
return CompletableFuture.completedFuture(FlowAccessApi.AccessApiCallResponse.Error("Failed to get transaction result by index", e))
}
).handle { response, ex ->
if (ex != null) {
FlowAccessApi.AccessApiCallResponse.Error("Failed to get transaction result by index", ex)
} else {
FlowAccessApi.AccessApiCallResponse.Success(FlowTransactionResult.of(response))
}
}
} catch (e: Exception) {
CompletableFuture.completedFuture(FlowAccessApi.AccessApiCallResponse.Error("Failed to get transaction result by index", e))
}
}

@Deprecated("Behaves identically to getAccountAtLatestBlock", replaceWith = ReplaceWith("getAccountAtLatestBlock"))
override fun getAccountByAddress(addresss: FlowAddress): CompletableFuture<FlowAccessApi.AccessApiCallResponse<FlowAccount>> {
return try {
Expand Down
14 changes: 14 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 @@ -276,6 +276,20 @@ class FlowAccessApiImpl(
FlowAccessApi.AccessApiCallResponse.Error("Failed to get transaction result by ID", e)
}

override fun getTransactionResultByIndex(blockId: FlowId, index: Int): FlowAccessApi.AccessApiCallResponse<FlowTransactionResult> =
try {
val ret = api.getTransactionResultByIndex(
Access.GetTransactionByIndexRequest
.newBuilder()
.setBlockId(blockId.byteStringValue)
.setIndex(index)
.build()
)
FlowAccessApi.AccessApiCallResponse.Success(FlowTransactionResult.of(ret))
} catch (e: Exception) {
FlowAccessApi.AccessApiCallResponse.Error("Failed to get transaction result by index", e)
}

@Deprecated("Behaves identically to getAccountAtLatestBlock", replaceWith = ReplaceWith("getAccountAtLatestBlock"))
override fun getAccountByAddress(addresss: FlowAddress): FlowAccessApi.AccessApiCallResponse<FlowAccount> =
try {
Expand Down
14 changes: 14 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 @@ -264,6 +264,20 @@ class FlowAccessApiTest {
assertEquals(FlowAccessApi.AccessApiCallResponse.Success(flowTransactionResult), result)
}

@Test
fun `Test getTransactionResultByIndex`() {
val flowAccessApi = mock(FlowAccessApi::class.java)
val flowId = FlowId("01")
val index = 0

val flowTransactionResult = FlowTransactionResult.of(Access.TransactionResultResponse.getDefaultInstance())
`when`(flowAccessApi.getTransactionResultByIndex(flowId, index)).thenReturn(FlowAccessApi.AccessApiCallResponse.Success(flowTransactionResult))

val result = flowAccessApi.getTransactionResultByIndex(flowId, index)

assertEquals(FlowAccessApi.AccessApiCallResponse.Success(flowTransactionResult), result)
}

@Test
fun `Test getAccountAtLatestBlock`() {
val flowAccessApi = mock(FlowAccessApi::class.java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ class AsyncFlowAccessApiImplTest {
),
parentView = 1L
)

val mockTransactionResultResponse = Access.TransactionResultResponse
.newBuilder()
.setStatus(TransactionOuterClass.TransactionStatus.SEALED)
.setStatusCode(1)
.setErrorMessage("message")
.setBlockId(ByteString.copyFromUtf8("id"))
.setBlockHeight(1L)
.setTransactionId(ByteString.copyFromUtf8("id"))
.setCollectionId(ByteString.copyFromUtf8("id"))
.setComputationUsage(1L)
.build()
}

private fun <T> setupFutureMock(response: T): ListenableFuture<T> {
Expand Down Expand Up @@ -461,17 +473,7 @@ class AsyncFlowAccessApiImplTest {
val flowId = FlowId.of("id".toByteArray())
val flowTransactionResult = FlowTransactionResult(FlowTransactionStatus.SEALED, 1, "message", emptyList(), flowId, 1L, flowId, flowId, 1L)

val transactionResultResponse = Access.TransactionResultResponse
.newBuilder()
.setStatus(TransactionOuterClass.TransactionStatus.SEALED)
.setStatusCode(1)
.setErrorMessage("message")
.setBlockId(ByteString.copyFromUtf8("id"))
.setBlockHeight(1L)
.setTransactionId(ByteString.copyFromUtf8("id"))
.setCollectionId(ByteString.copyFromUtf8("id"))
.setComputationUsage(1L)
.build()
val transactionResultResponse = mockTransactionResultResponse

`when`(api.getTransactionResult(any())).thenReturn(setupFutureMock(transactionResultResponse))

Expand All @@ -481,6 +483,37 @@ class AsyncFlowAccessApiImplTest {
assertEquals(flowTransactionResult, result.data)
}

@Test
fun `test getTransactionResultByIndex success`() {
val index = 0
val flowId = FlowId.of("id".toByteArray())
val flowTransactionResult = FlowTransactionResult(FlowTransactionStatus.SEALED, 1, "message", emptyList(), flowId, 1L, flowId, flowId, 1L)

val transactionResultResponse = mockTransactionResultResponse

`when`(api.getTransactionResultByIndex(any())).thenReturn(setupFutureMock(transactionResultResponse))

val result = asyncFlowAccessApi.getTransactionResultByIndex(flowId, index).get()
assert(result is FlowAccessApi.AccessApiCallResponse.Success)
result as FlowAccessApi.AccessApiCallResponse.Success
assertEquals(flowTransactionResult, result.data)
}

@Test
fun `test getTransactionResultByIndex failure`() {
val index = 0
val flowId = FlowId.of("id".toByteArray())
val exception = RuntimeException("Test exception")

`when`(api.getTransactionResultByIndex(any())).thenThrow(exception)

val result = asyncFlowAccessApi.getTransactionResultByIndex(flowId, index).get()
assert(result is FlowAccessApi.AccessApiCallResponse.Error)
result as FlowAccessApi.AccessApiCallResponse.Error
assertEquals("Failed to get transaction result by index", result.message)
assertEquals(exception, result.throwable)
}

@Test
fun `test getAccountByAddress`() {
val flowAddress = FlowAddress("01")
Expand Down
Loading
Loading