Skip to content
Open
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
57 changes: 57 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Contributing to hiero-sdk-swift

Thank you for your interest in contributing!

## How to Contribute

1. **Fork the repository** and create your branch from `main`.
2. **Make your changes** in the appropriate folder:
- SDK code: `Sources/Hiero/`
- Example usage: `Examples/`
- Tests: `Tests/`
3. **Add or update documentation** as needed.
4. **Test your changes** to ensure nothing is broken.
5. **Commit and push** your branch.
6. **Open a Pull Request** on GitHub and describe your changes.

## Local Setup

1. Install [Swift](https://swift.org/download/) (5.7 or later recommended).
2. Clone the repository:
```sh
git clone https://github.com/K6-Rakshith/hiero-sdk-swift.git
cd hiero-sdk-swift
```
3. Build the project:
```sh
swift build
```
4. Run tests:
```sh
swift test
```

## Code Style
- Follow Swift best practices and existing code style.
- Add comments and documentation where helpful.
- Use descriptive variable and function names.

## Commit Messages
- Use clear, concise commit messages.
- Reference issues or PRs when relevant (e.g., `Fixes #42`).

## Pull Request Review Process
- All PRs are reviewed by maintainers.
- Address all review comments before merging.
- Ensure CI checks pass before requesting review.

## Code of Conduct
- Be respectful and inclusive.
- See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) if available.

## Reporting Issues
- Use GitHub Issues to report bugs or suggest features.
- Provide as much detail as possible (steps to reproduce, logs, etc.).

## Questions?
- Check the README or open an issue.
56 changes: 56 additions & 0 deletions Examples/CreateAccount/main.swift
Original file line number Diff line number Diff line change
@@ -1,26 +1,80 @@

Check notice on line 1 in Examples/CreateAccount/main.swift

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

Examples/CreateAccount/main.swift#L1

Files should not contain leading whitespace
import Hiero
import SwiftDotenv

@main
internal enum Program {
internal static func main() async throws {
let env = try Dotenv.load()
let client = try Client.forName(env.networkName)

client.setOperator(env.operatorAccountId, env.operatorKey)

let newKey = PrivateKey.generateEd25519()

print("private key = \(newKey)")
print("public key = \(newKey.publicKey)")

let response = try await AccountCreateTransaction()
.keyWithoutAlias(.single(newKey.publicKey))
.initialBalance(5)
.execute(client)

let receipt = try await response.getReceipt(client)
let newAccountId = receipt.accountId!

print("account address = \(newAccountId)")
}
}

