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

Integration tests updates #34

Merged
merged 7 commits into from
Mar 5, 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 build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ configurations["intTestRuntimeOnly"].extendsFrom(configurations.runtimeOnly.get(

dependencies {
intTestImplementation("org.junit.jupiter:junit-jupiter:5.10.1")
intTestImplementation("org.assertj:assertj-core:3.25.1")
intTestRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

Expand Down
8 changes: 5 additions & 3 deletions src/intTest/com/nftco/flow/sdk/ExposeAccountKeyIssueTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ class ExposeAccountKeyIssueTest {
@FlowServiceAccountCredentials
lateinit var serviceAccount: TestAccount

// Constants
private val startingBalance = BigDecimal.ONE
private val signatureAlgorithm1 = SignatureAlgorithm.ECDSA_P256
private val hashAlgorithm1 = HashAlgorithm.SHA3_256

// Ignoring for now
// @Test
fun `Expose issue with account keys api`() {
Expand All @@ -31,9 +36,6 @@ class ExposeAccountKeyIssueTest {

// create the account

val startingBalance = BigDecimal.ONE
val signatureAlgorithm1 = SignatureAlgorithm.ECDSA_P256
val hashAlgorithm1 = HashAlgorithm.SHA3_256
val pair1 = Crypto.generateKeyPair(signatureAlgorithm1)
val signer1 = Crypto.getSigner(pair1.private, hashAlgorithm1)

Expand Down
24 changes: 24 additions & 0 deletions src/intTest/com/nftco/flow/sdk/IntegrationTestUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.nftco.flow.sdk

object IntegrationTestUtils {
fun newMainnetAccessApi(): FlowAccessApi = Flow.newAccessApi(MAINNET_HOSTNAME)

fun newTestnetAccessApi(): FlowAccessApi = Flow.newAccessApi(TESTNET_HOSTNAME)

private const val MAINNET_HOSTNAME = "access.mainnet.nodes.onflow.org"
private const val TESTNET_HOSTNAME = "access.devnet.nodes.onflow.org"

var transaction = FlowTransaction(
script = FlowScript("import 0xsomething \n {}"),
arguments = listOf(FlowArgument(byteArrayOf(2, 2, 3)), FlowArgument(byteArrayOf(3, 3, 3))),
referenceBlockId = FlowId.of(byteArrayOf(3, 3, 3, 6, 6, 6)),
gasLimit = 44,
proposalKey = FlowTransactionProposalKey(
address = FlowAddress.of(byteArrayOf(4, 5, 4, 5, 4, 5)),
keyIndex = 11,
sequenceNumber = 7
),
payerAddress = FlowAddress.of(byteArrayOf(6, 5, 4, 3, 2)),
authorizers = listOf(FlowAddress.of(byteArrayOf(9, 9, 9, 9, 9)), FlowAddress.of(byteArrayOf(8, 9, 9, 9, 9)))
)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.nftco.flow.sdk
package com.nftco.flow.sdk.cadence

import com.nftco.flow.sdk.FlowId
import com.nftco.flow.sdk.IntegrationTestUtils
import com.nftco.flow.sdk.decode
import com.nftco.flow.sdk.simpleFlowScript
import kotlinx.serialization.Serializable
import org.assertj.core.api.Assertions
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class JsonCadenceTest {
Expand All @@ -25,14 +29,14 @@ class JsonCadenceTest {
val bar: Int,
)

val flow = TestUtils.newMainnetAccessApi()
private val flow = IntegrationTestUtils.newMainnetAccessApi()

@Test
fun `Can parse new JSON Cadence`() {
val flow = TestUtils.newMainnetAccessApi()
val flow = IntegrationTestUtils.newMainnetAccessApi()
val tx = flow.getTransactionResultById(FlowId("273f68ffe175a0097db60bc7cf5e92c5a775d189af3f5636f5432c1206be771a"))!!
val events = tx.events.map { it.payload.jsonCadence }
Assertions.assertThat(events).hasSize(7)
assertThat(events).hasSize(7)
}

@Test
Expand All @@ -47,7 +51,7 @@ class JsonCadenceTest {
}
}
val data = result.jsonCadence.decode<Boolean?>()
Assertions.assertThat(data).isEqualTo(null)
assertThat(data).isEqualTo(null)
}

@Test
Expand All @@ -62,7 +66,7 @@ class JsonCadenceTest {
}
}
val data = result.jsonCadence.decode<Boolean?>()
Assertions.assertThat(data).isEqualTo(true)
assertThat(data).isEqualTo(true)
}

@Test
Expand All @@ -77,7 +81,7 @@ class JsonCadenceTest {
}
}
val data = result.jsonCadence.decode<Boolean>()
Assertions.assertThat(data).isEqualTo(true)
assertThat(data).isEqualTo(true)
}

@Test
Expand All @@ -93,8 +97,8 @@ class JsonCadenceTest {
}

val data = result.jsonCadence.decode<List<ULong>>()
Assertions.assertThat(data.first()).isEqualTo(1UL)
Assertions.assertThat(data).hasSize(4)
assertThat(data.first()).isEqualTo(1UL)
assertThat(data).hasSize(4)
}

@Test
Expand All @@ -110,7 +114,7 @@ class JsonCadenceTest {
}

val data = result.jsonCadence.decode<Double>()
Assertions.assertThat(data).isEqualTo(0.789111)
assertThat(data).isEqualTo(0.789111)
}

