Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1bd2629
Reflect spec changes
franciszekjob Jul 15, 2025
d409c41
Add tip support
franciszekjob Jul 15, 2025
95dc6bb
Simplify constructors for fee estimate structs
franciszekjob Jul 15, 2025
45bf10f
Fix `testSimulateTransactionsV3`
franciszekjob Jul 15, 2025
7f74704
Fix newline
franciszekjob Jul 15, 2025
74a2b09
Merge branch 'feat/rpc-0.9.0' of https://github.com/software-mansion/…
franciszekjob Jul 15, 2025
3879956
Fix tests
franciszekjob Jul 15, 2025
44dbd3b
Fix tip value in constructor
franciszekjob Jul 15, 2025
d4d91b9
Remove unused variables
franciszekjob Jul 15, 2025
b45ae20
Restore `ethErc20ContractAddress`
franciszekjob Jul 15, 2025
64a4d62
Apply code review suggestions
franciszekjob Jul 17, 2025
66d81f9
Add comment
franciszekjob Jul 17, 2025
496f776
Merge branch 'main' of https://github.com/software-mansion/starknet.s…
franciszekjob Jul 17, 2025
bd822ea
Merge branch 'feat/rpc-0.9.0' of https://github.com/software-mansion/…
franciszekjob Jul 17, 2025
ba6c958
Merge branch 'main' of https://github.com/software-mansion/starknet.s…
franciszekjob Jul 17, 2025
281bd7c
Support `starknet_getBlockWithTxs`
franciszekjob Jul 28, 2025
529a31f
Merge branch 'main' into get-block-with-txs
franciszekjob Jul 28, 2025
ebf9ecf
Formatting
franciszekjob Jul 28, 2025
5bbe0d6
Merge branch 'get-block-with-txs' of https://github.com/software-mans…
franciszekjob Jul 28, 2025
30e281b
Add network tests
franciszekjob Jul 28, 2025
db95e96
Fix commas
franciszekjob Jul 28, 2025
1e5ad3b
Add comma
franciszekjob Jul 28, 2025
042c85b
Remove tests for getting block from regular test suite
franciszekjob Jul 29, 2025
78a0f72
Add todo
franciszekjob Jul 29, 2025
61805c0
Add pre-confirmed coding key in `BlockTag`
franciszekjob Jul 29, 2025
956a0f9
Update todo
franciszekjob Jul 30, 2025
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
4 changes: 4 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@ let package = Package(
.process("Resources"),
]
),
.testTarget(
name: "NetworkTests",
dependencies: ["Starknet"]
),
]
)
113 changes: 113 additions & 0 deletions Sources/Starknet/Data/Block.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
public enum BlockStatus: String, Codable {
case preConfirmed = "PRE_CONFIRMED"
case acceptedOnL1 = "ACCEPTED_ON_L1"
case acceptedOnL2 = "ACCEPTED_ON_L2"
case rejected = "REJECTED"
}

public protocol StarknetBlock: Codable {
var timestamp: Int { get }
var sequencerAddress: Felt { get }
var blockNumber: Int { get }
var l1GasPrice: StarknetResourcePrice { get }
var l2GasPrice: StarknetResourcePrice { get }
var l1DataGasPrice: StarknetResourcePrice { get }
var l1DataAvailabilityMode: StarknetL1DAMode { get }
var starknetVersion: String { get }
}

public protocol StarknetProcessedBlock: StarknetBlock {
var status: BlockStatus { get }
var blockHash: Felt { get }
var parentHash: Felt { get }
var newRoot: Felt { get }
}

public protocol StarknetPreConfirmedBlock: StarknetBlock {}

public protocol StarknetBlockWithTxs: StarknetBlock {
var transactions: [TransactionWrapper] { get }
}

public struct StarknetProcessedBlockWithTxs: StarknetProcessedBlock, StarknetBlockWithTxs, Encodable {
public let status: BlockStatus
public let transactions: [TransactionWrapper]
public let blockHash: Felt
public let parentHash: Felt
public let blockNumber: Int
public let newRoot: Felt
public let timestamp: Int
public let sequencerAddress: Felt
public let l1GasPrice: StarknetResourcePrice
public let l2GasPrice: StarknetResourcePrice
public let l1DataGasPrice: StarknetResourcePrice
public let l1DataAvailabilityMode: StarknetL1DAMode
public let starknetVersion: String

enum CodingKeys: String, CodingKey {
case status
case transactions
case blockHash = "block_hash"
case parentHash = "parent_hash"
case blockNumber = "block_number"
case newRoot = "new_root"
case timestamp
case sequencerAddress = "sequencer_address"
case l1GasPrice = "l1_gas_price"
case l2GasPrice = "l2_gas_price"
case l1DataGasPrice = "l1_data_gas_price"
case l1DataAvailabilityMode = "l1_da_mode"
case starknetVersion = "starknet_version"
}
}