extension Environment {
/// Account ID for the operator to use in this example.
internal var operatorAccountId: AccountId {
AccountId(self["OPERATOR_ID"]!.stringValue)!
}

/// Private key for the operator to use in this example.
internal var operatorKey: PrivateKey {
PrivateKey(self["OPERATOR_KEY"]!.stringValue)!
}
// SPDX-License-Identifier: Apache-2.0

import Hiero
import SwiftDotenv

/// Example program to create a new Hedera account using the Hiero SDK.
///
/// This script demonstrates:
/// 1. Loading environment variables for network and operator credentials.
/// 2. Initializing a client for the target network.
/// 3. Generating a new Ed25519 key pair.
/// 4. Creating a new account with the generated public key and an initial balance.
/// 5. Printing the new account's ID and the generated keys.
@main
internal enum Program {
internal static func main() async throws {
// Load environment variables from .env file
let env = try Dotenv.load()

// Initialize the client for the specified network
let client = try Client.forName(env.networkName)

// Set the operator (payer) for transactions
client.setOperator(env.operatorAccountId, env.operatorKey)

// Generate a new Ed25519 private/public key pair
let newKey = PrivateKey.generateEd25519()

print("private key = \(newKey)")
print("public key = \(newKey.publicKey)")

// Create a new account with the generated public key and initial balance of 5 hbars
let response = try await AccountCreateTransaction()
.keyWithoutAlias(.single(newKey.publicKey))
.initialBalance(5)
.execute(client)

// Get the receipt and extract the new account ID
let receipt = try await response.getReceipt(client)
let newAccountId = receipt.accountId!

Expand All @@ -30,11 +84,13 @@

extension Environment {
/// Account ID for the operator to use in this example.
/// Reads from the OPERATOR_ID environment variable.
internal var operatorAccountId: AccountId {
AccountId(self["OPERATOR_ID"]!.stringValue)!
}

/// Private key for the operator to use in this example.
/// Reads from the OPERATOR_KEY environment variable.
internal var operatorKey: PrivateKey {
PrivateKey(self["OPERATOR_KEY"]!.stringValue)!
}
Expand Down
57 changes: 23 additions & 34 deletions Tests/HieroE2ETests/Batch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Hiero
import XCTest

internal final class Batch: XCTestCase {
internal final class BatchTests: XCTestCase {
internal func testBatchOneTransaction() async throws {
let testEnv = try TestEnvironment.nonFree

Expand All @@ -19,9 +19,13 @@ internal final class Batch: XCTestCase {
.addInnerTransaction(accountCreateTx)
.freezeWith(testEnv.client)
.sign(batchKey)
_ = try await batchTx.execute(testEnv.client).getReceipt(testEnv.client)
let batchReceipt = try await batchTx.execute(testEnv.client).getReceipt(testEnv.client)

XCTAssertEqual(batchReceipt.status, .success)

let transactionIds = batchTx.innerTransactionIds
XCTAssertEqual(transactionIds.count, 1)

let accountCreateReceipt = try await TransactionReceiptQuery()
.transactionId(transactionIds[0]).execute(testEnv.client)
let accountId = try XCTUnwrap(accountCreateReceipt.accountId)
Expand All @@ -44,38 +48,21 @@ internal final class Batch: XCTestCase {
.batchify(client: testEnv.client, .single(batchKey.publicKey))
.freezeWith(testEnv.client)

let batchTx = try BatchTransaction()
/// 25 account create transactions
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
.addInnerTransaction(accountCreateTx)
var batchTx = BatchTransaction()
for _ in 0..<25 {
try batchTx.addInnerTransaction(accountCreateTx)
}

batchTx = try batchTx
.freezeWith(testEnv.client)
.sign(batchKey)
_ = try await batchTx.execute(testEnv.client).getReceipt(testEnv.client)
let batchReceipt = try await batchTx.execute(testEnv.client).getReceipt(testEnv.client)

XCTAssertEqual(batchReceipt.status, .success)

let transactionIds = batchTx.innerTransactionIds
XCTAssertEqual(transactionIds.count, 25)

let accountCreateReceipt = try await TransactionReceiptQuery()
.transactionId(transactionIds[0]).execute(testEnv.client)
let accountId = try XCTUnwrap(accountCreateReceipt.accountId)
Expand Down Expand Up @@ -137,7 +124,9 @@ internal final class Batch: XCTestCase {
.addInnerTransaction(topicMsgSubmitTx)
.freezeWith(testEnv.client)
.sign(batchKey)
_ = try await batchTx.execute(testEnv.client).getReceipt(testEnv.client)
let batchReceipt = try await batchTx.execute(testEnv.client).getReceipt(testEnv.client)

XCTAssertEqual(batchReceipt.status, .success)

let info = try await TopicInfoQuery(topicId: topicId).execute(testEnv.client)

Expand Down Expand Up @@ -251,9 +240,9 @@ internal final class Batch: XCTestCase {

let finalOperatorBalance = try await AccountBalanceQuery().accountId(testEnv.operator.accountId).execute(
testEnv.client
)
.hbars
XCTAssertLessThan(initialOperatorBalance, finalOperatorBalance)
).hbars

XCTAssertLessThan(finalOperatorBalance, initialOperatorBalance)
}

internal func testBatchifiedTxButNotInBatch() async throws {
Expand Down
34 changes: 28 additions & 6 deletions Tests/HieroE2ETests/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,36 @@
import Hiero
import XCTest

internal class ClientIntegrationTests: XCTestCase {
internal final class ClientIntegrationTests: XCTestCase {
internal func testInitWithMirrorNetwork() async throws {
let mirrorNetworkString = "testnet.mirrornode.hedera.com:443"
let client = try await Client.forMirrorNetwork([mirrorNetworkString])
// Define the mirror network address for testnet
let mirrorNetworkAddress = "testnet.mirrornode.hedera.com:443"

// Initialize the client with the mirror network
let client: Client
do {
client = try await Client.forMirrorNetwork([mirrorNetworkAddress])
} catch {
XCTFail("Client initialization failed with error: \(error.localizedDescription)")
throw error
}

// Verify the mirror network is set correctly
let mirrorNetwork = client.mirrorNetwork
XCTAssertEqual(mirrorNetwork.count, 1, "Mirror network should contain exactly one address")
XCTAssertEqual(mirrorNetwork[0], mirrorNetworkAddress, "Mirror network address mismatch")

// Verify the main network is initialized and not nil/empty
XCTAssertNotNil(client.network, "Main network should be initialized")
XCTAssertFalse(client.network.isEmpty, "Main network should not be empty after mirror initialization")

// Optional: Perform a simple query to validate client functionality (e.g., get network name or a basic info)
// This ensures the client is not just created but usable; adjust based on SDK capabilities
XCTAssertNoThrow(try await client.pingAll(), "Client should be able to ping the network")

XCTAssertEqual(mirrorNetwork.count, 1)
XCTAssertEqual(mirrorNetwork[0], mirrorNetworkString)
XCTAssertNotNil(client.network)
// Teardown: Close the client to release resources (if supported by SDK)
addTeardownBlock {
client.close()
}
}
}
Loading