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

Fix tx details request #525

Merged
merged 7 commits into from
Jul 10, 2024
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* Updated Prov Protos to 1.19.0-rc2 [#522](https://github.com/provenance-io/explorer-service/pull/522)
* Updated gRPC query to use `query` field instead of `events` field [#523](https://github.com/provenance-io/explorer-service/pull/523)
* Fixed transaction details endpoint by handling Base64 and string encoding changes [#525](https://github.com/provenance-io/explorer-service/pull/525)

### Bug Fixes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ fun String.toByteString() = ByteString.copyFromUtf8(this)
fun ByteArray.toByteString() = ByteString.copyFrom(this)
fun ByteString.toBase64() = Base64.getEncoder().encodeToString(this.toByteArray())
fun String.fromBase64() = Base64.getDecoder().decode(this).decodeToString()

fun String.tryFromBase64(): String {
return if (isBase64(this)) {
try {
Base64.getDecoder().decode(this).decodeToString()
} catch (e: IllegalArgumentException) {
this
}
} else {
this
}
}

private fun isBase64(str: String): Boolean {
if (str.length % 4 != 0) return false
return str.matches(Regex("^[A-Za-z0-9+/=]+\$"))
}
fun String.fromBase64ToMAddress() = Base64.getDecoder().decode(this).toByteString().toMAddress()
fun String.toBase64() = Base64.getEncoder().encodeToString(this.toByteArray())
fun ByteArray.base64EncodeString(): String = String(Base64.getEncoder().encode(this))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ fun List<Types.Event>.txEventsToObjectNodePrint(protoPrinter: JsonFormat.Printer
val newArray = JSON_NODE_FACTORY.arrayNode()
oldArray.forEach {
val newNode = JSON_NODE_FACTORY.objectNode()
val newKey = it.get("key").asText().fromBase64()
val newValue = it.get("value")?.asText()?.fromBase64()
val newKey = it.get("key").asText().tryFromBase64()
val newValue = it.get("value")?.asText()?.tryFromBase64()
newNode.put("key", newKey)
newNode.put("value", newValue)
newArray.add(newNode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,25 @@ class TransactionService(
.ifEmpty { throw ResourceNotFoundException("Invalid transaction hash: '$txnHash'") }
.getMainState(blockHeight).txV2.let { protoPrinter.print(it) }

fun getTransactionByHash(hash: String, blockHeight: Int? = null) =
getTxByHash(hash)
.ifEmpty { throw ResourceNotFoundException("Invalid transaction hash: '$hash'") }
.let { list ->
val state = list.getMainState(blockHeight)

hydrateTxDetails(state)
.apply { this.additionalHeights = list.filterNot { it.height == state.height }.map { it.height } }
}
fun getTransactionByHash(hash: String, blockHeight: Int? = null): TxDetails {
logger.info("Fetching transaction for hash: $hash with blockHeight: $blockHeight")
return try {
getTxByHash(hash)
.ifEmpty {
throw ResourceNotFoundException("Invalid transaction hash: '$hash'")
}
.let { list ->
val state = list.getMainState(blockHeight)
hydrateTxDetails(state)
.apply {
this.additionalHeights = list.filterNot { it.height == state.height }.map { it.height }
}
}
} catch (e: Exception) {
logger.error("Error fetching transaction for hash: $hash", e)
throw e
}
}

private fun hydrateTxDetails(tx: TxCacheRecord) = transaction {
TxDetails(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,23 @@ class ExtensionsKtTest {
assertEquals("{\"marker\":{\"transfer-auths\":[\"tp19zf8q9swrsspkdljumwh04zjac4nkfvju6ehl9\",\"tp1tk6fqws0su7fzp090edrauaa756mdyjfdw0507\",\"tp1a53udazy8ayufvy0s434pfwjcedzqv34vfvvyc\"],\"allow-force-transfer\":false}}", actualJsonObj.get("memo").asText(), testname)
}
}

@Test
fun `test tryFromBase64 with various cases`() {
val base64String = "SGVsbG8gd29ybGQ="
val expectedDecodedString = "Hello world"
assertEquals(expectedDecodedString, base64String.tryFromBase64(), "Valid Base64 string should decode to 'Hello world'")

val invalidBase64String = "Hello world"
val expectedInvalidOutput = invalidBase64String
assertEquals(expectedInvalidOutput, invalidBase64String.tryFromBase64(), "Invalid Base64 string should return the original string")

val emptyString = ""
val expectedEmptyOutput = emptyString
assertEquals(expectedEmptyOutput, emptyString.tryFromBase64(), "Empty string should return the original string")

val malformedBase64String = "SGVsbG8gd29ybGQ"
val expectedMalformedOutput = malformedBase64String
assertEquals(expectedMalformedOutput, malformedBase64String.tryFromBase64(), "Malformed Base64 string should return the original string")
}
}
Loading