public struct StarknetPreConfirmedBlockWithTxs: StarknetPreConfirmedBlock, StarknetBlockWithTxs, Codable {
public let transactions: [TransactionWrapper]
public let blockNumber: Int
public let timestamp: Int
public let sequencerAddress: Felt
public let l1GasPrice: StarknetResourcePrice
public let l2GasPrice: StarknetResourcePrice
public let l1DataGasPrice: StarknetResourcePrice
public let l1DataAvailabilityMode: StarknetL1DAMode
public let starknetVersion: String

enum CodingKeys: String, CodingKey {
case transactions
case blockNumber = "block_number"
case timestamp
case sequencerAddress = "sequencer_address"
case l1GasPrice = "l1_gas_price"
case l2GasPrice = "l2_gas_price"
case l1DataGasPrice = "l1_data_gas_price"
case l1DataAvailabilityMode = "l1_da_mode"
case starknetVersion = "starknet_version"
}
}

public enum StarknetBlockWithTxsWrapper: Codable {
case processed(StarknetProcessedBlockWithTxs)
case preConfirmed(StarknetPreConfirmedBlockWithTxs)

public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
if container.contains(.parentHash) {
let block = try StarknetProcessedBlockWithTxs(from: decoder)
self = .processed(block)
} else {
let block = try StarknetPreConfirmedBlockWithTxs(from: decoder)
self = .preConfirmed(block)
}
}

public func encode(to encoder: Encoder) throws {
switch self {
case let .processed(block): try block.encode(to: encoder)
case let .preConfirmed(block): try block.encode(to: encoder)
}
}

private enum CodingKeys: String, CodingKey {
case parentHash = "parent_hash"
}
}
11 changes: 3 additions & 8 deletions Sources/Starknet/Data/StarknetBlockId.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import Foundation

public enum StarknetBlockId: Equatable {
public enum BlockTag: String {
public enum BlockTag: String, Codable {
case latest
case preConfirmed
case preConfirmed = "pre_confirmed"
}

case hash(Felt)
case number(Int)
case tag(BlockTag)

enum CodingKeys: String, CodingKey {
case latest
case preConfirmed = "pre_confirmed"
}
}

extension StarknetBlockId: Encodable {
Expand All @@ -30,7 +25,7 @@ extension StarknetBlockId: Encodable {
]
try dict.encode(to: encoder)
case let .tag(blockTag):
try blockTag.rawValue.encode(to: encoder)
try blockTag.encode(to: encoder)
}
}
}
4 changes: 4 additions & 0 deletions Sources/Starknet/Data/Transaction/Data/L1DAMode.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
public enum StarknetL1DAMode: String, Codable {
case blob = "BLOB"
case calldata = "CALLDATA"
}
9 changes: 9 additions & 0 deletions Sources/Starknet/Data/Transaction/Data/ResourcePrice.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
public struct StarknetResourcePrice: Codable, Equatable {
public let priceInWei: Felt
public let priceInFri: Felt

enum CodingKeys: String, CodingKey {
case priceInWei = "price_in_wei"
case priceInFri = "price_in_fri"
}
}
2 changes: 1 addition & 1 deletion Sources/Starknet/Data/Transaction/TransactionWrapper.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

