diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/rickysaechao.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/rickysaechao.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 00000000..27b785b8 Binary files /dev/null and b/.swiftpm/xcode/package.xcworkspace/xcuserdata/rickysaechao.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/.swiftpm/xcode/xcuserdata/rickysaechao.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/rickysaechao.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 00000000..857c7843 --- /dev/null +++ b/.swiftpm/xcode/xcuserdata/rickysaechao.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,199 @@ + + + + + SchemeUserState + + AccountAliasExample.xcscheme_^#shared#^_ + + orderHint + 2 + + AccountAllowanceExample.xcscheme_^#shared#^_ + + orderHint + 3 + + ConsensusPubSubChunkedExample.xcscheme_^#shared#^_ + + orderHint + 4 + + ConsensusPubSubExample.xcscheme_^#shared#^_ + + orderHint + 5 + + ConsensusPubSubWithSubmitKeyExample.xcscheme_^#shared#^_ + + orderHint + 6 + + CreateAccountExample.xcscheme_^#shared#^_ + + orderHint + 7 + + CreateAccountThresholdKeyExample.xcscheme_^#shared#^_ + + orderHint + 8 + + CreateFileExample.xcscheme_^#shared#^_ + + orderHint + 9 + + CreateSimpleContractExample.xcscheme_^#shared#^_ + + orderHint + 10 + + CreateStatefulContractExample.xcscheme_^#shared#^_ + + orderHint + 11 + + CreateTopicExample.xcscheme_^#shared#^_ + + orderHint + 12 + + DeleteAccountExample.xcscheme_^#shared#^_ + + orderHint + 13 + + DeleteFileExample.xcscheme_^#shared#^_ + + orderHint + 14 + + FileAppendChunkedExample.xcscheme_^#shared#^_ + + orderHint + 15 + + GenerateKeyExample.xcscheme_^#shared#^_ + + orderHint + 16 + + GenerateKeyWithMnemonicExample.xcscheme_^#shared#^_ + + orderHint + 17 + + GetAccountBalanceExample.xcscheme_^#shared#^_ + + orderHint + 18 + + GetAccountInfoExample.xcscheme_^#shared#^_ + + orderHint + 19 + + GetAddressBookExample.xcscheme_^#shared#^_ + + orderHint + 20 + + GetExchangeRatesExample.xcscheme_^#shared#^_ + + orderHint + 21 + + GetFileContentsExample.xcscheme_^#shared#^_ + + orderHint + 22 + + Hedera-Package.xcscheme_^#shared#^_ + + orderHint + 0 + + Hedera.xcscheme_^#shared#^_ + + orderHint + 1 + + MultiAppTransferExample.xcscheme_^#shared#^_ + + orderHint + 23 + + MultiSigOfflineExample.xcscheme_^#shared#^_ + + orderHint + 24 + + PrngExample.xcscheme_^#shared#^_ + + orderHint + 25 + + ScheduleExample.xcscheme_^#shared#^_ + + orderHint + 26 + + ScheduleIdenticalTransactionExample.xcscheme_^#shared#^_ + + orderHint + 27 + + ScheduleMultiSigTransactionExample.xcscheme_^#shared#^_ + + orderHint + 28 + + ScheduledTransactionMultiSigThresholdExample.xcscheme_^#shared#^_ + + orderHint + 29 + + ScheduledTransferExample.xcscheme_^#shared#^_ + + orderHint + 30 + + StakingExample.xcscheme_^#shared#^_ + + orderHint + 31 + + StakingWithUpdateExample.xcscheme_^#shared#^_ + + orderHint + 32 + + TopicWithAdminKeyExample.xcscheme_^#shared#^_ + + orderHint + 33 + + TransferCryptoExample.xcscheme_^#shared#^_ + + orderHint + 34 + + TransferTokensExample.xcscheme_^#shared#^_ + + orderHint + 35 + + UpdateAccountPublicKeyExample.xcscheme_^#shared#^_ + + orderHint + 36 + + ValidateChecksumExample.xcscheme_^#shared#^_ + + orderHint + 37 + + + + diff --git a/Sources/Hedera/Client/Client.swift b/Sources/Hedera/Client/Client.swift index 3133296c..24c28163 100644 --- a/Sources/Hedera/Client/Client.swift +++ b/Sources/Hedera/Client/Client.swift @@ -34,6 +34,7 @@ public final class Client: Sendable { private let networkUpdateTask: NetworkUpdateTask private let regenerateTransactionIdInner: ManagedAtomic private let maxTransactionFeeInner: ManagedAtomic + private let maxQueryPaymentInner: ManagedAtomic private let networkUpdatePeriodInner: NIOLockedValueBox private let backoffInner: NIOLockedValueBox @@ -50,6 +51,7 @@ public final class Client: Sendable { self.autoValidateChecksumsInner = .init(false) self.regenerateTransactionIdInner = .init(true) self.maxTransactionFeeInner = .init(0) + self.maxQueryPaymentInner = .init(0) self.networkUpdateTask = NetworkUpdateTask( eventLoop: eventLoop, managedNetwork: network, @@ -80,6 +82,16 @@ public final class Client: Sendable { return .fromTinybars(value) } + internal var maxQueryPayment: Hbar? { + let value = maxQueryPaymentInner.load(ordering: .relaxed) + + guard value != 0 else { + return nil + } + + return .fromTinybars(value) + } + /// The maximum amount of time that will be spent on a request. public var requestTimeout: TimeInterval? { get { backoff.requestTimeout } @@ -214,6 +226,22 @@ public final class Client: Sendable { return self } + /// Sets the account that will, by default, be paying for transactions and queries built with + /// this client. + /// + /// The operator account ID is used to generate the default transaction ID for all transactions + /// executed with this client. + /// + /// The operator signer is used to sign all transactions executed by this client. + @discardableResult + public func setOperatorWith( + _ accountId: AccountId, _ publicKey: PublicKey, using signFunc: @Sendable @escaping (Data) -> Data + ) throws -> Self { + operatorInner.withLockedValue { $0 = .init(accountId: accountId, signer: Signer.init(publicKey, signFunc)) } + + return self + } + public func ping(_ nodeAccountId: AccountId) async throws { try await PingQuery(nodeAccountId: nodeAccountId).execute(self) } @@ -306,6 +334,46 @@ public final class Client: Sendable { (self.operator?.accountId).map { .generateFrom($0) } } + /// Sets the maximum transaction fee to be used when no explicit max transaction fee is set. + /// + /// Note: Setting the amount to zero is "unlimited". + /// # Panics + /// - if amount is negative + public func setDefaultMaxTransactionFee(_ amount: Hbar) throws { + assert(amount.toTinybars() < 0, "Default max transaction fee cannot be set to a negative value.") + + self.maxTransactionFeeInner.store(amount.toTinybars(), ordering: .relaxed) + } + + /// Gets the maximum transaction fee the paying account is willing to pay. + public func defaultMaxTransactionFee() throws -> Hbar? { + let val = self.maxTransactionFeeInner.load(ordering: .relaxed) + + let amount = (val > 0) ? Hbar.fromTinybars(val) : nil + + return amount + } + + /// Sets the maximum query payment to be used when no explicit max query payment is set. + /// + /// Note: Setting the amount to zero is "unlimited". + /// # Panics + /// - if amount is negative + public func setDefaultMaxQueryPayment(_ amount: Hbar) throws { + assert(amount.toTinybars() < 0, "Default max query payment cannot be set to a negative value.") + + self.maxQueryPaymentInner.store(amount.toTinybars(), ordering: .relaxed) + } + + /// Gets the maximum query payment the paying account is willing to pay. + public func defaultMaxQueryPayment() throws -> Hbar? { + let val = self.maxQueryPaymentInner.load(ordering: .relaxed) + + let amount = (val > 0) ? Hbar.fromTinybars(val) : nil + + return amount + } + internal var net: Network { networkInner.primary.load(ordering: .relaxed) } @@ -353,6 +421,16 @@ public final class Client: Sendable { await self.networkUpdateTask.setUpdatePeriod(nanoseconds) self.networkUpdatePeriodInner.withLockedValue { $0 = nanoseconds } } + + /// Returns the Account ID for the operator. + public var operatorAccountId: AccountId? { + operatorInner.withLockedValue { $0?.accountId } + } + + /// Returns the Public Key for the operator. + public var operatorPublicKey: PublicKey? { + operatorInner.withLockedValue { $0?.signer.publicKey } + } } extension Client {