Skip to content

Commit dd854b8

Browse files
committed
Add final state for all onchain interaction
1 parent 8ede77a commit dd854b8

6 files changed

Lines changed: 91 additions & 52 deletions

File tree

Sources/Network/FlowAccess.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ extension Flow: FlowAccessProtocol {
1212
return try await flow.accessAPI.ping()
1313
}
1414

15-
public func getLatestBlockHeader() async throws -> BlockHeader {
16-
return try await flow.accessAPI.getLatestBlockHeader()
15+
public func getLatestBlockHeader(blockStatus: Flow.BlockStatus = .final) async throws -> BlockHeader {
16+
return try await flow.accessAPI.getLatestBlockHeader(blockStatus: blockStatus)
1717
}
1818

1919
public func getBlockHeaderById(id: ID) async throws -> BlockHeader {
@@ -24,8 +24,8 @@ extension Flow: FlowAccessProtocol {
2424
return try await flow.accessAPI.getBlockHeaderByHeight(height: height)
2525
}
2626

27-
public func getLatestBlock(sealed: Bool) async throws -> Block {
28-
return try await flow.accessAPI.getLatestBlock(sealed: sealed)
27+
public func getLatestBlock(blockStatus: Flow.BlockStatus = .final) async throws -> Block {
28+
return try await flow.accessAPI.getLatestBlock(blockStatus: blockStatus)
2929
}
3030

3131
public func getBlockById(id: ID) async throws -> Block {
@@ -52,8 +52,8 @@ extension Flow: FlowAccessProtocol {
5252
return try await flow.accessAPI.getTransactionResultById(id: id)
5353
}
5454

55-
public func getAccountAtLatestBlock(address: Address) async throws -> Account {
56-
return try await flow.accessAPI.getAccountAtLatestBlock(address: address)
55+
public func getAccountAtLatestBlock(address: Address, blockStatus: Flow.BlockStatus = .final) async throws -> Account {
56+
return try await flow.accessAPI.getAccountAtLatestBlock(address: address, blockStatus: blockStatus)
5757
}
5858

5959
public func getAccountByBlockHeight(address: Address, height: UInt64) async throws -> Account {
@@ -68,8 +68,8 @@ extension Flow: FlowAccessProtocol {
6868
return try await flow.accessAPI.getEventsForBlockIds(type: type, ids: ids)
6969
}
7070

71-
public func executeScriptAtLatestBlock(script: Script, arguments: [Argument]) async throws -> ScriptResponse {
72-
return try await flow.accessAPI.executeScriptAtLatestBlock(script: script, arguments: arguments)
71+
public func executeScriptAtLatestBlock(script: Script, arguments: [Argument], blockStatus: Flow.BlockStatus = .final) async throws -> ScriptResponse {
72+
return try await flow.accessAPI.executeScriptAtLatestBlock(script: script, arguments: arguments, blockStatus: blockStatus)
7373
}
7474

7575
public func getNetworkParameters() async throws -> ChainID {

Sources/Network/FlowAccessProtocol.swift

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public protocol FlowAccessProtocol {
4242

4343
/// Get latest block header
4444
/// - Returns: Most recent block header
45-
func getLatestBlockHeader() async throws -> Flow.BlockHeader
45+
func getLatestBlockHeader(blockStatus: Flow.BlockStatus) async throws -> Flow.BlockHeader
4646

4747
/// Get block header by ID
4848
/// - Parameter id: Block identifier
@@ -51,7 +51,7 @@ public protocol FlowAccessProtocol {
5151

5252
func getBlockHeaderByHeight(height: UInt64) async throws -> Flow.BlockHeader
5353

54-
func getLatestBlock(sealed: Bool) async throws -> Flow.Block
54+
func getLatestBlock(blockStatus: Flow.BlockStatus) async throws -> Flow.Block
5555

5656
func getBlockById(id: Flow.ID) async throws -> Flow.Block
5757

@@ -65,13 +65,13 @@ public protocol FlowAccessProtocol {
6565

6666
func getTransactionResultById(id: Flow.ID) async throws -> Flow.TransactionResult
6767

68-
func getAccountAtLatestBlock(address: Flow.Address) async throws -> Flow.Account
68+
func getAccountAtLatestBlock(address: Flow.Address, blockStatus: Flow.BlockStatus) async throws -> Flow.Account
6969

7070
func getAccountByBlockHeight(address: Flow.Address, height: UInt64) async throws -> Flow.Account
7171

72-
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Argument]) async throws -> Flow.ScriptResponse
72+
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Argument], blockStatus: Flow.BlockStatus) async throws -> Flow.ScriptResponse
7373

74-
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Cadence.FValue]) async throws -> Flow.ScriptResponse
74+
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Cadence.FValue], blockStatus: Flow.BlockStatus) async throws -> Flow.ScriptResponse
7575

7676
func executeScriptAtBlockId(script: Flow.Script, blockId: Flow.ID, arguments: [Flow.Argument]) async throws -> Flow.ScriptResponse
7777

@@ -91,8 +91,17 @@ public protocol FlowAccessProtocol {
9191
}
9292

9393
public extension FlowAccessProtocol {
94-
func getAccountAtLatestBlock(address: String) async throws -> Flow.Account {
95-
return try await getAccountAtLatestBlock(address: .init(hex: address.addHexPrefix()))
94+
95+
func getLatestBlockHeader(blockStatus: Flow.BlockStatus = .final) async throws -> Flow.BlockHeader {
96+
return try await getLatestBlockHeader(blockStatus: blockStatus)
97+
}
98+
99+
func getAccountAtLatestBlock(address: Flow.Address, blockStatus: Flow.BlockStatus = .final) async throws -> Flow.Account {
100+
return try await getAccountAtLatestBlock(address: address, blockStatus: blockStatus)
101+
}
102+
103+
func getAccountAtLatestBlock(address: String, blockStatus: Flow.BlockStatus = .final) async throws -> Flow.Account {
104+
return try await getAccountAtLatestBlock(address: .init(hex: address.addHexPrefix()), blockStatus: blockStatus)
96105
}
97106

98107
func getTransactionById(id: String) async throws -> Flow.Transaction {
@@ -104,24 +113,28 @@ public extension FlowAccessProtocol {
104113
}
105114

106115
func getLatestBlock(sealed: Bool = true) async throws -> Flow.Block {
107-
return try await getLatestBlock(sealed: sealed)
116+
return try await getLatestBlock(blockStatus: .final)
108117
}
109118

110-
func executeScriptAtLatestBlock(cadence: String, arguments: [Flow.Argument] = []) async throws -> Flow.ScriptResponse {
111-
return try await executeScriptAtLatestBlock(script: .init(text: cadence), arguments: arguments)
119+
func executeScriptAtLatestBlock(cadence: String, arguments: [Flow.Argument] = [], blockStatus: Flow.BlockStatus = .final) async throws -> Flow.ScriptResponse {
120+
return try await executeScriptAtLatestBlock(script: .init(text: cadence), arguments: arguments, blockStatus: blockStatus)
112121
}
113122

114-
func executeScriptAtLatestBlock(cadence: String, arguments: [Flow.Cadence.FValue] = []) async throws -> Flow.ScriptResponse {
115-
return try await executeScriptAtLatestBlock(script: .init(text: cadence), arguments: arguments.map { $0.toArgument() })
123+
func executeScriptAtLatestBlock(cadence: String, arguments: [Flow.Cadence.FValue] = [], blockStatus: Flow.BlockStatus = .final) async throws -> Flow.ScriptResponse {
124+
return try await executeScriptAtLatestBlock(script: .init(text: cadence), arguments: arguments, blockStatus: blockStatus)
116125
}
117126

118-
func executeScriptAtLatestBlock(script: Flow.Script) async throws -> Flow.ScriptResponse {
127+
func executeScriptAtLatestBlock(script: Flow.Script, blockStatus: Flow.BlockStatus = .final) async throws -> Flow.ScriptResponse {
119128
let list: [Flow.Argument] = []
120-
return try await executeScriptAtLatestBlock(script: script, arguments: list)
129+
return try await executeScriptAtLatestBlock(script: script, arguments: list, blockStatus: blockStatus)
130+
}
131+
132+
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Argument], blockStatus: Flow.BlockStatus = .final) async throws -> Flow.ScriptResponse {
133+
return try await executeScriptAtLatestBlock(script: script, arguments: arguments, blockStatus: blockStatus)
121134
}
122135

123-
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Cadence.FValue]) async throws -> Flow.ScriptResponse {
124-
return try await executeScriptAtLatestBlock(script: script, arguments: arguments.map { $0.toArgument() })
136+
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Cadence.FValue], blockStatus: Flow.BlockStatus = .final) async throws -> Flow.ScriptResponse {
137+
return try await executeScriptAtLatestBlock(script: script, arguments: arguments.map { $0.toArgument() }, blockStatus: blockStatus)
125138
}
126139

127140
func executeScriptAtBlockId(script: Flow.Script, blockId: Flow.ID, arguments: [Flow.Argument] = []) async throws -> Flow.ScriptResponse {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// File.swift
3+
// Flow
4+
//
5+
// Created by Hao Fu on 7/5/2025.
6+
//
7+
8+
import Foundation
9+
10+
extension Flow {
11+
public enum BlockStatus: String, Codable {
12+
case sealed
13+
case final
14+
}
15+
}

Sources/Network/HTTP/AccessEndpoint.swift

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,17 @@ extension Flow {
2424
case getNetwork
2525
case getBlockHeaderByHeight(height: UInt64)
2626
case getBlockHeaderById(id: Flow.ID)
27-
case getLatestBlockHeader
28-
case getLatestBlock(sealed: Bool)
27+
case getLatestBlockHeader(blockStatus: Flow.BlockStatus)
28+
case getLatestBlock(blockStatus: Flow.BlockStatus)
2929
case getBlockById(id: Flow.ID)
3030
case getBlockByHeight(height: UInt64)
3131
case getCollectionById(id: Flow.ID)
3232
case sendTransaction(transaction: Flow.Transaction)
3333
case getTransactionById(id: Flow.ID)
3434
case getTransactionResultById(id: Flow.ID)
35-
case getAccountAtLatestBlock(address: Flow.Address)
35+
case getAccountAtLatestBlock(address: Flow.Address, blockStatus: Flow.BlockStatus)
3636
case getAccountByBlockHeight(address: Flow.Address, height: UInt64)
37-
case executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Argument])
37+
case executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Argument], blockStatus: Flow.BlockStatus)
3838
case executeScriptAtBlockId(script: Flow.Script, blockId: Flow.ID, arguments: [Flow.Argument])
3939
case executeScriptAtBlockHeight(script: Flow.Script, height: UInt64, arguments: [Flow.Argument])
4040
case getEventsForHeightRange(type: String, range: ClosedRange<UInt64>)
@@ -45,24 +45,26 @@ extension Flow {
4545
extension Flow.AccessEndpoint: TargetType {
4646
var task: Task {
4747
switch self {
48-
case .ping, .getLatestBlockHeader:
48+
case .ping:
4949
return .requestParameters(["height": "sealed"])
50+
case let .getLatestBlockHeader(blockStatus):
51+
return .requestParameters(["height": blockStatus.rawValue])
5052
case let .getBlockHeaderByHeight(height: height):
5153
return .requestParameters(["height": String(height)])
5254
case .getBlockById:
5355
return .requestParameters(["expand": "payload"])
5456
case let .getBlockByHeight(height):
5557
return .requestParameters(["height": String(height), "expand": "payload"])
56-
case let .getLatestBlock(sealed: sealed):
57-
return .requestParameters(["height": sealed ? "sealed" : "finalized", "expand": "payload"])
58-
case .getAccountAtLatestBlock:
59-
return .requestParameters(["block_height": "sealed", "expand": "contracts,keys"])
58+
case let .getLatestBlock(blockStatus):
59+
return .requestParameters(["height": blockStatus.rawValue, "expand": "payload"])
60+
case let .getAccountAtLatestBlock(_, blockStatus):
61+
return .requestParameters(["block_height": blockStatus.rawValue, "expand": "contracts,keys"])
6062
case let .getAccountByBlockHeight(_, height):
6163
return .requestParameters(["block_height": String(height), "expand": "contracts,keys"])
6264
case .getCollectionById:
6365
return .requestParameters(["expand": "transactions"])
64-
case let .executeScriptAtLatestBlock(script, arguments):
65-
return .requestParameters(["block_height": "final"], body: Flow.ScriptRequest(script: script, arguments: arguments))
66+
case let .executeScriptAtLatestBlock(script, arguments, blockStatus):
67+
return .requestParameters(["block_height": blockStatus.rawValue], body: Flow.ScriptRequest(script: script, arguments: arguments))
6668
case let .executeScriptAtBlockHeight(script, height, arguments):
6769
return .requestParameters(["block_height": String(height)], body: Flow.ScriptRequest(script: script, arguments: arguments))
6870
case let .executeScriptAtBlockId(script, id, arguments):
@@ -109,7 +111,7 @@ extension Flow.AccessEndpoint: TargetType {
109111
return "/v1/blocks/\(id.hex)"
110112
case let .getBlockById(id):
111113
return "/v1/blocks/\(id.hex)"
112-
case let .getAccountAtLatestBlock(address):
114+
case let .getAccountAtLatestBlock(address, _):
113115
return "/v1/accounts/\(address.hex.stripHexPrefix())"
114116
case let .getAccountByBlockHeight(address, _):
115117
return "/v1/accounts/\(address.hex.stripHexPrefix())"

Sources/Network/HTTP/FlowHTTPClient.swift

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extension Flow {
2727
/// HTTP client implementation for Flow Access API
2828
/// Handles all network communication with Flow nodes
2929
class FlowHTTPAPI: FlowAccessProtocol {
30+
3031
/// Shared instance of the HTTP client
3132
static let client = FlowHTTPAPI()
3233

@@ -152,8 +153,8 @@ extension Flow {
152153
return result.chainId
153154
}
154155

155-
func getLatestBlockHeader() async throws -> Flow.BlockHeader {
156-
let result: [Flow.BlockHeaderResponse] = try await request(Flow.AccessEndpoint.getLatestBlockHeader)
156+
func getLatestBlockHeader(blockStatus: Flow.BlockStatus) async throws -> Flow.BlockHeader {
157+
let result: [Flow.BlockHeaderResponse] = try await request(Flow.AccessEndpoint.getLatestBlockHeader(blockStatus: blockStatus))
157158
guard let block = result.first else {
158159
throw FError.invaildResponse
159160
}
@@ -176,8 +177,8 @@ extension Flow {
176177
return block.header
177178
}
178179

179-
func getLatestBlock(sealed: Bool) async throws -> Flow.Block {
180-
let result: [Flow.BlockResponse] = try await request(Flow.AccessEndpoint.getLatestBlock(sealed: sealed))
180+
func getLatestBlock(blockStatus: Flow.BlockStatus) async throws -> Flow.Block {
181+
let result: [Flow.BlockResponse] = try await request(Flow.AccessEndpoint.getLatestBlock(blockStatus: blockStatus))
181182
guard let block = result.first else {
182183
throw FError.invaildResponse
183184
}
@@ -217,17 +218,17 @@ extension Flow {
217218
return try await request(Flow.AccessEndpoint.getTransactionResultById(id: id))
218219
}
219220

220-
func getAccountAtLatestBlock(address: Flow.Address) async throws -> Flow.Account {
221-
return try await request(Flow.AccessEndpoint.getAccountAtLatestBlock(address: address))
221+
func getAccountAtLatestBlock(address: Flow.Address, blockStatus: Flow.BlockStatus = .final) async throws -> Flow.Account {
222+
return try await request(Flow.AccessEndpoint.getAccountAtLatestBlock(address: address, blockStatus: blockStatus))
222223
}
223224

224225
func getAccountByBlockHeight(address: Flow.Address, height: UInt64) async throws -> Flow.Account {
225226
return try await request(Flow.AccessEndpoint.getAccountByBlockHeight(address: address, height: height))
226227
}
227228

228-
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Argument]) async throws -> Flow.ScriptResponse {
229+
func executeScriptAtLatestBlock(script: Flow.Script, arguments: [Flow.Argument], blockStatus: Flow.BlockStatus) async throws -> Flow.ScriptResponse {
229230
let resolvedScript = flow.addressRegister.resolveImports(in: script.text, for: chainID)
230-
return try await request(Flow.AccessEndpoint.executeScriptAtLatestBlock(script: .init(text: resolvedScript), arguments: arguments))
231+
return try await request(Flow.AccessEndpoint.executeScriptAtLatestBlock(script: .init(text: resolvedScript), arguments: arguments, blockStatus: blockStatus))
231232
}
232233

233234
func executeScriptAtBlockId(script: Flow.Script, blockId: Flow.ID, arguments: [Flow.Argument]) async throws -> Flow.ScriptResponse {

Tests/FlowAccessAPIOnTestnetTests.swift

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ final class FlowAccessAPIOnTestnetTests: XCTestCase {
6767
let result = try! await flow.accessAPI.executeScriptAtLatestBlock(script: .init(text: """
6868
import FlowFees from 0x912d5440f7e3769e
6969
70-
pub fun main(): FlowFees.FeeParameters {
71-
return FlowFees.getFeeParameters()
72-
}
70+
access(all) fun main(): FlowFees.FeeParameters {
71+
return FlowFees.getFeeParameters()
72+
}
7373
"""))
7474
print(result)
7575
}
@@ -90,19 +90,19 @@ final class FlowAccessAPIOnTestnetTests: XCTestCase {
9090
let accountKey = Flow.AccountKey(publicKey: Flow.PublicKey(hex: "bfa6d9893d4d9b5e53b0b9d79ac44b4e20f57b6443f02e5f12b366ed4e1fb4e7decca4e58b76308cee1a22a4c0c01f6fce698dc62c80120f65e8cdf57a0ffdff"),
9191
signAlgo: .ECDSA_P256,
9292
hashAlgo: .SHA2_256,
93-
weight: 1000)
93+
weight: 1001)
9494

9595
var unsignedTx = try! await flow.buildTransaction {
9696
cadence {
9797
"""
9898
import Crypto
9999
transaction(publicKey: String, signatureAlgorithm: UInt8, hashAlgorithm: UInt8, weight: UFix64) {
100-
prepare(signer: AuthAccount) {
100+
prepare(signer: auth(BorrowValue | Storage) &Account) {
101101
let key = PublicKey(
102102
publicKey: publicKey.decodeHex(),
103103
signatureAlgorithm: SignatureAlgorithm(rawValue: signatureAlgorithm)!
104104
)
105-
let account = AuthAccount(payer: signer)
105+
let account = Account(payer: signer)
106106
account.keys.add(
107107
publicKey: key,
108108
hashAlgorithm: HashAlgorithm(rawValue: hashAlgorithm)!,
@@ -137,10 +137,18 @@ final class FlowAccessAPIOnTestnetTests: XCTestCase {
137137
}
138138

139139
let signedTx = try! await unsignedTx.sign(signers: signer)
140-
141140
let txId = try! await flow.sendTransaction(signedTransaction: signedTx)
142-
XCTAssertNotNil(txId)
143141
print("txid --> \(txId.hex)")
142+
XCTAssertNotNil(txId)
143+
144+
let result = try await txId.onceExecuted()
145+
let address = result.getCreatedAddress()!
146+
print("address --> \(address)")
147+
XCTAssertNotNil(address)
148+
149+
let accountInfo = try await flow.getAccountAtLatestBlock(address: .init(address))
150+
print("accountInfo --> \(accountInfo)")
151+
XCTAssertNotNil(accountInfo)
144152
}
145153

146154
func testMultipleSigner() async throws {

0 commit comments

Comments
 (0)