Skip to content

Commit

Permalink
Bring this sdk closer to parity
Browse files Browse the repository at this point in the history
  • Loading branch information
qtbeee committed Jan 4, 2020
1 parent 85a9362 commit d17d3b7
Show file tree
Hide file tree
Showing 24 changed files with 167 additions and 217 deletions.
8 changes: 4 additions & 4 deletions Examples/CreateAccount/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public func clientFromEnvironment(eventLoopGroup: EventLoopGroup) -> Client {
guard let operatorId = ProcessInfo.processInfo.environment["OPERATOR_ID"] else { fatalError("environment variable OPERATOR_ID must be set")}
guard let operatorKey = ProcessInfo.processInfo.environment["OPERATOR_KEY"] else { fatalError("environment variable OPERATOR_KEY must be set")}

return Client(node: AccountId(nodeId)!, address: address, eventLoopGroup: eventLoopGroup)
.setOperator(Operator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!))
return Client(network: [address: AccountId(nodeId)!], eventLoopGroup: eventLoopGroup)
.setOperator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!)
}

// Make sure to shutdown the eventloop once we're done so we don't leak threads
Expand All @@ -31,9 +31,9 @@ let tx = AccountCreateTransaction()
.setKey(newAccountKey.publicKey)
.setMemo("Create Account Example - Swift SDK")
.build(client: client)

try! tx.execute(client: client).get()

let receipt = try! tx.queryReceipt(client: client).get()
let receipt = try! tx.queryReceipt(client: client).wait().get()

print("Account created: \(receipt.accountId!)")
6 changes: 3 additions & 3 deletions Examples/CreateFile/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public func clientFromEnvironment(eventLoopGroup: EventLoopGroup) -> Client {
guard let operatorId = ProcessInfo.processInfo.environment["OPERATOR_ID"] else { fatalError("environment variable OPERATOR_ID must be set")}
guard let operatorKey = ProcessInfo.processInfo.environment["OPERATOR_KEY"] else { fatalError("environment variable OPERATOR_KEY must be set")}

return Client(node: AccountId(nodeId)!, address: address, eventLoopGroup: eventLoopGroup)
.setOperator(Operator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!))
return Client(network: [address: AccountId(nodeId)!], eventLoopGroup: eventLoopGroup)
.setOperator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!)
}

// Make sure to shutdown the eventloop once we're done so we don't leak threads
Expand All @@ -33,6 +33,6 @@ let tx = FileCreateTransaction()

try! tx.execute(client: client).get()

let receipt = try! tx.queryReceipt(client: client).get()
let receipt = try! tx.queryReceipt(client: client).wait().get()

print("File created: \(receipt.fileId!)")
9 changes: 5 additions & 4 deletions Examples/GetAccountBalance/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ public func clientFromEnvironment(eventLoopGroup: EventLoopGroup) -> Client {
fatalError("environment variables OPERATOR_KEY and OPERATOR_ID must be present")
}

return Client(node: AccountId(3), address: "0.testnet.hedera.com:50211", eventLoopGroup: eventLoopGroup)
.setOperator(Operator(id: AccountId(operatorId!)!, privateKey: Ed25519PrivateKey(operatorKey!)!))
return Client(network: ["0.testnet.hedera.com:50211": AccountId(3)], eventLoopGroup: eventLoopGroup)
.setOperator(id: AccountId(operatorId!)!, privateKey: Ed25519PrivateKey(operatorKey!)!)
}

let eventLoopGroup = PlatformSupport.makeEventLoopGroup(loopCount: 1)
Expand All @@ -24,7 +24,8 @@ defer {

let client = clientFromEnvironment(eventLoopGroup: eventLoopGroup)

let balance = AccountBalanceQuery(node: client.pickNode())
.execute(client: client)
let balance = try! AccountBalanceQuery()
.executeAsync(client: client)
.wait()

print("balance = \(balance)")
9 changes: 5 additions & 4 deletions Examples/GetFileInfo/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public func clientFromEnvironment(eventLoopGroup: EventLoopGroup) -> Client {
guard let operatorId = ProcessInfo.processInfo.environment["OPERATOR_ID"] else { fatalError("environment variable OPERATOR_ID must be set")}
guard let operatorKey = ProcessInfo.processInfo.environment["OPERATOR_KEY"] else { fatalError("environment variable OPERATOR_KEY must be set")}

return Client(node: AccountId(nodeId)!, address: address, eventLoopGroup: eventLoopGroup)
.setOperator(Operator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!))
return Client(network: [address: AccountId(nodeId)!], eventLoopGroup: eventLoopGroup)
.setOperator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!)
}

// Make sure to shutdown the eventloop once we're done so we don't leak threads
Expand All @@ -23,9 +23,10 @@ let client = clientFromEnvironment(eventLoopGroup: eventLoopGroup)
.setMaxTransactionFee(100_000_000)
.setMaxQueryPayment(1_000_000_000)

let fileInfo = try! FileInfoQuery(node: client.pickNode())
let fileInfo = try! FileInfoQuery()
.setFile(FileId(119300))
.execute(client: client)
.executeAsync(client: client)
.wait()
.get()