@Test
Expand Down Expand Up @@ -143,9 +147,9 @@ class JsonCadenceTest {
}

val data = result.jsonCadence.decode<List<StorageInfo>>().first()
Assertions.assertThat(data.capacity).isEqualTo(1)
Assertions.assertThat(data.used).isEqualTo(2)
Assertions.assertThat(data.available).isEqualTo(3)
assertThat(data.capacity).isEqualTo(1)
assertThat(data.used).isEqualTo(2)
assertThat(data.available).isEqualTo(3)
}

@Test
Expand Down Expand Up @@ -191,6 +195,6 @@ class JsonCadenceTest {
}

val data = result.decode<Map<String, List<StorageInfoComplex>>>()
Assertions.assertThat(data["test"]!!.first().foo.bar).isEqualTo(1)
assertThat(data["test"]!!.first().foo.bar).isEqualTo(1)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package com.nftco.flow.sdk
package com.nftco.flow.sdk.extensions

import com.nftco.flow.sdk.AsyncFlowAccessApi
import com.nftco.flow.sdk.FlowAccessApi
import com.nftco.flow.sdk.HashAlgorithm
import com.nftco.flow.sdk.SignatureAlgorithm
import com.nftco.flow.sdk.test.*
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.nftco.flow.sdk
package com.nftco.flow.sdk.extensions

import com.nftco.flow.sdk.AsyncFlowAccessApi
import com.nftco.flow.sdk.FlowAccessApi
import com.nftco.flow.sdk.SignatureAlgorithm
import com.nftco.flow.sdk.test.*
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
Expand Down
133 changes: 133 additions & 0 deletions src/intTest/com/nftco/flow/sdk/transaction/TransactionCreationTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package com.nftco.flow.sdk.transaction

import com.nftco.flow.sdk.*
import com.nftco.flow.sdk.crypto.Crypto
import com.nftco.flow.sdk.IntegrationTestUtils.transaction
import org.assertj.core.api.Assertions.assertThat
import com.nftco.flow.sdk.test.FlowEmulatorTest
import com.nftco.flow.sdk.test.FlowServiceAccountCredentials
import com.nftco.flow.sdk.test.FlowTestClient
import com.nftco.flow.sdk.test.TestAccount
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test

