This fork updates the original Outblock flow-swift SDK and tests for Swift 6, modern concurrency, and Swift Testing. It focuses on safety, test reliability, and compatibility with current Flow tooling and APIs.
-
Actor-based WebSocket center
- Introduced a WebSocket coordination actor that manages NIO-based subscriptions for transaction status streams.
- Uses
AsyncThrowingStream<Flow.WebSocketTopicResponse<Flow.WSTransactionResponse>, Error>.ContinuationperFlow.IDto bridge NIO callbacks into structured async streams.
-
Transaction status waiting APIs
- Added helpers like:
once(status: Flow.Transaction.Status, timeout: TimeInterval = 60) async throws -> Flow.TransactionResultonFlow.ID.
- Internally, this uses
AsyncThrowingStreamand task groups to:- Listen for WebSocket updates.
- Enforce timeouts.
- Cancel remaining work after a result is obtained.
- Added helpers like:
-
Sendable coverage
- Marked core models as
Sendablewhere correct, including:- Transaction-related WebSocket response types.
- Value and argument container types used across tasks and actors.
- Marked core models as
All XCTest-based tests were migrated to the new Swift Testing APIs:
@Suiteinstead ofXCTestCase.@Test("description")instead offunc testXYZ().#expect(...)assertions instead ofXCTAssert*.
Updated suites include (non-exhaustive):
FlowAccessAPIOnTestnetTestsFlowOperationTests(with legacy examples preserved but disabled)CadenceTargetTestsRLPTests
-
Transaction builder DSL
- Transaction construction now uses a clearer builder style:
cadence { """ ... """ }proposer { Flow.TransactionProposalKey(...) }payer { Flow.Address(...) }authorizers { [...] }arguments { [Flow.Argument(...), ...] }gasLimit { 1000 }
- Builders are compatible with Swift 6โs stricter closure isolation rules.
- Transaction construction now uses a clearer builder style:
-
Flow.Argument & Cadence values
Flow.Argumentretains initializers that wrap Cadence values, while avoiding leaking internal representation types into the public API.- Conversion helpers are available internally to map between Cadence values and arguments, but callers typically work directly with
Flow.Argumentand the DSL.
-
Cadence target tests
CadenceTargetTestsnow uses an explicit enum-based target description without relying on reflection.- Arguments are explicitly constructed per case, improving clarity and type safety.
- Cadence model types and conversion utilities remain internal to the SDK, so they do not appear in the public API.
- Helpers that depend on internal representation types are kept internal to avoid access-control and ABI issues.
- Public surface area exposes stable, high-level types (e.g.,
Flow.Argument,Flow.Address,Flow.Transaction) instead of low-level Cadence internals.
RLPTestswere modernized for Swift 6:- Fixed issues where mutating helpers were called on immutable values by introducing local mutable copies when necessary.
- Preserved all original RLP expectations, ensuring transaction encoding remains compatible with Flow nodes.
-
Legacy high-level transaction helpers on
Flow- Methods like
addContractToAccount,removeAccountKeyByIndex,addKeyToAccount,createAccount(...),updateContractOfAccount,removeContractFromAccount, andverifyUserSignature(...)are no longer exposed on the mainFlowtype. - Tests that referenced these helpers have been converted into commented examples inside
FlowOperationTests:- They remain as documentation for how to implement these flows.
- They can be reintroduced or reimplemented using the new transaction builder DSL as needed.
- Methods like
-
Reflection-based test plumbing
- Reflection-based helper types previously used to derive arguments (e.g., via
Mirror) are no longer used in public-facing tests. - Tests now wire arguments explicitly for clarity and compatibility with Swift 6.
- Reflection-based helper types previously used to derive arguments (e.g., via
- Swift 6 toolchain (or the latest Swift that supports Swift Testing and stricter concurrency checks).
- macOS with Xcode 16+ (or a matching Swift toolchain on another platform).
- Network access to Flow testnet/mainnet for integration tests.
Add the package to Package.swift:
dependencies: [
.package(url: "https://github.com/13Ophiuchus/flow-swift-macos.git", branch: "main")
]Then add Flow as a dependency to your target:
.target(
name: "MyApp",
dependencies: [
.product(name: "Flow", package: "flow-swift-macos")
]
)Update and build:
swift package update
swift buildThis repository uses Swift Testing (@Suite, @Test, #expect) instead of XCTest.
From the package root:
swift testThis will build and run all active test suites, including:
FlowAccessAPIOnTestnetTestsCadenceTargetTestsRLPTestsFlowOperationTests(only active tests; legacy examples remain commented out)
FlowAccessAPIOnTestnetTestsexercises real Flow access nodes against testnet.- Ensure:
- Correct access node configuration (HTTP endpoint via
createHTTPAccessAPI(chainID: .testnet)). - Stable network connectivity.
- Correct access node configuration (HTTP endpoint via
If you need to avoid network tests (e.g., in CI):
- Disable or tag specific tests/suites.
- Or temporarily comment out the
@Testattributes for integration tests.
If your toolchain supports filtering:
swift test --filter FlowAccessAPIOnTestnetTests-
Concurrency
- Prefer
actorfor shared mutable state (e.g., WebSocket centers). - Only mark types as
Sendablewhen they are truly safe across tasks. - Avoid capturing non-Sendable types (such as test suites) in
@Sendableclosures; capture only the values needed.
- Prefer
-
Access control
- Keep Cadence internals (
FValue-like types and converters) non-public. - When adding helpers on top of internal types, keep them internal unless you design a stable public abstraction.
- Keep Cadence internals (
-
Tests as specification
- Encoding tests (especially RLP) serve as a compatibility spec; do not change expected hex outputs unless you are intentionally changing encoding semantics and understand the implications for network compatibility.