print("FileInfo Example succeeded with result \(fileInfo)")
6 changes: 3 additions & 3 deletions Examples/SimpleAccountRecords/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public func clientFromEnvironment(eventLoopGroup: EventLoopGroup) -> Client {
guard let operatorId = ProcessInfo.processInfo.environment["OPERATOR_ID"] else { fatalError("environment variable OPERATOR_ID must be set")}
guard let operatorKey = ProcessInfo.processInfo.environment["OPERATOR_KEY"] else { fatalError("environment variable OPERATOR_KEY must be set")}

return Client(node: AccountId(nodeId)!, address: address, eventLoopGroup: eventLoopGroup)
.setOperator(Operator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!))
return Client(network: [address: AccountId(nodeId)!], eventLoopGroup: eventLoopGroup)
.setOperator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!)
}

// Make sure to shutdown the eventloop once we're done so we don't leak threads
Expand All @@ -22,6 +22,6 @@ defer {
let client = clientFromEnvironment(eventLoopGroup: eventLoopGroup)
.setMaxQueryPayment(100_000_000)

let records = try! client.getAccountRecords().get()
// let records = try! client.getAccountRecords().wait().get()

print("records fetched successfully")
8 changes: 4 additions & 4 deletions Examples/TransferCrypto/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public func clientFromEnvironment(eventLoopGroup: EventLoopGroup) -> Client {
guard let operatorId = ProcessInfo.processInfo.environment["OPERATOR_ID"] else { fatalError("environment variable OPERATOR_ID must be set")}
guard let operatorKey = ProcessInfo.processInfo.environment["OPERATOR_KEY"] else { fatalError("environment variable OPERATOR_KEY must be set")}

return Client(node: AccountId(nodeId)!, address: address, eventLoopGroup: eventLoopGroup)
.setOperator(Operator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!))
return Client(network: [address: AccountId(nodeId)!], eventLoopGroup: eventLoopGroup)
.setOperator(id: AccountId(operatorId)!, privateKey: Ed25519PrivateKey(operatorKey)!)
}

// Make sure to shutdown the eventloop once we're done so we don't leak threads
Expand All @@ -27,9 +27,9 @@ let tx = CryptoTransferTransaction()
.add(recipient: AccountId("0.0.2")!, amount: 10000)
.setMemo("Transfer Crypto Example - Swift SDK")
.build(client: client)

let transactionId = try! tx.execute(client: client).get()

let receipt = try! tx.queryReceipt(client: client).get()
let receipt = try! tx.queryReceipt(client: client).wait().get()

print("Crypto transferred successfully")
2 changes: 1 addition & 1 deletion Sources/Hedera/Backoff.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ enum Backoff {
// converting from seconds to microseconds
return UInt32(delay * 1000000)
}
}
}
118 changes: 41 additions & 77 deletions Sources/Hedera/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import Sodium
import GRPC
import NIO

