Skip to content
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
7 changes: 2 additions & 5 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ jobs:
]

runs-on: ${{ matrix.os }}
env:
DEVNET_SHA: a985727189ac884924f104e34026c0ca5716b14d # v0.5.0-rc.3
steps:
- uses: actions/checkout@v3
with:
Expand Down Expand Up @@ -67,8 +65,8 @@ jobs:
- name: Install starknet-devnet
run: |
asdf plugin add starknet-devnet
asdf install starknet-devnet 0.7.0
asdf set starknet-devnet 0.7.0 --home
asdf install starknet-devnet 0.8.0-rc.0
asdf set starknet-devnet 0.8.0-rc.0 --home

- name: Install starknet-foundry
run: |
Expand Down Expand Up @@ -104,7 +102,6 @@ jobs:

- name: Run tests and generate coverage report
env:
DEVNET_PATH: ${{ github.workspace }}/starknet-devnet-rs/target/release/starknet-devnet
NETWORK_TEST_MODE: "disabled"
run: ./gradlew :lib:koverXmlReport --info

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,26 @@ object TransactionHashCalculator {
accountDeploymentData: AccountDeploymentData,
feeDataAvailabilityMode: DAMode,
nonceDataAvailabilityMode: DAMode,
proofFacts: List<Felt>? = null,
): Felt {
return Poseidon.poseidonHash(
*prepareCommonTransanctionV3Fields(
txType = TransactionType.INVOKE,
version = version,
address = senderAddress,
tip = tip,
resourceBounds = resourceBounds,
paymasterData = paymasterData,
chainId = chainId,
nonce = nonce,
nonceDataAvailabilityMode = nonceDataAvailabilityMode,
feeDataAvailabilityMode = feeDataAvailabilityMode,
).toTypedArray(),
Poseidon.poseidonHash(accountDeploymentData),
Poseidon.poseidonHash(calldata),
)
val fields = prepareCommonTransanctionV3Fields(
txType = TransactionType.INVOKE,
version = version,
address = senderAddress,
tip = tip,
resourceBounds = resourceBounds,
paymasterData = paymasterData,
chainId = chainId,
nonce = nonce,
nonceDataAvailabilityMode = nonceDataAvailabilityMode,
feeDataAvailabilityMode = feeDataAvailabilityMode,
).toMutableList()
fields.add(Poseidon.poseidonHash(accountDeploymentData))
fields.add(Poseidon.poseidonHash(calldata))
if (!proofFacts.isNullOrEmpty()) {
fields.add(Poseidon.poseidonHash(proofFacts))
}
return Poseidon.poseidonHash(*fields.toTypedArray())
}

@JvmStatic
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.swmansion.starknet.data.serializers

import com.swmansion.starknet.data.types.AddressFilter
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonEncoder
import kotlinx.serialization.json.encodeToJsonElement

internal object AddressFilterSerializer : KSerializer<AddressFilter> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("AddressFilter", PrimitiveKind.STRING)

override fun serialize(encoder: Encoder, value: AddressFilter) {
require(encoder is JsonEncoder)
val element = when (value) {
is AddressFilter.Single -> encoder.json.encodeToJsonElement(FeltSerializer, value.address)
is AddressFilter.Multiple -> encoder.json.encodeToJsonElement(ListSerializer(FeltSerializer), value.addresses)
}
encoder.encodeJsonElement(element)
}

