Skip to content

Commit

Permalink
Merge pull request #144 from onflow/refactor-code-duplication
Browse files Browse the repository at this point in the history
#114  Streaming endpoints code duplication, general refactoring
  • Loading branch information
franklywatson authored Nov 21, 2024
2 parents 99f39fc + b5c808e commit e697552
Show file tree
Hide file tree
Showing 7 changed files with 496 additions and 620 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package org.onflow.examples.kotlin.getAccountBalance
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.onflow.examples.kotlin.getTransaction.GetTransactionAccessAPIConnectorTest
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.FlowBlock

@FlowEmulatorProjectTest(flowJsonLocation = "../flow/flow.json")
internal class GetAccountBalanceAccessAPIConnectorTest {
Expand All @@ -18,10 +20,12 @@ internal class GetAccountBalanceAccessAPIConnectorTest {
lateinit var accessAPI: FlowAccessApi

private lateinit var balanceAPIConnector: GetAccountBalanceAccessAPIConnector
private lateinit var latestBlock: FlowBlock

@BeforeEach
fun setup() {
balanceAPIConnector = GetAccountBalanceAccessAPIConnector(accessAPI)
latestBlock = GetTransactionAccessAPIConnectorTest.fetchLatestBlockWithRetries(accessAPI)
}

@Test
Expand All @@ -36,17 +40,10 @@ internal class GetAccountBalanceAccessAPIConnectorTest {
@Test
fun `Can fetch account balance at a specific block height`() {
val address = serviceAccount.flowAddress
val latestBlock = accessAPI.getLatestBlock(true) // Fetch the latest sealed block
val balanceAtHeight = balanceAPIConnector.getBalanceAtBlockHeight(address, latestBlock.height)

when (latestBlock) {
is FlowAccessApi.AccessApiCallResponse.Success -> {
val balanceAtHeight = balanceAPIConnector.getBalanceAtBlockHeight(address, latestBlock.data.height)

Assertions.assertNotNull(balanceAtHeight, "Balance at specific block height should not be null")
Assertions.assertTrue(balanceAtHeight >= 0, "Balance at specific block height should be non-negative")
}
is FlowAccessApi.AccessApiCallResponse.Error -> Assertions.fail("Failed to retrieve the latest block: ${latestBlock.message}")
}
Assertions.assertNotNull(balanceAtHeight, "Balance at specific block height should not be null")
Assertions.assertTrue(balanceAtHeight >= 0, "Balance at specific block height should be non-negative")
}

@Test
Expand All @@ -56,18 +53,11 @@ internal class GetAccountBalanceAccessAPIConnectorTest {
// Fetch balance at latest block
val balanceAtLatest = balanceAPIConnector.getBalanceAtLatestBlock(address)

// Fetch latest block height
val latestBlock = accessAPI.getLatestBlock(true)
when (latestBlock) {
is FlowAccessApi.AccessApiCallResponse.Success -> {
val blockHeight = latestBlock.data.height
val blockHeight = latestBlock.height

// Fetch balance at the same block height
val balanceAtHeight = balanceAPIConnector.getBalanceAtBlockHeight(address, blockHeight)
// Fetch balance at the same block height
val balanceAtHeight = balanceAPIConnector.getBalanceAtBlockHeight(address, blockHeight)

Assertions.assertEquals(balanceAtLatest, balanceAtHeight, "Balance at latest block and specific block height should match")
}
is FlowAccessApi.AccessApiCallResponse.Error -> Assertions.fail("Failed to retrieve the latest block: ${latestBlock.message}")
}
Assertions.assertEquals(balanceAtLatest, balanceAtHeight, "Balance at latest block and specific block height should match")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.onflow.examples.kotlin.AccessAPIConnector
import org.onflow.examples.kotlin.getTransaction.GetTransactionAccessAPIConnectorTest
import org.onflow.flow.common.test.FlowEmulatorProjectTest
import org.onflow.flow.common.test.FlowServiceAccountCredentials
import org.onflow.flow.common.test.FlowTestClient
Expand All @@ -23,6 +24,7 @@ class GetCollectionAccessAPIConnectorTest {
private lateinit var accessAPIConnector: AccessAPIConnector

private lateinit var collectionId: FlowId
lateinit var block: FlowBlock

@BeforeEach
fun setup() {
Expand All @@ -36,10 +38,7 @@ class GetCollectionAccessAPIConnectorTest {
publicKey
)

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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.examples.kotlin.getTransaction.GetTransactionAccessAPIConnectorTest
import org.onflow.flow.common.test.FlowEmulatorProjectTest
import org.onflow.flow.common.test.FlowTestClient
import org.onflow.flow.sdk.FlowAccessApi
Expand All @@ -20,6 +21,7 @@ internal class GetProtocolStateAccessAPIConnectorTest {
@BeforeEach
fun setup() {
protocolStateConnector = GetProtocolStateAccessAPIConnector(accessAPI)
block = GetTransactionAccessAPIConnectorTest.fetchLatestBlockWithRetries(accessAPI)
}

@Test
Expand All @@ -30,22 +32,12 @@ 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)
}

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"))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.onflow.examples.kotlin.getTransaction

import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -37,10 +39,7 @@ internal class GetTransactionAccessAPIConnectorTest {
publicKey
)

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

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

companion object {
fun fetchLatestBlockWithRetries(accessAPI: FlowAccessApi, retries: Int = 5, delayMillis: Long = 500): FlowBlock {
repeat(retries) { attempt ->
when (val response = accessAPI.getLatestBlock()) {
is FlowAccessApi.AccessApiCallResponse.Success -> return response.data
is FlowAccessApi.AccessApiCallResponse.Error -> {
println("Attempt ${attempt + 1} failed: ${response.message}. Retrying...")
runBlocking { delay(delayMillis) }
}
}
}
throw Exception("Failed to retrieve the latest block after $retries attempts.")
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.onflow.flow.sdk.transaction

import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.onflow.flow.sdk.*
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
Expand Down Expand Up @@ -43,8 +45,22 @@ class TransactionIntegrationTest {
fail("$errorMessage: ${e.message}")
}

private fun getLatestBlock(): FlowBlock =
safelyHandle({ Result.success(handleResult(accessAPI.getLatestBlock(true), LATEST_BLOCK_ERROR)) }, LATEST_BLOCK_ERROR)
private fun getLatestBlock(retries: Int = 5, delayMillis: Long = 500): FlowBlock {
repeat(retries) { attempt ->
try {
return safelyHandle(
{ Result.success(handleResult(accessAPI.getLatestBlock(true), LATEST_BLOCK_ERROR)) },
LATEST_BLOCK_ERROR
)
} catch (e: Exception) {
if (attempt == retries - 1) {
throw Exception("$LATEST_BLOCK_ERROR after $retries attempts", e)
}
runBlocking { delay(delayMillis) }
}
}
throw Exception(LATEST_BLOCK_ERROR)
}

private fun getAccountAtLatestBlock(address: FlowAddress): FlowAccount =
safelyHandle({ Result.success(handleResult(accessAPI.getAccountAtLatestBlock(address), ACCOUNT_ERROR)) }, ACCOUNT_ERROR)
Expand Down
Loading

0 comments on commit e697552

Please sign in to comment.