public struct Node {
struct Node {
let accountId: AccountId
let address: String

var host: String {
let colonIndex = address.firstIndex(of: ":")!
return String(address.prefix(upTo: colonIndex))
}

var port: Int {
let colonIndex = address.firstIndex(of: ":")!
return Int(String(address.suffix(from: address.index(after: colonIndex))))!
}
}

typealias HederaGRPCClient = (fileService: Proto_FileServiceServiceClient,
cryptoService: Proto_CryptoServiceServiceClient,
contractService: Proto_SmartContractServiceServiceClient)
Expand All @@ -26,8 +26,7 @@ let defaultMaxTransactionFee: UInt64 = 100_000_000
public class Client {
var `operator`: Operator?

var nodes: [AccountId: Node]
var node: Node?
var network: [AccountId: Node]

var grpcClients: [AccountId: HederaGRPCClient] = [:]

Expand All @@ -42,23 +41,48 @@ public class Client {

/// Eventloop that will be shared by all grpc clients
let eventLoopGroup: EventLoopGroup
let shouldCloseEventLoopOnDestroy: Bool

public init(node id: AccountId, address url: String, eventLoopGroup: EventLoopGroup) {
nodes = [ id: Node(accountId: id, address: url) ]
self.eventLoopGroup = eventLoopGroup
public convenience init(network: [String: AccountId], eventLoopGroup: EventLoopGroup) {
self.init(network: network, eventLoopGroup: eventLoopGroup, shouldCloseEventLoopOnDestroy: false)
}

public convenience init(network: [String: AccountId]) {
self.init(network: network,
eventLoopGroup: PlatformSupport.makeEventLoopGroup(loopCount: 1),
shouldCloseEventLoopOnDestroy: true)
}

public init(nodes: [(AccountId, String)], eventLoopGroup: EventLoopGroup) {
let keys = nodes.map { $0.0 }
let values = nodes.map { Node(accountId: $0.0, address: $0.1) }
self.nodes = Dictionary(uniqueKeysWithValues: zip(keys, values))
init(network: [String: AccountId], eventLoopGroup: EventLoopGroup, shouldCloseEventLoopOnDestroy: Bool) {
self.network = Dictionary(uniqueKeysWithValues: network.map { (key, value) in
return (value, Node(accountId: value, address: key))
})
self.eventLoopGroup = eventLoopGroup
self.shouldCloseEventLoopOnDestroy = shouldCloseEventLoopOnDestroy
}

deinit {
if shouldCloseEventLoopOnDestroy {
try! eventLoopGroup.syncShutdownGracefully()
}
}

/// Sets the account that will be paying for transactions and queries on the network.
/// - Returns: Self for fluent usage.
@discardableResult
public func setOperator(_ operator: Operator) -> Self {
public func setOperator(id: AccountId, privateKey: Ed25519PrivateKey) -> Self {
return setOperator(Operator(id: id, privateKey: privateKey))
}

/// Sets the account that will be paying for transactions and queries on the network.
/// - Returns: Self for fluent usage.
@discardableResult
public func setOperator(id: AccountId, signer: @escaping Signer, publicKey: Ed25519PublicKey) -> Self {
return setOperator(Operator(id: id, signer: signer, publicKey: publicKey))
}

@discardableResult
func setOperator(_ operator: Operator) -> Self {
self.`operator` = `operator`
return self
}
Expand Down Expand Up @@ -89,68 +113,8 @@ public class Client {
return self
}

@discardableResult
public func setNode(_ id: AccountId) -> Self {
node = nodes[id]
return self
}

@discardableResult
public func addNode(id: AccountId, address url: String) -> Self {
nodes[id] = Node(accountId: id, address: url)
return self
}

public func pickNode() -> Node {
nodes.randomElement()!.value
}

/// Gets the balance of the operator's account in tiny bars.
/// - Returns: The operator's account balance.
public func getAccountBalance() -> Result<UInt64, HederaError> {
getAccountBalance(account: self.operator!.id)
}

/// Gets the balance of the given account in tiny bars.
/// - Parameters:
/// - account: The account to check the balance of.
/// - Returns: `account`'s balance.
public func getAccountBalance(account: AccountId) -> Result<UInt64, HederaError> {
AccountBalanceQuery(node: node ?? pickNode())
.setAccount(account)
.execute(client: self)
}

/// Gets the operator's account info.
/// - Returns: The operator's account info.
public func getAccountInfo() -> Result<AccountInfo, HederaError> {
getAccountInfo(account: self.operator!.id)
}

/// Gets the given account's account info.
/// - Parameters:
/// - account: The account to get the info of.
/// - Returns: `account`'s account info.
public func getAccountInfo(account: AccountId) -> Result<AccountInfo, HederaError> {
AccountInfoQuery(node: node ?? pickNode())
.setAccount(account)
.execute(client: self)
}

/// Gets the operator's Transaction Records.
/// - Returns: The operator's Transaction Records.
public func getAccountRecords() -> Result<[TransactionRecord], HederaError> {
getAccountRecords(account: self.operator!.id)
}

/// Gets the given account's transaction records.
/// - Parameters:
/// - account: The account to get the transaction records for.
/// - Returns: `account`'s transaction records.
public func getAccountRecords(account: AccountId) -> Result<[TransactionRecord], HederaError> {
AccountRecordsQuery(node: node ?? pickNode())
.setAccount(account)
.execute(client: self)
func pickNode() -> Node {
network.randomElement()!.value
}

func grpcClient(for node: Node) -> HederaGRPCClient {
Expand All @@ -168,7 +132,7 @@ public class Client {
fileService: fileService,
cryptoService: cryptoService,
contractService: contractService)

grpcClients[node.accountId] = service
return grpcClients[node.accountId]!
}
Expand Down
11 changes: 9 additions & 2 deletions Sources/Hedera/HederaError.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
public struct HederaError: Error {
let message: String
public enum HederaError: Error {
case networkError(HederaNetworkError)
case queryPaymentExceedsMax
case message(String)
}

public struct HederaNetworkError: Error {
let status: Int
let statusMessage: String
}
7 changes: 3 additions & 4 deletions Sources/Hedera/Operator.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import Sodium

public typealias Signer = (_ message: Bytes) -> Bytes

public struct Operator {
struct Operator {
let id: AccountId
let signer: Signer
let publicKey: Ed25519PublicKey
Expand All @@ -12,7 +11,7 @@ public struct Operator {
/// - signer: closure that will be called to sign transactions.
/// Useful for requesting signing from a hardware wallet that won't give you the private key.
/// - publicKey: public key associated with the signer
public init(id: AccountId, signer: @escaping Signer, publicKey: Ed25519PublicKey) {
init(id: AccountId, signer: @escaping Signer, publicKey: Ed25519PublicKey) {
self.id = id
self.signer = signer
self.publicKey = publicKey
Expand All @@ -21,7 +20,7 @@ public struct Operator {
/// - Parameters:
/// - id: Account ID
/// - privateKey: private key that will be used to sign transactions.
public init(id: AccountId, privateKey: Ed25519PrivateKey) {
init(id: AccountId, privateKey: Ed25519PrivateKey) {
self.init(id: id, signer: privateKey.sign, publicKey: privateKey.publicKey)
}
}
Loading

0 comments on commit d17d3b7

Please sign in to comment.