override fun deserialize(decoder: Decoder): AddressFilter {
require(decoder is JsonDecoder)
val element = decoder.decodeJsonElement()
return if (element is JsonArray) {
val addresses = element.map { decoder.json.decodeFromJsonElement(FeltSerializer, it) }
AddressFilter.Multiple(addresses)
} else {
val address = decoder.json.decodeFromJsonElement(FeltSerializer, element)
AddressFilter.Single(address)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.*

internal val transactionIgnoredKeys = listOf("transaction_hash", "contract_address")
internal val transactionIgnoredKeys = listOf("transaction_hash", "contract_address", "proof_facts", "proof")

internal object TransactionSerializer : KSerializer<Transaction> {
override val descriptor = PrimitiveSerialDescriptor("Transaction", PrimitiveKind.STRING)
Expand Down Expand Up @@ -37,10 +37,14 @@ internal object TransactionSerializer : KSerializer<Transaction> {
"TransactionSerializer can only serialize ExecutableTransaction instances."
}

val jsonObject = encoder.json.encodeToJsonElement(ExecutableTransactionSerializer, value).jsonObject
val result = JsonObject(
jsonObject.filter { (key, _) -> !transactionIgnoredKeys.contains(key) }.plus("type" to encoder.json.encodeToJsonElement(value.type)),
)
val base = encoder.json.encodeToJsonElement(ExecutableTransactionSerializer, value).jsonObject.toMutableMap()
if (value is InvokeTransactionV3) {
value.proof?.let { base["proof"] = JsonPrimitive(it) }
if (!value.proofFacts.isNullOrEmpty()) {
base["proof_facts"] = JsonArray(value.proofFacts.map { JsonPrimitive(it.hexString()) })
}
}
val result = JsonObject(base)

encoder.encodeJsonElement(result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ internal object TransactionTracePolymorphicSerializer :
}
}

private fun selectL1HandlerTransactionTraceDeserializer(jsonObject: JsonObject): DeserializationStrategy<L1HandlerTransactionTraceBase> {
val functionInvocation = jsonObject["function_invocation"]?.jsonObject ?: throw IllegalStateException("Response from node contains invalid L1_HANDLER_TXN_TRACE: function_invocation is missing.")
val isReverted = "revert_reason" in functionInvocation

return when (isReverted) {
true -> RevertedL1HandlerTransactionTrace.serializer()
false -> L1HandlerTransactionTrace.serializer()
}
}

override fun selectDeserializer(element: JsonElement): DeserializationStrategy<TransactionTrace> {
val jsonObject = element.jsonObject

Expand All @@ -27,7 +37,7 @@ internal object TransactionTracePolymorphicSerializer :
return when (type) {
TransactionType.INVOKE -> selectInvokeTransactionTraceDeserializer(jsonObject)
TransactionType.DEPLOY_ACCOUNT -> DeployAccountTransactionTrace.serializer()
TransactionType.L1_HANDLER -> L1HandlerTransactionTrace.serializer()
TransactionType.L1_HANDLER -> selectL1HandlerTransactionTraceDeserializer(jsonObject)
TransactionType.DECLARE -> DeclareTransactionTrace.serializer()
else -> throw IllegalArgumentException("Unknown transaction trace type '${typeElement.jsonPrimitive.content}'")
}
Expand Down
18 changes: 17 additions & 1 deletion lib/src/main/kotlin/com/swmansion/starknet/data/types/Event.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.swmansion.starknet.data.types

import com.swmansion.starknet.data.serializers.AddressFilterSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -76,6 +77,21 @@ data class EmittedEvent @JvmOverloads constructor(
}
}

/**
* Filter for contract addresses emitting events.
*
* Use [Single] for a single address (serialized as a plain hex string) or
* [Multiple] for a list of addresses (serialized as a JSON array)
*/
@Serializable(with = AddressFilterSerializer::class)
sealed class AddressFilter {
/** Filter by a single contract address. */
data class Single(val address: Felt) : AddressFilter()

/** Filter by multiple contract addresses. */
data class Multiple(val addresses: List<Felt>) : AddressFilter()
}

@Serializable
data class GetEventsPayload @JvmOverloads constructor(
@SerialName("from_block")
Expand All @@ -85,7 +101,7 @@ data class GetEventsPayload @JvmOverloads constructor(
val toBlockId: BlockId? = null,

@SerialName("address")
val address: Felt? = null,
val address: AddressFilter? = null,

@SerialName("keys")
val keys: List<List<Felt>>? = null,
Expand Down
18 changes: 18 additions & 0 deletions lib/src/main/kotlin/com/swmansion/starknet/data/types/Payloads.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,18 @@ internal data class GetStorageAtPayload(

@SerialName("block_id")
override val blockId: BlockId,

@SerialName("response_flags")
val responseFlags: Set<StorageResponseFlag>? = null,
) : PayloadWithBlockId()

@Serializable
internal data class GetTransactionByHashPayload(
@SerialName("transaction_hash")
val transactionHash: Felt,

@SerialName("response_flags")
val responseFlags: Set<TxnResponseFlag>? = null,
)

@Serializable
Expand Down Expand Up @@ -108,6 +114,9 @@ internal data class GetStorageProofPayload constructor(
internal data class GetBlockWithTransactionsPayload(
@SerialName("block_id")
override val blockId: BlockId,

@SerialName("response_flags")
val responseFlags: Set<TxnResponseFlag>? = null,
) : PayloadWithBlockId()

@Serializable
Expand All @@ -120,12 +129,18 @@ internal data class GetBlockWithTransactionHashesPayload(
internal data class GetBlockWithReceiptsPayload(
@SerialName("block_id")
override val blockId: BlockId,

@SerialName("response_flags")
val responseFlags: Set<TxnResponseFlag>? = null,
) : PayloadWithBlockId()

@Serializable
internal data class GetStateUpdatePayload(
@SerialName("block_id")
override val blockId: BlockId,

@SerialName("contract_addresses")
val contractAddresses: List<Felt>? = null,
) : PayloadWithBlockId()

@Serializable
Expand All @@ -135,6 +150,9 @@ internal data class GetTransactionByBlockIdAndIndexPayload(

@SerialName("index")
val index: Int,

@SerialName("response_flags")
val responseFlags: Set<TxnResponseFlag>? = null,
) : PayloadWithBlockId()

@Serializable
Expand Down
21 changes: 21 additions & 0 deletions lib/src/main/kotlin/com/swmansion/starknet/data/types/Responses.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,27 @@ import kotlin.math.roundToInt

typealias NodeHashToNodeMapping = List<NodeHashToNodeMappingItem>

@Serializable
enum class TxnResponseFlag {
@SerialName("INCLUDE_PROOF_FACTS")
INCLUDE_PROOF_FACTS,
}

@Serializable
enum class StorageResponseFlag {
@SerialName("INCLUDE_LAST_UPDATE_BLOCK")
INCLUDE_LAST_UPDATE_BLOCK,
}

@Serializable
data class StorageResult(
@SerialName("value")
val value: Felt,

@SerialName("last_update_block")
val lastUpdateBlock: Long,
) : StarknetResponse

@Serializable
data class CallContractResponse(
val result: List<Felt>,
Expand Down
Loading
Loading