@FlowEmulatorTest
class TransactionCreationTest {
@FlowTestClient
lateinit var accessAPI: FlowAccessApi

@FlowServiceAccountCredentials
lateinit var serviceAccount: TestAccount

@Test
fun `Canonical transaction form is accurate`() {
val payloadEnvelope = transaction.canonicalPayload

// those values were generated from Go implementation for the same transaction input data
val payloadExpectedHex =
"f86a97696d706f7274203078736f6d657468696e67200a207b7dc88302020383030303a000000000000000000000000000000000000000000000000000000303030606062c8800000405040504050b07880000000605040302d2880000000909090909880000000809090909"
val envelopeExpectedHex =
"f883f86a97696d706f7274203078736f6d657468696e67200a207b7dc88302020383030303a000000000000000000000000000000000000000000000000000000303030606062c8800000405040504050b07880000000605040302d2880000000909090909880000000809090909d6ce80808b0404040404040404040404c6040583030303"

assertThat(payloadEnvelope).isEqualTo(payloadExpectedHex.hexToBytes())

val fooSignature = byteArrayOf(4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4)
val barSignature = byteArrayOf(3, 3, 3)

val signedTx = transaction.copy(
payloadSignatures = listOf(
FlowTransactionSignature(serviceAccount.flowAddress, 0, 0, FlowSignature(fooSignature)),
FlowTransactionSignature(serviceAccount.flowAddress, 4, 5, FlowSignature(barSignature))
)
)

val authorizationEnvelope = signedTx.canonicalAuthorizationEnvelope
assertThat(authorizationEnvelope).isEqualTo(envelopeExpectedHex.hexToBytes())
}

@Test
fun `Can create an account using the transaction DSL`() {
val latestBlockId = accessAPI.getLatestBlockHeader().id

val payerAccount = accessAPI.getAccountAtLatestBlock(serviceAccount.flowAddress)!!

val newAccountKeyPair = Crypto.generateKeyPair(SignatureAlgorithm.ECDSA_P256)
val newAccountPublicKey = FlowAccountKey(
publicKey = FlowPublicKey(newAccountKeyPair.public.hex),
signAlgo = SignatureAlgorithm.ECDSA_P256,
hashAlgo = HashAlgorithm.SHA3_256,
weight = 1000
)

val tx = flowTransaction {
script {
"""
transaction(publicKey: String) {
prepare(signer: AuthAccount) {
let account = AuthAccount(payer: signer)
account.addPublicKey(publicKey.decodeHex())
}
}
"""
}

arguments {
arg { string(newAccountPublicKey.encoded.bytesToHex()) }
}

referenceBlockId = latestBlockId
gasLimit = 100

proposalKey {
address = payerAccount.address
keyIndex = payerAccount.keys[0].id
sequenceNumber = payerAccount.keys[0].sequenceNumber.toLong()
}

payerAddress = payerAccount.address

signatures {
signature {
address = payerAccount.address
keyIndex = 0
signer = serviceAccount.signer
}
}
}

val txID = accessAPI.sendTransaction(tx)
val result = waitForSeal(accessAPI, txID).throwOnError()
assertThat(result).isNotNull
assertThat(result.status).isEqualTo(FlowTransactionStatus.SEALED)
}

@Test
fun `Can create an account using the simpleTransaction DSL`() {
val newAccountKeyPair = Crypto.generateKeyPair(SignatureAlgorithm.ECDSA_P256)
val newAccountPublicKey = FlowAccountKey(
publicKey = FlowPublicKey(newAccountKeyPair.public.hex),
signAlgo = SignatureAlgorithm.ECDSA_P256,
hashAlgo = HashAlgorithm.SHA3_256,
weight = 1000
)

val result = accessAPI.simpleFlowTransaction(serviceAccount.flowAddress, serviceAccount.signer) {
script {
"""
transaction(publicKey: String) {
prepare(signer: AuthAccount) {
let account = AuthAccount(payer: signer)
account.addPublicKey(publicKey.decodeHex())
}
}
"""
}

arguments {
arg { string(newAccountPublicKey.encoded.bytesToHex()) }
}
}.sendAndWaitForSeal()
.throwOnError()
assertThat(result.status).isEqualTo(FlowTransactionStatus.SEALED)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.nftco.flow.sdk.transaction

import com.nftco.flow.sdk.*
import org.assertj.core.api.Assertions.assertThat
import com.nftco.flow.sdk.test.FlowEmulatorTest
import org.junit.jupiter.api.Test

@FlowEmulatorTest
class TransactionDecodingTest {
@Test
fun `Can decode transaction envelope`() {
// the value below was calculated using the flow-go-sdk from the tx defined here https://github.com/onflow/flow-go-sdk/blob/3ecd5d4920939922bb3b010b0d1b5567131b1341/transaction_test.go#L119-L129
val canonicalTransactionHex = "f882f872b07472616e73616374696f6e207b2065786563757465207b206c6f67282248656c6c6f2c20576f726c64212229207d207dc0a001020000000000000000000000000000000000000000000000000000000000002a88f8d6e0586b0a20c7032a88ee82856bf20e2aa6c988f8d6e0586b0a20c7c8c3800202c3800301c4c3010703"
val expectedTransactionId = "d1a2c58aebfce1050a32edf3568ec3b69cb8637ae090b5f7444ca6b2a8de8f8b"
val proposerAddress = "f8d6e0586b0a20c7"
val payerAddress = "ee82856bf20e2aa6"

val decodedTx = FlowTransaction.of(canonicalTransactionHex.hexToBytes())

assertThat(decodedTx.script).isEqualTo(FlowScript("transaction { execute { log(\"Hello, World!\") } }"))
assertThat(decodedTx.arguments).isEqualTo(emptyList<FlowArgument>())
assertThat(decodedTx.referenceBlockId).isEqualTo(FlowId.of(byteArrayOf(1, 2).copyOf(32)))
assertThat(decodedTx.gasLimit).isEqualTo(42)
assertThat(decodedTx.proposalKey.address.base16Value).isEqualTo(proposerAddress)
assertThat(decodedTx.proposalKey.keyIndex).isEqualTo(3)
assertThat(decodedTx.proposalKey.sequenceNumber).isEqualTo(42)
assertThat(decodedTx.payerAddress.base16Value).isEqualTo(payerAddress)
assertThat(decodedTx.authorizers).isEqualTo(listOf(FlowAddress(proposerAddress)))

assertThat(decodedTx.payloadSignatures).isEqualTo(
listOf(
FlowTransactionSignature(FlowAddress("f8d6e0586b0a20c7"), 0, 2, FlowSignature(byteArrayOf(2))),
FlowTransactionSignature(
FlowAddress("f8d6e0586b0a20c7"), 0, 3, FlowSignature(byteArrayOf(1))
)
)
)
assertThat(decodedTx.envelopeSignatures).isEqualTo(
listOf(FlowTransactionSignature(FlowAddress(payerAddress), 1, 7, FlowSignature(byteArrayOf(3))))
)

assertThat(decodedTx.id.base16Value).isEqualTo(expectedTransactionId)
assertThat(decodedTx.canonicalTransaction.bytesToHex()).isEqualTo(canonicalTransactionHex)
}

@Test
fun `Can precompute the transaction id`() {
// the example below was retrieved from https://github.com/onflow/flow-go-sdk/blob/3ecd5d4920939922bb3b010b0d1b5567131b1341/transaction_test.go#L119-L129
val expectedTransactionIdBeforeSigning = "8c362dd8b7553d48284cecc94d2ab545d513b29f930555632390fff5ca9772ee"
val expectedTransactionIdAfterSigning = "d1a2c58aebfce1050a32edf3568ec3b69cb8637ae090b5f7444ca6b2a8de8f8b"
val expectedCanonicalTransactionHex = "f882f872b07472616e73616374696f6e207b2065786563757465207b206c6f67282248656c6c6f2c20576f726c64212229207d207dc0a001020000000000000000000000000000000000000000000000000000000000002a88f8d6e0586b0a20c7032a88ee82856bf20e2aa6c988f8d6e0586b0a20c7c8c3800202c3800301c4c3010703"
val proposerAddress = "f8d6e0586b0a20c7"
val payerAddress = "ee82856bf20e2aa6"

var testTx = FlowTransaction(
script = FlowScript("transaction { execute { log(\"Hello, World!\") } }"),
arguments = emptyList(),
referenceBlockId = FlowId.of(byteArrayOf(1, 2).copyOf(32)),
gasLimit = 42,
proposalKey = FlowTransactionProposalKey(
address = FlowAddress(proposerAddress),
keyIndex = 3,
sequenceNumber = 42
),
payerAddress = FlowAddress(payerAddress),
authorizers = listOf(FlowAddress(proposerAddress))
)

assertThat(testTx.id.base16Value).isEqualTo(expectedTransactionIdBeforeSigning)

testTx = testTx.addPayloadSignature(FlowAddress(proposerAddress), 3, FlowSignature(byteArrayOf(1)))
testTx = testTx.addPayloadSignature(FlowAddress(proposerAddress), 2, FlowSignature(byteArrayOf(2)))
testTx = testTx.addEnvelopeSignature(FlowAddress(payerAddress), 7, FlowSignature(byteArrayOf(3)))

assertThat(testTx.id.base16Value).isEqualTo(expectedTransactionIdAfterSigning)
assertThat(testTx.canonicalTransaction.bytesToHex()).isEqualTo(expectedCanonicalTransactionHex)
}
}
Loading
Loading