/// Transaction wrapper used for decoding polymorphic StarknetTransaction
public enum TransactionWrapper: Decodable {
public enum TransactionWrapper: Decodable, Encodable {
fileprivate enum Keys: String, CodingKey {
case type
case version
Expand Down
42 changes: 42 additions & 0 deletions Sources/Starknet/Network/StarknetRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,46 @@ public enum RequestBuilder {
public static func simulateTransactions(_ transactions: [any StarknetExecutableTransaction], simulationFlags: Set<StarknetSimulationFlag>) -> StarknetRequest<[StarknetSimulatedTransaction]> {
simulateTransactions(transactions, at: defaultBlockId, simulationFlags: simulationFlags)
}

/// Get a block with transactions.
///
/// - Parameters:
/// - blockId: hash, number, or tag of the requested block.
///
/// - Returns: Block information with full transactions.
public static func getBlockWithTxs(_ blockId: StarknetBlockId) -> StarknetRequest<StarknetBlockWithTxsWrapper> {
let params = GetBlockWithTxsParams(blockId: blockId)

return StarknetRequest(method: .getBlockWithTxs, params: .getBlockWithTxs(params))
}

/// Get a block with transactions by block hash.
///
/// - Parameters:
/// - blockHash: hash of the requested block.
///
/// - Returns: Block information with full transactions.
public static func getBlockWithTxs(_ blockHash: Felt) -> StarknetRequest<StarknetBlockWithTxsWrapper> {
getBlockWithTxs(StarknetBlockId.hash(blockHash))
}

/// Get a block with transactions by block number.
///
/// - Parameters:
/// - blockNumber: number of the requested block.
///
/// - Returns: Block information with full transactions.
public static func getBlockWithTxs(_ blockNumber: Int) -> StarknetRequest<StarknetBlockWithTxsWrapper> {
getBlockWithTxs(StarknetBlockId.number(blockNumber))
}

/// Get a block with transactions by block tag.
///
/// - Parameters:
/// - blockTag: tag of the requested block.
///
/// - Returns: Block information with full transactions.
public static func getBlockWithTxs(_ blockTag: StarknetBlockId.BlockTag) -> StarknetRequest<StarknetBlockWithTxsWrapper> {
getBlockWithTxs(StarknetBlockId.tag(blockTag))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ enum JsonRpcMethod: String, Encodable {
case getClassHashAt = "starknet_getClassHashAt"
case getBlockNumber = "starknet_blockNumber"
case getBlockHashAndNumber = "starknet_blockHashAndNumber"
case getBlockWithTxs = "starknet_getBlockWithTxs"
case getEvents = "starknet_getEvents"
case getStorageProof = "starknet_getStorageProof"
case getTransactionByHash = "starknet_getTransactionByHash"
Expand Down
11 changes: 11 additions & 0 deletions Sources/Starknet/Providers/StarknetProvider/JsonRpcParams.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ struct SimulateTransactionsParams: Encodable {
}
}

struct GetBlockWithTxsParams: Encodable {
let blockId: StarknetBlockId

enum CodingKeys: String, CodingKey {
case blockId = "block_id"
}
}

enum JsonRpcParams {
case getNonce(GetNonceParams)
case addInvokeTransaction(AddInvokeTransactionParams)
Expand All @@ -194,6 +202,7 @@ enum JsonRpcParams {
case estimateFee(EstimateFeeParams)
case estimateMessageFee(EstimateMessageFeeParams)
case addDeployAccountTransaction(AddDeployAccountTransactionParams)
case getBlockWithTxs(GetBlockWithTxsParams)
case getClassHashAt(GetClassHashAtParams)
case getEvents(GetEventsPayload)
case getStorageProof(GetStorageProofParams)
Expand Down Expand Up @@ -224,6 +233,8 @@ extension JsonRpcParams: Encodable {
try params.encode(to: encoder)
case let .addDeployAccountTransaction(params):
try params.encode(to: encoder)
case let .getBlockWithTxs(params):
try params.encode(to: encoder)
case let .getClassHashAt(params):
try params.encode(to: encoder)
case let .getEvents(params):
Expand Down
56 changes: 56 additions & 0 deletions Tests/NetworkTests/Providers/ProviderTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import XCTest

@testable import Starknet

final class ProviderTests: XCTestCase {
var provider: StarknetProviderProtocol!

override class func setUp() {
super.setUp()
}

override func setUp() async throws {
try await super.setUp()

// TODO(#245): Change this to internal node
provider = StarknetProvider(url: "https://rpc.pathfinder.equilibrium.co/testnet-sepolia/rpc/v0_9")
}

func testGetBlockWithTxsWithLatestBlockTag() async throws {
let result = try await provider.send(request: RequestBuilder.getBlockWithTxs(StarknetBlockId.BlockTag.latest))

if case .preConfirmed = result {
XCTFail("Expected .processed")
}
}

func testGetBlockWithTxsWithPreConfirmedBlockTag() async throws {
let result = try await provider.send(request: RequestBuilder.getBlockWithTxs(StarknetBlockId.BlockTag.preConfirmed))

if case .processed = result {
XCTFail("Expected .preConfirmed")
}
}

func testGetBlockWithTxsWithBlockHash() async throws {
let blockHash = Felt(fromHex: "0x05d95c778dad488e15f6a279c77c59322ad61eabf085cd8624ff5b39ca5ae8d8")!
let result = try await provider.send(request: RequestBuilder.getBlockWithTxs(blockHash))

if case let .processed(processedBlock) = result {
XCTAssertEqual(processedBlock.transactions.count, 7)
} else {
XCTFail("Expected .processed")
}
}

func testGetBlockWithTxsWithBlockNumber() async throws {
let blockNumber = 1_210_000
let result = try await provider.send(request: RequestBuilder.getBlockWithTxs(blockNumber))

if case let .processed(processedBlock) = result {
XCTAssertEqual(processedBlock.transactions.count, 8)
} else {
XCTFail("Expected .processed")
}
}
}
16 changes: 16 additions & 0 deletions Tests/StarknetTests/Providers/ProviderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -383,4 +383,20 @@ final class ProviderTests: XCTestCase {
XCTFail("Error was not a StarknetProviderError. Received error type: \(type(of: error))")
}
}

func testGetBlockWithTxsWithLatestBlockTag() async throws {
let result = try await provider.send(request: RequestBuilder.getBlockWithTxs(StarknetBlockId.BlockTag.latest))

if case .preConfirmed = result {
XCTFail("Expected .processed")
}
}

func testGetBlockWithTxsWithPreConfirmedBlockTag() async throws {
let result = try await provider.send(request: RequestBuilder.getBlockWithTxs(StarknetBlockId.BlockTag.preConfirmed))

if case .processed = result {
XCTFail("Expected .preConfirmed")
}
}
}
Loading