diff --git a/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt b/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt index 5e6a0b6..3e18c80 100644 --- a/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt +++ b/sdk/src/main/kotlin/org/onflow/flow/sdk/models.kt @@ -1201,27 +1201,80 @@ data class FlowCollectionGuarantee( } data class FlowBlockSeal( - val id: FlowId, + val blockId: FlowId, val executionReceiptId: FlowId, val executionReceiptSignatures: List, - val resultApprovalSignatures: List + val resultApprovalSignatures: List, + val finalState: ByteArray, + val resultId: FlowId, + val aggregatedApprovalSigs: List, ) : Serializable { companion object { @JvmStatic fun of(value: BlockSealOuterClass.BlockSeal) = FlowBlockSeal( - id = FlowId.of(value.blockId.toByteArray()), + blockId = FlowId.of(value.blockId.toByteArray()), executionReceiptId = FlowId.of(value.executionReceiptId.toByteArray()), executionReceiptSignatures = value.executionReceiptSignaturesList.map { FlowSignature(it.toByteArray()) }, - resultApprovalSignatures = value.executionReceiptSignaturesList.map { FlowSignature(it.toByteArray()) } + resultApprovalSignatures = value.resultApprovalSignaturesList.map { FlowSignature(it.toByteArray()) }, + finalState = value.finalState.toByteArray(), + resultId = FlowId.of(value.resultId.toByteArray()), + aggregatedApprovalSigs = value.aggregatedApprovalSigsList.map { FlowAggregatedSignature.of(it) }, ) } @JvmOverloads fun builder(builder: BlockSealOuterClass.BlockSeal.Builder = BlockSealOuterClass.BlockSeal.newBuilder()): BlockSealOuterClass.BlockSeal.Builder = builder - .setBlockId(id.byteStringValue) + .setBlockId(blockId.byteStringValue) .setExecutionReceiptId(executionReceiptId.byteStringValue) .addAllExecutionReceiptSignatures(executionReceiptSignatures.map { it.byteStringValue }) .addAllResultApprovalSignatures(resultApprovalSignatures.map { it.byteStringValue }) + .setFinalState(UnsafeByteOperations.unsafeWrap(finalState)) + .setResultId(resultId.byteStringValue) + .addAllAggregatedApprovalSigs(aggregatedApprovalSigs.map { it.builder().build() }) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is FlowBlockSeal) return false + + if (blockId != other.blockId) return false + if (executionReceiptId != other.executionReceiptId) return false + if (executionReceiptSignatures != other.executionReceiptSignatures) return false + if (resultApprovalSignatures != other.resultApprovalSignatures) return false + if (!finalState.contentEquals(other.finalState)) return false + if (resultId != other.resultId) return false + if (aggregatedApprovalSigs != other.aggregatedApprovalSigs) return false + + return true + } + + override fun hashCode(): Int { + var result = blockId.hashCode() + result = 31 * result + executionReceiptId.hashCode() + result = 31 * result + executionReceiptSignatures.hashCode() + result = 31 * result + resultApprovalSignatures.hashCode() + result = 31 * result + finalState.contentHashCode() + result = 31 * result + resultId.hashCode() + result = 31 * result + aggregatedApprovalSigs.hashCode() + return result + } +} + +data class FlowAggregatedSignature( + val verifierSignatures: List, + val signerIds: List, +) : Serializable { + companion object { + @JvmStatic + fun of(value: BlockSealOuterClass.AggregatedSignature) = FlowAggregatedSignature( + verifierSignatures = value.verifierSignaturesList.map { FlowSignature(it.toByteArray()) }, + signerIds = value.signerIdsList.map { FlowId.of(it.toByteArray()) } + ) + } + + @JvmOverloads + fun builder(builder: BlockSealOuterClass.AggregatedSignature.Builder = BlockSealOuterClass.AggregatedSignature.newBuilder()): BlockSealOuterClass.AggregatedSignature.Builder = builder + .addAllVerifierSignatures(verifierSignatures.map { it.byteStringValue }) + .addAllSignerIds(signerIds.map { it.byteStringValue }) } data class FlowCollection( diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/models/FlowAggregatedSignatureTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/models/FlowAggregatedSignatureTest.kt new file mode 100644 index 0000000..9dbd9f6 --- /dev/null +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/models/FlowAggregatedSignatureTest.kt @@ -0,0 +1,83 @@ +package org.onflow.flow.sdk.models + +import org.onflow.flow.sdk.FlowAggregatedSignature +import org.onflow.flow.sdk.FlowId +import org.onflow.flow.sdk.FlowSignature +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import org.mockito.Mockito +import org.onflow.protobuf.entities.BlockSealOuterClass + +class FlowAggregatedSignatureTest { + @Test + fun `test FlowAggregatedSignature equals and hashCode`() { + val signature1 = FlowSignature("signature1".toByteArray()) + val signature2 = FlowSignature("signature2".toByteArray()) + + val signerId1 = FlowId.of("signerId1".toByteArray()) + val signerId2 = FlowId.of("signerId2".toByteArray()) + + val aggregatedSignature1 = FlowAggregatedSignature( + verifierSignatures = listOf(signature1), + signerIds = listOf(signerId1) + ) + + val aggregatedSignature2 = FlowAggregatedSignature( + verifierSignatures = listOf(signature1), + signerIds = listOf(signerId1) + ) + + val aggregatedSignature3 = FlowAggregatedSignature( + verifierSignatures = listOf(signature2), + signerIds = listOf(signerId2) + ) + + // Test equality + assertEquals(aggregatedSignature1, aggregatedSignature2) + assertNotEquals(aggregatedSignature1, aggregatedSignature3) + + // Test hashCode + assertEquals(aggregatedSignature1.hashCode(), aggregatedSignature2.hashCode()) + assertNotEquals(aggregatedSignature1.hashCode(), aggregatedSignature3.hashCode()) + } + + @Test + fun `test FlowAggregatedSignature of function`() { + // Mock BlockSealOuterClass.AggregatedSignature + val aggregatedSignatureProto = Mockito.mock(BlockSealOuterClass.AggregatedSignature::class.java) + + val signatureBytes = "signature".toByteArray() + val signerIdBytes = "signerId".toByteArray() + + Mockito.`when`(aggregatedSignatureProto.verifierSignaturesList).thenReturn( + listOf(com.google.protobuf.ByteString.copyFrom(signatureBytes)) + ) + Mockito.`when`(aggregatedSignatureProto.signerIdsList).thenReturn( + listOf(com.google.protobuf.ByteString.copyFrom(signerIdBytes)) + ) + + val flowAggregatedSignature = FlowAggregatedSignature.of(aggregatedSignatureProto) + + assertEquals(1, flowAggregatedSignature.verifierSignatures.size) + assertEquals(FlowSignature(signatureBytes), flowAggregatedSignature.verifierSignatures[0]) + + assertEquals(1, flowAggregatedSignature.signerIds.size) + assertEquals(FlowId.of(signerIdBytes), flowAggregatedSignature.signerIds[0]) + } + + @Test + fun `test FlowAggregatedSignature builder function`() { + val signature1 = FlowSignature("signature1".toByteArray()) + val signerId1 = FlowId.of("signerId1".toByteArray()) + + val aggregatedSignature = FlowAggregatedSignature( + verifierSignatures = listOf(signature1), + signerIds = listOf(signerId1) + ) + + val builderResult = aggregatedSignature.builder() + + assertEquals(listOf(signature1.byteStringValue), builderResult.verifierSignaturesList) + assertEquals(listOf(signerId1.byteStringValue), builderResult.signerIdsList) + } +} diff --git a/sdk/src/test/kotlin/org/onflow/flow/sdk/models/FlowBlockSealTest.kt b/sdk/src/test/kotlin/org/onflow/flow/sdk/models/FlowBlockSealTest.kt new file mode 100644 index 0000000..95d0fe2 --- /dev/null +++ b/sdk/src/test/kotlin/org/onflow/flow/sdk/models/FlowBlockSealTest.kt @@ -0,0 +1,120 @@ +package org.onflow.flow.sdk.models + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import org.mockito.Mockito +import org.onflow.flow.sdk.FlowAggregatedSignature +import org.onflow.flow.sdk.FlowBlockSeal +import org.onflow.flow.sdk.FlowId +import org.onflow.flow.sdk.FlowSignature +import org.onflow.protobuf.entities.BlockSealOuterClass + +class FlowBlockSealTest { + @Test + fun `test FlowBlockSeal equals and hashCode`() { + val blockId = FlowId.of("blockId".toByteArray()) + val executionReceiptId = FlowId.of("executionReceiptId".toByteArray()) + val resultId = FlowId.of("resultId".toByteArray()) + val finalState = "finalState".toByteArray() + + val signature1 = FlowSignature("signature1".toByteArray()) + val signature2 = FlowSignature("signature2".toByteArray()) + + val aggregatedSignature1 = FlowAggregatedSignature( + verifierSignatures = listOf(signature1), + signerIds = listOf(blockId) + ) + + val seal1 = FlowBlockSeal( + blockId = blockId, + executionReceiptId = executionReceiptId, + executionReceiptSignatures = listOf(signature1), + resultApprovalSignatures = listOf(signature2), + finalState = finalState, + resultId = resultId, + aggregatedApprovalSigs = listOf(aggregatedSignature1) + ) + + val seal2 = FlowBlockSeal( + blockId = blockId, + executionReceiptId = executionReceiptId, + executionReceiptSignatures = listOf(signature1), + resultApprovalSignatures = listOf(signature2), + finalState = finalState, + resultId = resultId, + aggregatedApprovalSigs = listOf(aggregatedSignature1) + ) + + // Testing equals + assertEquals(seal1, seal2) + + // Testing hashCode + assertEquals(seal1.hashCode(), seal2.hashCode()) + } + + @Test + fun `test FlowBlockSeal of function`() { + // Mock BlockSealOuterClass.BlockSeal + val blockSealProto = Mockito.mock(BlockSealOuterClass.BlockSeal::class.java) + + val blockIdBytes = "blockId".toByteArray() + val executionReceiptIdBytes = "executionReceiptId".toByteArray() + val resultIdBytes = "resultId".toByteArray() + val finalStateBytes = "finalState".toByteArray() + + Mockito.`when`(blockSealProto.blockId).thenReturn(com.google.protobuf.ByteString.copyFrom(blockIdBytes)) + Mockito.`when`(blockSealProto.executionReceiptId).thenReturn(com.google.protobuf.ByteString.copyFrom(executionReceiptIdBytes)) + Mockito.`when`(blockSealProto.resultId).thenReturn(com.google.protobuf.ByteString.copyFrom(resultIdBytes)) + Mockito.`when`(blockSealProto.finalState).thenReturn(com.google.protobuf.ByteString.copyFrom(finalStateBytes)) + Mockito.`when`(blockSealProto.executionReceiptSignaturesList).thenReturn(listOf( + com.google.protobuf.ByteString.copyFrom("signature1".toByteArray()) + )) + Mockito.`when`(blockSealProto.resultApprovalSignaturesList).thenReturn(listOf( + com.google.protobuf.ByteString.copyFrom("signature2".toByteArray()) + )) + Mockito.`when`(blockSealProto.aggregatedApprovalSigsList).thenReturn(listOf( + BlockSealOuterClass.AggregatedSignature.newBuilder().build() + )) + + val flowBlockSeal = FlowBlockSeal.of(blockSealProto) + + assertEquals(FlowId.of(blockIdBytes), flowBlockSeal.blockId) + assertEquals(FlowId.of(executionReceiptIdBytes), flowBlockSeal.executionReceiptId) + assertEquals(FlowId.of(resultIdBytes), flowBlockSeal.resultId) + assertArrayEquals(finalStateBytes, flowBlockSeal.finalState) + } + + @Test + fun `test FlowBlockSeal builder function`() { + val blockId = FlowId.of("blockId".toByteArray()) + val executionReceiptId = FlowId.of("executionReceiptId".toByteArray()) + val resultId = FlowId.of("resultId".toByteArray()) + val finalState = "finalState".toByteArray() + + val signature1 = FlowSignature("signature1".toByteArray()) + val signature2 = FlowSignature("signature2".toByteArray()) + val aggregatedSignature1 = FlowAggregatedSignature( + verifierSignatures = listOf(signature1), + signerIds = listOf(blockId) + ) + + val seal = FlowBlockSeal( + blockId = blockId, + executionReceiptId = executionReceiptId, + executionReceiptSignatures = listOf(signature1), + resultApprovalSignatures = listOf(signature2), + finalState = finalState, + resultId = resultId, + aggregatedApprovalSigs = listOf(aggregatedSignature1) + ) + + val builderResult = seal.builder() + + assertEquals(blockId.byteStringValue, builderResult.blockId) + assertEquals(executionReceiptId.byteStringValue, builderResult.executionReceiptId) + assertEquals(resultId.byteStringValue, builderResult.resultId) + assertEquals(finalState.toList(), builderResult.finalState.toByteArray().toList()) + assertEquals(listOf(signature1.byteStringValue), builderResult.executionReceiptSignaturesList) + assertEquals(listOf(signature2.byteStringValue), builderResult.resultApprovalSignaturesList) + } +}