diff --git a/Sources/Hedera/Account/AccountBalance.swift b/Sources/Hedera/Account/AccountBalance.swift
index 3e738d14..0ccb9700 100644
--- a/Sources/Hedera/Account/AccountBalance.swift
+++ b/Sources/Hedera/Account/AccountBalance.swift
@@ -21,7 +21,7 @@
import Foundation
import HederaProtobufs
-private struct TokenBalance {
+private struct TokenBalance: Sendable {
fileprivate let id: TokenId
fileprivate let balance: UInt64
fileprivate let decimals: UInt32
@@ -67,11 +67,10 @@ public struct AccountBalance: Sendable {
/// Token balances for the referenced account.
///
/// This access is *`O(n)`*.
- @available(*, deprecated, message: "use a mirror query")
public var tokenBalances: [TokenId: UInt64] { tokenBalancesInner }
// hack to work around deprecated warning
- private var tokenDecimalsInner: [TokenId: UInt32] {
+ public var tokenDecimalsInner: [TokenId: UInt32] {
Dictionary(uniqueKeysWithValues: tokensInner.map { ($0.id, $0.decimals) })
}
diff --git a/Sources/Hedera/Account/AccountCreateTransaction.swift b/Sources/Hedera/Account/AccountCreateTransaction.swift
index ef5535c4..d2b7a0fe 100644
--- a/Sources/Hedera/Account/AccountCreateTransaction.swift
+++ b/Sources/Hedera/Account/AccountCreateTransaction.swift
@@ -32,7 +32,7 @@ public final class AccountCreateTransaction: Transaction {
autoRenewPeriod: Duration? = .days(90),
autoRenewAccountId: AccountId? = nil,
accountMemo: String = "",
- maxAutomaticTokenAssociations: UInt32 = 0,
+ maxAutomaticTokenAssociations: Int32 = 0,
alias: EvmAddress? = nil,
stakedAccountId: AccountId? = nil,
stakedNodeId: UInt64? = nil,
@@ -59,7 +59,7 @@ public final class AccountCreateTransaction: Transaction {
self.receiverSignatureRequired = data.receiverSigRequired
self.autoRenewPeriod = data.hasAutoRenewPeriod ? .fromProtobuf(data.autoRenewPeriod) : nil
self.accountMemo = data.memo
- self.maxAutomaticTokenAssociations = UInt32(data.maxAutomaticTokenAssociations)
+ self.maxAutomaticTokenAssociations = data.maxAutomaticTokenAssociations
if let id = data.stakedID {
switch id {
@@ -175,7 +175,7 @@ public final class AccountCreateTransaction: Transaction {
}
/// The maximum number of tokens that an Account can be implicitly associated with.
- public var maxAutomaticTokenAssociations: UInt32 {
+ public var maxAutomaticTokenAssociations: Int32 {
willSet {
ensureNotFrozen()
}
@@ -183,7 +183,7 @@ public final class AccountCreateTransaction: Transaction {
/// Sets the maximum number of tokens that an Account can be implicitly associated with.
@discardableResult
- public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: UInt32) -> Self {
+ public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: Int32) -> Self {
self.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
return self
@@ -288,7 +288,7 @@ extension AccountCreateTransaction: ToProtobuf {
autoRenewPeriod?.toProtobufInto(&proto.autoRenewPeriod)
// autoRenewAccountId?.toProtobufInto(&proto.autoRenewAccount)
proto.memo = accountMemo
- proto.maxAutomaticTokenAssociations = Int32(maxAutomaticTokenAssociations)
+ proto.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
if let alias = alias {
proto.alias = alias.data
diff --git a/Sources/Hedera/Account/AccountInfo.swift b/Sources/Hedera/Account/AccountInfo.swift
index 05165e18..9c60c1b8 100644
--- a/Sources/Hedera/Account/AccountInfo.swift
+++ b/Sources/Hedera/Account/AccountInfo.swift
@@ -44,7 +44,7 @@ public struct AccountInfo: Sendable {
autoRenewPeriod: Duration?,
accountMemo: String,
ownedNfts: UInt64,
- maxAutomaticTokenAssociations: UInt32,
+ maxAutomaticTokenAssociations: Int32,
aliasKey: PublicKey?,
ethereumNonce: UInt64,
ledgerId: LedgerId,
@@ -140,7 +140,7 @@ public struct AccountInfo: Sendable {
public let ownedNfts: UInt64
/// The maximum number of tokens that an Account can be implicitly associated with.
- public let maxAutomaticTokenAssociations: UInt32
+ public let maxAutomaticTokenAssociations: Int32
/// The public key which aliases to this account.
public let aliasKey: PublicKey?
@@ -193,7 +193,7 @@ extension AccountInfo: TryProtobufCodable {
autoRenewPeriod: .fromProtobuf(autoRenewPeriod),
accountMemo: proto.memo,
ownedNfts: UInt64(proto.ownedNfts),
- maxAutomaticTokenAssociations: UInt32(proto.maxAutomaticTokenAssociations),
+ maxAutomaticTokenAssociations: proto.maxAutomaticTokenAssociations,
aliasKey: try .fromAliasBytes(proto.alias),
ethereumNonce: UInt64(proto.ethereumNonce),
ledgerId: .fromBytes(proto.ledgerID),
@@ -217,7 +217,7 @@ extension AccountInfo: TryProtobufCodable {
autoRenewPeriod?.toProtobufInto(&proto.autoRenewPeriod)
proto.memo = accountMemo
proto.ownedNfts = Int64(ownedNfts)
- proto.maxAutomaticTokenAssociations = Int32(maxAutomaticTokenAssociations)
+ proto.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
proto.alias = aliasKey?.toProtobufBytes() ?? Data()
proto.ethereumNonce = Int64(ethereumNonce)
proto.ledgerID = ledgerId.bytes
diff --git a/Sources/Hedera/Account/AccountUpdateTransaction.swift b/Sources/Hedera/Account/AccountUpdateTransaction.swift
index 0d8f2659..3d2295d7 100644
--- a/Sources/Hedera/Account/AccountUpdateTransaction.swift
+++ b/Sources/Hedera/Account/AccountUpdateTransaction.swift
@@ -73,7 +73,7 @@ public final class AccountUpdateTransaction: Transaction {
self.accountMemo = data.hasMemo ? data.memo.value : nil
self.maxAutomaticTokenAssociations =
data.hasMaxAutomaticTokenAssociations
- ? UInt32(data.maxAutomaticTokenAssociations.value) : nil
+ ? data.maxAutomaticTokenAssociations.value : nil
self.stakedAccountId = stakedAccountId
self.stakedNodeId = stakedNodeId
self.declineStakingReward = data.hasDeclineReward ? data.declineReward.value : nil
@@ -227,7 +227,7 @@ public final class AccountUpdateTransaction: Transaction {
}
/// The maximum number of tokens that an Account can be implicitly associated with.
- public var maxAutomaticTokenAssociations: UInt32? {
+ public var maxAutomaticTokenAssociations: Int32? {
willSet {
ensureNotFrozen()
}
@@ -235,7 +235,7 @@ public final class AccountUpdateTransaction: Transaction {
/// Sets the maximum number of tokens that an Account can be implicitly associated with.
@discardableResult
- public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: UInt32) -> Self {
+ public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: Int32) -> Self {
self.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
return self
@@ -350,7 +350,7 @@ extension AccountUpdateTransaction: ToProtobuf {
if let maxAutomaticTokenAssociations = maxAutomaticTokenAssociations {
proto.maxAutomaticTokenAssociations = Google_Protobuf_Int32Value(
- Int32(maxAutomaticTokenAssociations))
+ maxAutomaticTokenAssociations)
}
if let stakedAccountId = stakedAccountId {
diff --git a/Sources/Hedera/AnyTransaction.swift b/Sources/Hedera/AnyTransaction.swift
index f14d80b8..5e9c617d 100644
--- a/Sources/Hedera/AnyTransaction.swift
+++ b/Sources/Hedera/AnyTransaction.swift
@@ -51,6 +51,7 @@ internal enum ServicesTransactionDataList {
case tokenMint([Proto_TokenMintTransactionBody])
case tokenPause([Proto_TokenPauseTransactionBody])
case tokenRevokeKyc([Proto_TokenRevokeKycTransactionBody])
+ case tokenReject([Proto_TokenRejectTransactionBody])
case tokenUnfreeze([Proto_TokenUnfreezeAccountTransactionBody])
case tokenUnpause([Proto_TokenUnpauseTransactionBody])
case tokenUpdate([Proto_TokenUpdateTransactionBody])
@@ -235,6 +236,10 @@ internal enum ServicesTransactionDataList {
array.append(data)
self = .tokenUpdateNfts(array)
+ case (.tokenReject(var array), .tokenReject(let data)):
+ array.append(data)
+ self = .tokenReject(array)
+
default:
throw HError.fromProtobuf("mismatched transaction types")
}
@@ -302,6 +307,7 @@ extension ServicesTransactionDataList: TryFromProtobuf {
case .nodeDelete: throw HError.fromProtobuf("Unsupported transaction `NodeDeleteTransaction`")
case .nodeCreate: throw HError.fromProtobuf("Unsupported transaction `NodeCreateTransaction`")
case .nodeUpdate: throw HError.fromProtobuf("Unsupported transaction `NodeUpdateTransaction`")
+ case .tokenReject(let data): value = .tokenReject([data])
}
for transaction in iter {
diff --git a/Sources/Hedera/Contract/ContractCreateFlow.swift b/Sources/Hedera/Contract/ContractCreateFlow.swift
index ad309100..9ccdb3d8 100644
--- a/Sources/Hedera/Contract/ContractCreateFlow.swift
+++ b/Sources/Hedera/Contract/ContractCreateFlow.swift
@@ -52,7 +52,7 @@ public final class ContractCreateFlow {
constructorParameters: Data = Data(),
gas: UInt64 = 0,
initialBalance: Hbar = .zero,
- maxAutomaticTokenAssociations: UInt32 = 0,
+ maxAutomaticTokenAssociations: Int32 = 0,
declineStakingReward: Bool = false,
adminKey: Key? = nil,
autoRenewAccountId: AccountId? = nil,
@@ -79,7 +79,7 @@ public final class ContractCreateFlow {
fileprivate var constructorParameters: Data
fileprivate var gas: UInt64
fileprivate var initialBalance: Hbar
- fileprivate var maxAutomaticTokenAssociations: UInt32
+ fileprivate var maxAutomaticTokenAssociations: Int32
fileprivate var declineStakingReward: Bool
fileprivate var adminKey: Key?
// fileprivate var proxyAccountId: AccountId?
@@ -220,7 +220,7 @@ public final class ContractCreateFlow {
}
/// The maximum number of tokens that the contract can be automatically associated with.
- public var maxAutomaticTokenAssociations: UInt32 {
+ public var maxAutomaticTokenAssociations: Int32 {
get { contractCreateData.maxAutomaticTokenAssociations }
set(value) { contractCreateData.maxAutomaticTokenAssociations = value }
}
@@ -229,7 +229,7 @@ public final class ContractCreateFlow {
///
/// - Returns: `self`
@discardableResult
- public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: UInt32) -> Self {
+ public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: Int32) -> Self {
self.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
return self
diff --git a/Sources/Hedera/Contract/ContractCreateTransaction.swift b/Sources/Hedera/Contract/ContractCreateTransaction.swift
index e3bc54a2..92f0fbdf 100644
--- a/Sources/Hedera/Contract/ContractCreateTransaction.swift
+++ b/Sources/Hedera/Contract/ContractCreateTransaction.swift
@@ -56,7 +56,7 @@ public final class ContractCreateTransaction: Transaction {
autoRenewPeriod: Duration? = .days(90),
constructorParameters: Data? = nil,
contractMemo: String = "",
- maxAutomaticTokenAssociations: UInt32 = 0,
+ maxAutomaticTokenAssociations: Int32 = 0,
autoRenewAccountId: AccountId? = nil,
stakedAccountId: AccountId? = nil,
stakedNodeId: UInt64? = nil,
@@ -117,7 +117,7 @@ public final class ContractCreateTransaction: Transaction {
self.autoRenewPeriod = .fromProtobuf(data.autoRenewPeriod)
self.constructorParameters = !data.constructorParameters.isEmpty ? data.constructorParameters : nil
self.contractMemo = data.memo
- self.maxAutomaticTokenAssociations = UInt32(data.maxAutomaticTokenAssociations)
+ self.maxAutomaticTokenAssociations = data.maxAutomaticTokenAssociations
self.autoRenewAccountId = data.hasAutoRenewAccountID ? try .fromProtobuf(data.autoRenewAccountID) : nil
self.stakedAccountId = stakedAccountId
self.stakedNodeId = stakedNodeId
@@ -285,7 +285,7 @@ public final class ContractCreateTransaction: Transaction {
}
/// The maximum number of tokens that this contract can be automatically associated with.
- public var maxAutomaticTokenAssociations: UInt32 {
+ public var maxAutomaticTokenAssociations: Int32 {
willSet {
ensureNotFrozen()
}
@@ -293,7 +293,7 @@ public final class ContractCreateTransaction: Transaction {
/// Sets the maximum number of tokens that this contract can be automatically associated with.
@discardableResult
- public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: UInt32) -> Self {
+ public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: Int32) -> Self {
self.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
return self
diff --git a/Sources/Hedera/Contract/ContractInfo.swift b/Sources/Hedera/Contract/ContractInfo.swift
index b0393883..0370bae5 100644
--- a/Sources/Hedera/Contract/ContractInfo.swift
+++ b/Sources/Hedera/Contract/ContractInfo.swift
@@ -59,7 +59,7 @@ public struct ContractInfo {
public let autoRenewAccountId: AccountId?
/// The maximum number of tokens that a contract can be implicitly associated with.
- public let maxAutomaticTokenAssociations: UInt32
+ public let maxAutomaticTokenAssociations: Int32
/// Ledger ID for the network the response was returned from.
public let ledgerId: LedgerId
@@ -103,7 +103,7 @@ extension ContractInfo: TryProtobufCodable {
balance: .fromTinybars(Int64(proto.balance)),
isDeleted: proto.deleted,
autoRenewAccountId: try .fromProtobuf(autoRenewAccountId),
- maxAutomaticTokenAssociations: UInt32(proto.maxAutomaticTokenAssociations),
+ maxAutomaticTokenAssociations: proto.maxAutomaticTokenAssociations,
ledgerId: .fromBytes(proto.ledgerID),
stakingInfo: try .fromProtobuf(proto.stakingInfo)
)
@@ -122,7 +122,7 @@ extension ContractInfo: TryProtobufCodable {
proto.balance = UInt64(balance.toTinybars())
proto.deleted = isDeleted
autoRenewAccountId?.toProtobufInto(&proto.autoRenewAccountID)
- proto.maxAutomaticTokenAssociations = Int32(maxAutomaticTokenAssociations)
+ proto.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
proto.ledgerID = ledgerId.bytes
proto.stakingInfo = stakingInfo.toProtobuf()
}
diff --git a/Sources/Hedera/Contract/ContractUpdateTransaction.swift b/Sources/Hedera/Contract/ContractUpdateTransaction.swift
index b27eec12..a6ab9323 100644
--- a/Sources/Hedera/Contract/ContractUpdateTransaction.swift
+++ b/Sources/Hedera/Contract/ContractUpdateTransaction.swift
@@ -32,7 +32,7 @@ public final class ContractUpdateTransaction: Transaction {
adminKey: Key? = nil,
autoRenewPeriod: Duration? = nil,
contractMemo: String? = nil,
- maxAutomaticTokenAssociations: UInt32? = nil,
+ maxAutomaticTokenAssociations: Int32? = nil,
autoRenewAccountId: AccountId? = nil,
proxyAccountId: AccountId? = nil,
stakedAccountId: AccountId? = nil,
@@ -87,7 +87,7 @@ public final class ContractUpdateTransaction: Transaction {
self.autoRenewPeriod = data.hasAutoRenewPeriod ? .fromProtobuf(data.autoRenewPeriod) : nil
self.contractMemo = memo
self.maxAutomaticTokenAssociations =
- data.hasMaxAutomaticTokenAssociations ? UInt32(data.maxAutomaticTokenAssociations.value) : nil
+ data.hasMaxAutomaticTokenAssociations ? data.maxAutomaticTokenAssociations.value : nil
self.autoRenewAccountId = data.hasAutoRenewAccountID ? try .fromProtobuf(data.autoRenewAccountID) : nil
self.proxyAccountId = data.hasProxyAccountID ? try .fromProtobuf(data.proxyAccountID) : nil
self.stakedAccountId = stakedAccountId
@@ -180,7 +180,7 @@ public final class ContractUpdateTransaction: Transaction {
}
/// The maximum number of tokens that this contract can be automatically associated with.
- public var maxAutomaticTokenAssociations: UInt32? {
+ public var maxAutomaticTokenAssociations: Int32? {
willSet {
ensureNotFrozen()
}
@@ -188,7 +188,7 @@ public final class ContractUpdateTransaction: Transaction {
/// Sets the maximum number of tokens that this contract can be automatically associated with.
@discardableResult
- public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: UInt32?) -> Self {
+ public func maxAutomaticTokenAssociations(_ maxAutomaticTokenAssociations: Int32?) -> Self {
self.maxAutomaticTokenAssociations = maxAutomaticTokenAssociations
return self
diff --git a/Sources/Hedera/FeeSchedule/RequestType.swift b/Sources/Hedera/FeeSchedule/RequestType.swift
index 57cbf914..d6373c97 100644
--- a/Sources/Hedera/FeeSchedule/RequestType.swift
+++ b/Sources/Hedera/FeeSchedule/RequestType.swift
@@ -256,8 +256,8 @@ public enum RequestType {
/// Delete a node
case nodeDelete
- /// Get the info for a node
- case nodeGetInfo
+ /// Reject a Token
+ case tokenReject
// this literally can't be smaller.
// swiftlint:disable:next function_body_length
@@ -341,7 +341,7 @@ public enum RequestType {
case .nodeCreate: self = .nodeCreate
case .nodeDelete: self = .nodeDelete
case .nodeUpdate: self = .nodeUpdate
- case .nodeGetInfo: self = .nodeGetInfo
+ case .tokenReject: self = .tokenReject
case .UNRECOGNIZED(let code):
throw HError.fromProtobuf("unrecognized RequestType: `\(code)`")
@@ -427,7 +427,7 @@ public enum RequestType {
case .nodeCreate: return .nodeCreate
case .nodeUpdate: return .nodeUpdate
case .nodeDelete: return .nodeDelete
- case .nodeGetInfo: return .nodeGetInfo
+ case .tokenReject: return .tokenReject
}
}
}
diff --git a/Sources/Hedera/Schedule/ScheduleInfo.swift b/Sources/Hedera/Schedule/ScheduleInfo.swift
index ba995c2a..5278ceb8 100644
--- a/Sources/Hedera/Schedule/ScheduleInfo.swift
+++ b/Sources/Hedera/Schedule/ScheduleInfo.swift
@@ -115,6 +115,7 @@ public struct ScheduleInfo: Sendable {
case .nodeCreate(let data): proto.data = .nodeCreate(data)
case .nodeUpdate(let data): proto.data = .nodeUpdate(data)
case .nodeDelete(let data): proto.data = .nodeDelete(data)
+ case .tokenReject(let data): proto.data = .tokenReject(data)
case nil: break
}
diff --git a/Sources/Hedera/Status.swift b/Sources/Hedera/Status.swift
index 45f5514d..4a3a3b18 100644
--- a/Sources/Hedera/Status.swift
+++ b/Sources/Hedera/Status.swift
@@ -946,6 +946,87 @@ public enum Status: Equatable {
/// NFT serial numbers are missing in the TokenUpdateNftsTransactionBody
case missingSerialNumbers // = 336
+ /// Admin key is not set on token
+
+ case tokenHasNoAdminKey // = 337
+
+ /// A transaction failed because the consensus node identified is
+ /// deleted from the address book.
+ case nodeDeleted // = 338
+
+ /// A transaction failed because the consensus node identified is not valid or
+ /// does not exist in state.
+ case invalidNodeID // = 339
+
+ /// A transaction failed because one or more entries in the list of
+ /// service endpoints for the `gossip_endpoint` field is invalid.
+ /// The most common cause for this response is a service endpoint that has
+ /// the domain name (DNS) set rather than address and port.
+ case invalidGossipEndpoint // = 340
+
+ /// A transaction failed because the node account identifier provided
+ /// does not exist or is not valid.
+ /// One common source of this error is providing a node account identifier
+ /// using the "alias" form rather than "numeric" form.
+ case invalidNodeAccountID // = 341
+
+ /// A transaction failed because the description field cannot be encoded
+ /// as UTF-8 or is more than 100 bytes when encoded.
+ case invalidNodeDescription // = 342
+
+ /// A transaction failed because one or more entries in the list of
+ /// service endpoints for the `service_endpoint` field is invalid.
+ case invalidServiceEndpoint // = 343
+
+ /// A transaction failed because the TLS certificate provided for the
+ /// node is missing or invalid.
+ case invalidGossipCaCertificate // = 344
+
+ /// A transaction failed because the hash provided for the gRPC certificate
+ /// is present but invalid.
+ case invalidGrpcCertificate // = 345
+
+ /// The maximum automatic associations value is not valid.
+ case invalidMaxAutoAssociations // = 346
+
+ /// The maximum number of nodes allowed in the address book have been created.
+ case maxNodesCreated // = 347
+
+ /// In ServiceEndpoint, domain_name and ipAddressV4 are mutually exclusive
+ case ipFqdnCannotBeSetForSameEndpoint // = 348
+
+ /// Fully qualified domain name is not allowed in gossip_endpoint
+ case gossipEndpointCannotHaveFqdn // = 349
+
+ /// In ServiceEndpoint, domain_name size too large
+ case fqdnSizeTooLarge // = 350
+
+ /// ServiceEndpoint is invalid
+ case invalidEndpoint // = 351
+
+ /// The number of gossip endpoints exceeds the limit
+ case gossipEndpointsExceededLimit // = 352
+
+ /// The transaction attempted to use duplicate `TokenReference`
+ case tokenReferenceRepeated // = 353
+
+ /// The account id specified as the owner in `TokenReject` is invalid or does not exist.
+ case invalidOwnerID // = 354
+
+ /// The transaction attempted to use more than the allowed number of `TokenReference`.
+ case tokenReferenceListSizeLimitExceeded // = 355
+
+ /// The number of service endpoints exceeds the limit
+ case serviceEndpointsExceededLimit // = 356
+
+ /// The IPv4 address is invalid
+ case invalidIpv4Address // = 357
+
+ /// The transaction attempted to use empty `TokenReference` list.
+ case emptyTokenReferenceList // = 358
+
+ /// The node account is not allowed to be updated
+ case updateNodeAccountNotAllowed // = 359
/// swift-format-ignore: AlwaysUseLowerCamelCase
case unrecognized(Int32)
@@ -1249,6 +1330,29 @@ public enum Status: Equatable {
case 334: self = .tokenHasNoMetadataKey
case 335: self = .missingTokenMetadata
case 336: self = .missingSerialNumbers
+ case 337: self = .tokenHasNoAdminKey
+ case 338: self = .nodeDeleted
+ case 339: self = .invalidNodeID
+ case 340: self = .invalidGossipEndpoint
+ case 341: self = .invalidNodeAccountID
+ case 342: self = .invalidNodeDescription
+ case 343: self = .invalidServiceEndpoint
+ case 344: self = .invalidGossipCaCertificate
+ case 345: self = .invalidGrpcCertificate
+ case 346: self = .invalidMaxAutoAssociations
+ case 347: self = .maxNodesCreated
+ case 348: self = .ipFqdnCannotBeSetForSameEndpoint
+ case 349: self = .gossipEndpointCannotHaveFqdn
+ case 350: self = .fqdnSizeTooLarge
+ case 351: self = .invalidEndpoint
+ case 352: self = .gossipEndpointsExceededLimit
+ case 353: self = .tokenReferenceRepeated
+ case 354: self = .invalidOwnerID
+ case 355: self = .tokenReferenceListSizeLimitExceeded
+ case 356: self = .serviceEndpointsExceededLimit
+ case 357: self = .invalidIpv4Address
+ case 358: self = .emptyTokenReferenceList
+ case 359: self = .updateNodeAccountNotAllowed
default: self = .unrecognized(rawValue)
}
}
@@ -1550,6 +1654,29 @@ public enum Status: Equatable {
case .tokenHasNoMetadataKey: return 334
case .missingTokenMetadata: return 335
case .missingSerialNumbers: return 336
+ case .tokenHasNoAdminKey: return 337
+ case .nodeDeleted: return 338
+ case .invalidNodeID: return 339
+ case .invalidGossipEndpoint: return 340
+ case .invalidNodeAccountID: return 341
+ case .invalidNodeDescription: return 342
+ case .invalidServiceEndpoint: return 343
+ case .invalidGossipCaCertificate: return 344
+ case .invalidGrpcCertificate: return 345
+ case .invalidMaxAutoAssociations: return 346
+ case .maxNodesCreated: return 347
+ case .ipFqdnCannotBeSetForSameEndpoint: return 348
+ case .gossipEndpointCannotHaveFqdn: return 349
+ case .fqdnSizeTooLarge: return 350
+ case .invalidEndpoint: return 351
+ case .gossipEndpointsExceededLimit: return 352
+ case .tokenReferenceRepeated: return 353
+ case .invalidOwnerID: return 354
+ case .tokenReferenceListSizeLimitExceeded: return 355
+ case .serviceEndpointsExceededLimit: return 356
+ case .invalidIpv4Address: return 357
+ case .emptyTokenReferenceList: return 358
+ case .updateNodeAccountNotAllowed: return 359
case .unrecognized(let i): return i
}
}
@@ -1854,6 +1981,29 @@ extension Status: CaseIterable {
.tokenHasNoMetadataKey,
.missingTokenMetadata,
.missingSerialNumbers,
+ .tokenHasNoAdminKey,
+ .nodeDeleted,
+ .invalidNodeID,
+ .invalidGossipEndpoint,
+ .invalidNodeAccountID,
+ .invalidNodeDescription,
+ .invalidServiceEndpoint,
+ .invalidGossipCaCertificate,
+ .invalidGrpcCertificate,
+ .invalidMaxAutoAssociations,
+ .maxNodesCreated,
+ .ipFqdnCannotBeSetForSameEndpoint,
+ .gossipEndpointCannotHaveFqdn,
+ .fqdnSizeTooLarge,
+ .invalidEndpoint,
+ .gossipEndpointsExceededLimit,
+ .tokenReferenceRepeated,
+ .invalidOwnerID,
+ .tokenReferenceListSizeLimitExceeded,
+ .serviceEndpointsExceededLimit,
+ .invalidIpv4Address,
+ .emptyTokenReferenceList,
+ .updateNodeAccountNotAllowed,
]
}
@@ -2156,6 +2306,29 @@ extension Status {
334: "TOKEN_HAS_NO_METADATA_KEY",
335: "MISSING_TOKEN_METADATA",
336: "MISSING_SERIAL_NUMBERS",
+ 337: "TOKEN_HAS_NO_ADMIN_KEY",
+ 338: "NODE_DELETED",
+ 339: "INVALID_NODE_ID",
+ 340: "INVALID_GOSSIP_ENDPOINT",
+ 341: "INVALID_NODE_ACCOUNT_ID",
+ 342: "INVALID_NODE_DESCRIPTION",
+ 343: "INVALID_SERVICE_ENDPOINT",
+ 344: "INVALID_GOSSIP_CA_CERTIFICATE",
+ 345: "INVALID_GRPC_CERTIFICATE",
+ 346: "INVALID_MAX_AUTO_ASSOCIATIONS",
+ 347: "MAX_NODES_CREATED",
+ 348: "IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT",
+ 349: "GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN",
+ 350: "FQDN_SIZE_TOO_LARGE",
+ 351: "INVALID_ENDPOINT",
+ 352: "GOSSIP_ENDPOINTS_EXCEEDED_LIMIT",
+ 353: "TOKEN_REFERENCE_REPEATED",
+ 354: "INVALID_OWNER_ID",
+ 355: "TOKEN_REFERENCE_LIST_SIZE_LIMIT_EXCEEDED",
+ 356: "SERVICE_ENDPOINTS_EXCEEDED_LIMIT",
+ 357: "INVALID_IPV4_ADDRESS",
+ 358: "EMPTY_TOKEN_REFERENCE_LIST",
+ 359: "UPDATE_NODE_ACCOUNT_NOT_ALLOWED",
]
}
diff --git a/Sources/Hedera/Token/TokenRejectTransaction.swift b/Sources/Hedera/Token/TokenRejectTransaction.swift
new file mode 100644
index 00000000..641e31b0
--- /dev/null
+++ b/Sources/Hedera/Token/TokenRejectTransaction.swift
@@ -0,0 +1,155 @@
+/*
+ *
+ * Hedera Swift SDK
+ *
+ * Copyright (C) 2022 - 2024 Hedera Hashgraph, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import GRPC
+import HederaProtobufs
+
+/// Reject undesired Tokens or NFTs.
+public final class TokenRejectTransaction: Transaction {
+ /// Create a new `TokenRejectTransaction`.
+ public init(
+ owner: AccountId? = nil,
+ tokenIds: [TokenId] = [],
+ nftIds: [NftId] = []
+ ) {
+ self.owner = owner
+ self.tokenIds = tokenIds
+ self.nftIds = nftIds
+
+ super.init()
+ }
+
+ internal init(protobuf proto: Proto_TransactionBody, _ data: Proto_TokenRejectTransactionBody) throws {
+ self.owner = data.hasOwner ? try .fromProtobuf(data.owner) : nil
+ self.tokenIds = []
+ self.nftIds = []
+
+ for reference in data.rejections {
+ switch reference.tokenIdentifier {
+ case .fungibleToken(let tokenId):
+ self.tokenIds.append(TokenId(protobuf: tokenId))
+ case .nft(let nftId):
+ self.nftIds.append(NftId(protobuf: nftId))
+ default:
+ throw HError.fromProtobuf("invalid token identifier")
+ }
+ }
+
+ try super.init(protobuf: proto)
+ }
+
+ /// The account holding the token to be rejected.
+ public var owner: AccountId? {
+ willSet {
+ ensureNotFrozen()
+ }
+ }
+
+ /// Sets account holding the token to be rejected.
+ @discardableResult
+ public func owner(_ owner: AccountId) -> Self {
+ self.owner = owner
+
+ return self
+ }
+
+ public var tokenIds: [TokenId] {
+ willSet {
+ ensureNotFrozen()
+ }
+ }
+
+ @discardableResult
+ public func tokenIds(_ tokenIds: [TokenId]) -> Self {
+ self.tokenIds = tokenIds
+
+ return self
+ }
+
+ /// Append a fungible token to the list of tokens to be rejected.
+ @discardableResult
+ public func addTokenId(_ tokenId: TokenId) -> Self {
+ self.tokenIds.append(tokenId)
+
+ return self
+ }
+
+ public var nftIds: [NftId] {
+ willSet {
+ ensureNotFrozen()
+ }
+ }
+
+ @discardableResult
+ public func nftIds(_ nftIds: [NftId]) -> Self {
+ self.nftIds = nftIds
+
+ return self
+ }
+
+ /// Append an NFT to the list of tokens to be rejected.
+ @discardableResult
+ public func addNftId(_ nftId: NftId) -> Self {
+ self.nftIds.append(nftId)
+
+ return self
+ }
+
+ internal override func validateChecksums(on ledgerId: LedgerId) throws {
+ try owner?.validateChecksums(on: ledgerId)
+ try super.validateChecksums(on: ledgerId)
+ }
+
+ internal override func transactionExecute(_ channel: GRPCChannel, _ request: Proto_Transaction) async throws
+ -> Proto_TransactionResponse
+ {
+ try await Proto_TokenServiceAsyncClient(channel: channel).deleteToken(request)
+ }
+
+ internal override func toTransactionDataProtobuf(_ chunkInfo: ChunkInfo) -> Proto_TransactionBody.OneOf_Data {
+ _ = chunkInfo.assertSingleTransaction()
+
+ return .tokenReject(toProtobuf())
+ }
+}
+
+extension TokenRejectTransaction: ToProtobuf {
+ internal typealias Protobuf = Proto_TokenRejectTransactionBody
+
+ internal func toProtobuf() -> Protobuf {
+ .with { [self] proto in
+ owner?.toProtobufInto(&proto.owner)
+
+ for tokenId in self.tokenIds {
+ proto.rejections.append(.with { $0.fungibleToken = tokenId.toProtobuf() })
+ }
+
+ for nftId in self.nftIds {
+ proto.rejections.append(.with { $0.nft = nftId.toProtobuf() })
+ }
+ }
+ }
+}
+
+extension TokenRejectTransaction {
+ internal func toSchedulableTransactionData() -> Proto_SchedulableTransactionBody.OneOf_Data {
+ .tokenReject(toProtobuf())
+ }
+}
diff --git a/Sources/Hedera/Transaction/Transaction+FromProtobuf.swift b/Sources/Hedera/Transaction/Transaction+FromProtobuf.swift
index 10e99e23..1eaee783 100644
--- a/Sources/Hedera/Transaction/Transaction+FromProtobuf.swift
+++ b/Sources/Hedera/Transaction/Transaction+FromProtobuf.swift
@@ -201,6 +201,10 @@ extension Transaction {
case .tokenUpdateNfts(let value):
let value = try intoOnlyValue(value)
return try TokenUpdateNftsTransaction(protobuf: firstBody, value)
+
+ case .tokenReject(let value):
+ let value = try intoOnlyValue(value)
+ return try TokenRejectTransaction(protobuf: firstBody, value)
}
}
}
diff --git a/Sources/HederaProtobufs/Services/basic_types.pb.swift b/Sources/HederaProtobufs/Services/basic_types.pb.swift
index ae694152..8bd42b87 100644
--- a/Sources/HederaProtobufs/Services/basic_types.pb.swift
+++ b/Sources/HederaProtobufs/Services/basic_types.pb.swift
@@ -742,8 +742,8 @@ public enum Proto_HederaFunctionality: SwiftProtobuf.Enum {
case nodeDelete // = 91
///*
- /// Get Node information
- case nodeGetInfo // = 92
+ /// Transfer one or more token balances held by the requesting account to the treasury for each token type.
+ case tokenReject // = 92
case UNRECOGNIZED(Int)
public init() {
@@ -830,7 +830,7 @@ public enum Proto_HederaFunctionality: SwiftProtobuf.Enum {
case 89: self = .nodeCreate
case 90: self = .nodeUpdate
case 91: self = .nodeDelete
- case 92: self = .nodeGetInfo
+ case 92: self = .tokenReject
default: self = .UNRECOGNIZED(rawValue)
}
}
@@ -915,7 +915,7 @@ public enum Proto_HederaFunctionality: SwiftProtobuf.Enum {
case .nodeCreate: return 89
case .nodeUpdate: return 90
case .nodeDelete: return 91
- case .nodeGetInfo: return 92
+ case .tokenReject: return 92
case .UNRECOGNIZED(let i): return i
}
}
@@ -1005,7 +1005,7 @@ extension Proto_HederaFunctionality: CaseIterable {
.nodeCreate,
.nodeUpdate,
.nodeDelete,
- .nodeGetInfo,
+ .tokenReject,
]
}
@@ -2439,26 +2439,35 @@ public struct Proto_CurrentAndNextFeeSchedule {
}
///*
-/// Contains the IP address and the port representing a service endpoint of a Node in a network. Used
-/// to reach the Hedera API and submit transactions to the network.
+/// Contains the IP address and the port representing a service endpoint of
+/// a Node in a network. Used to reach the Hedera API and submit transactions
+/// to the network.
+///
+/// When the `domain_name` field is set, the `ipAddressV4` field
+/// MUST NOT be set.
+/// When the `ipAddressV4` field is set, the `domain_name` field
+/// MUST NOT be set.
public struct Proto_ServiceEndpoint {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
///*
- /// The 32-bit IPv4 address of the node encoded in left to right order (e.g. 127.0.0.1 has 127
- /// as its first byte)
+ /// The 4-byte IPv4 address of the endpoint encoded in left to right order
+ /// (e.g. 127.0.0.1 has bytes [127, 0, 0, 1])
public var ipAddressV4: Data = Data()
///*
- /// The port of the node
+ /// The port of the service endpoint
public var port: Int32 = 0
///*
- /// A node domain name
- /// This MUST be the fully qualified domain name of the node.
+ /// A node domain name.
+ /// This MUST be the fully qualified domain(DNS) name of the node.
/// This value MUST NOT be more than 253 characters.
+ /// domain_name and ipAddressV4 are mutually exclusive.
+ /// When the `domain_name` field is set, the `ipAddressV4` field MUST NOT be set.
+ /// When the `ipAddressV4` field is set, the `domain_name` field MUST NOT be set.
public var domainName: String = String()
public var unknownFields = SwiftProtobuf.UnknownStorage()
@@ -2470,8 +2479,8 @@ public struct Proto_ServiceEndpoint {
/// The data about a node, including its service endpoints and the Hedera account to be paid for
/// services provided by the node (that is, queries answered and transactions submitted.)
///
-/// If the serviceEndpoint list is not set, or empty, then the endpoint given by the
-/// (deprecated) ipAddress and portno fields should be used.
+/// If the `serviceEndpoint` list is not set, or empty, then the endpoint given by the
+/// (deprecated) `ipAddress` and `portno` fields should be used.
///
/// All fields are populated in the 0.0.102 address book file while only fields that start with # are
/// populated in the 0.0.101 address book file.
@@ -3071,7 +3080,7 @@ extension Proto_HederaFunctionality: SwiftProtobuf._ProtoNameProviding {
89: .same(proto: "NodeCreate"),
90: .same(proto: "NodeUpdate"),
91: .same(proto: "NodeDelete"),
- 92: .same(proto: "NodeGetInfo"),
+ 92: .same(proto: "TokenReject"),
]
}
diff --git a/Sources/HederaProtobufs/Services/contract_create.pb.swift b/Sources/HederaProtobufs/Services/contract_create.pb.swift
index 341d8b12..3f6ed9c4 100644
--- a/Sources/HederaProtobufs/Services/contract_create.pb.swift
+++ b/Sources/HederaProtobufs/Services/contract_create.pb.swift
@@ -215,8 +215,12 @@ public struct Proto_ContractCreateTransactionBody {
}
///*
- /// The maximum number of tokens that this contract can be automatically associated
- /// with (i.e., receive air-drops from).
+ /// The maximum number of tokens that can be auto-associated with the contract.
+ /// If this is less than or equal to `used_auto_associations`, or 0, then this contract
+ /// MUST manually associate with a token before transacting in that token.
+ /// This value MAY also be `-1` to indicate no limit.
+ /// This value MUST NOT be less than `-1`.
+ /// By default this value is 0 for contracts.
public var maxAutomaticTokenAssociations: Int32 {
get {return _storage._maxAutomaticTokenAssociations}
set {_uniqueStorage()._maxAutomaticTokenAssociations = newValue}
diff --git a/Sources/HederaProtobufs/Services/contract_update.pb.swift b/Sources/HederaProtobufs/Services/contract_update.pb.swift
index c38c34b2..18688d29 100644
--- a/Sources/HederaProtobufs/Services/contract_update.pb.swift
+++ b/Sources/HederaProtobufs/Services/contract_update.pb.swift
@@ -139,8 +139,12 @@ public struct Proto_ContractUpdateTransactionBody {
}
///*
- /// If set, the new maximum number of tokens that this contract can be
- /// automatically associated with (i.e., receive air-drops from).
+ /// If set, modify the maximum number of tokens that can be auto-associated with the
+ /// contract.
+ /// If this is set and less than or equal to `used_auto_associations`, or 0, then this contract
+ /// MUST manually associate with a token before transacting in that token.
+ /// This value MAY also be `-1` to indicate no limit.
+ /// This value MUST NOT be less than `-1`.
public var maxAutomaticTokenAssociations: SwiftProtobuf.Google_Protobuf_Int32Value {
get {return _storage._maxAutomaticTokenAssociations ?? SwiftProtobuf.Google_Protobuf_Int32Value()}
set {_uniqueStorage()._maxAutomaticTokenAssociations = newValue}
diff --git a/Sources/HederaProtobufs/Services/crypto_create.pb.swift b/Sources/HederaProtobufs/Services/crypto_create.pb.swift
index a4f00b8f..416fe152 100644
--- a/Sources/HederaProtobufs/Services/crypto_create.pb.swift
+++ b/Sources/HederaProtobufs/Services/crypto_create.pb.swift
@@ -168,8 +168,12 @@ public struct Proto_CryptoCreateTransactionBody {
}
///*
- /// The maximum number of tokens that an Account can be implicitly associated with. Defaults to 0
- /// and up to a maximum value of 1000.
+ /// The maximum number of tokens that can be auto-associated with the account.
+ /// If this is less than or equal to `used_auto_associations`, or 0, then this account
+ /// MUST manually associate with a token before transacting in that token.
+ /// This value MAY also be `-1` to indicate no limit.
+ /// This value MUST NOT be less than `-1`.
+ /// By default this value is 0 for accounts except for auto-created accounts which default -1.
public var maxAutomaticTokenAssociations: Int32 {
get {return _storage._maxAutomaticTokenAssociations}
set {_uniqueStorage()._maxAutomaticTokenAssociations = newValue}
diff --git a/Sources/HederaProtobufs/Services/crypto_update.pb.swift b/Sources/HederaProtobufs/Services/crypto_update.pb.swift
index 11f663ac..65db6742 100644
--- a/Sources/HederaProtobufs/Services/crypto_update.pb.swift
+++ b/Sources/HederaProtobufs/Services/crypto_update.pb.swift
@@ -196,8 +196,12 @@ public struct Proto_CryptoUpdateTransactionBody {
public mutating func clearMemo() {_uniqueStorage()._memo = nil}
///*
- /// The maximum number of tokens that an Account can be implicitly associated with. Up to a 1000
- /// including implicit and explicit associations.
+ /// If set, modify the maximum number of tokens that can be auto-associated with the
+ /// account.
+ /// If this is set and less than or equal to `used_auto_associations`, or 0, then this account
+ /// MUST manually associate with a token before transacting in that token.
+ /// This value MAY also be `-1` to indicate no limit.
+ /// This value MUST NOT be less than `-1`.
public var maxAutomaticTokenAssociations: SwiftProtobuf.Google_Protobuf_Int32Value {
get {return _storage._maxAutomaticTokenAssociations ?? SwiftProtobuf.Google_Protobuf_Int32Value()}
set {_uniqueStorage()._maxAutomaticTokenAssociations = newValue}
diff --git a/Sources/HederaProtobufs/Services/node_create.pb.swift b/Sources/HederaProtobufs/Services/node_create.pb.swift
index 3e764d1f..cd508df5 100644
--- a/Sources/HederaProtobufs/Services/node_create.pb.swift
+++ b/Sources/HederaProtobufs/Services/node_create.pb.swift
@@ -21,28 +21,42 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
}
///*
-/// A transaction body to add a new node to the network.
-/// After the node is created, the node_id for it is in the receipt.
+/// A transaction body to add a new consensus node to the network address book.
///
/// This transaction body SHALL be considered a "privileged transaction".
///
-/// This message supports a transaction to create a new node in the network.
-/// The transaction, once complete, enables a new consensus node
+/// This message supports a transaction to create a new node in the network
+/// address book. The transaction, once complete, enables a new consensus node
/// to join the network, and requires governing council authorization.
///
-/// A `NodeCreateTransactionBody` MUST be signed by the governing council.
-/// The newly created node information will be used to generate config.txt and
-/// a-pulbic-NodeAlias.pem file per each node during phase 2,
-/// not active until next freeze upgrade.
-public struct Proto_NodeCreateTransactionBody {
+/// - A `NodeCreateTransactionBody` MUST be signed by the governing council.
+/// - A `NodeCreateTransactionBody` MUST be signed by the `Key` assigned to the
+/// `admin_key` field.
+/// - The newly created node information SHALL be added to the network address
+/// book information in the network state.
+/// - The new entry SHALL be created in "state" but SHALL NOT participate in
+/// network consensus and SHALL NOT be present in network "configuration"
+/// until the next "upgrade" transaction (as noted below).
+/// - All new address book entries SHALL be added to the active network
+/// configuration during the next `freeze` transaction with the field
+/// `freeze_type` set to `PREPARE_UPGRADE`.
+///
+/// ### Record Stream Effects
+/// Upon completion the newly assigned `node_id` SHALL be in the transaction
+/// receipt.
+public struct Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
///*
- /// Node account id, mandatory field, ALIAS is not allowed, only ACCOUNT_NUM.
- /// If account_id does not exist, it will reject the transaction.
- /// Multiple nodes can have the same account_id.
+ /// A Node account identifier.
+ ///
+ /// This account identifier MUST be in the "account number" form.
+ /// This account identifier MUST NOT use the alias field.
+ /// If the identified account does not exist, this transaction SHALL fail.
+ /// Multiple nodes MAY share the same node account.
+ /// This field is REQUIRED.
public var accountID: Proto_AccountID {
get {return _accountID ?? Proto_AccountID()}
set {_accountID = newValue}
@@ -53,52 +67,100 @@ public struct Proto_NodeCreateTransactionBody {
public mutating func clearAccountID() {self._accountID = nil}
///*
- /// Description of the node with UTF-8 encoding up to 100 bytes, optional field.
+ /// A short description of the node.
+ ///
+ /// This value, if set, MUST NOT exceed 100 bytes when encoded as UTF-8.
+ /// This field is OPTIONAL.
public var description_p: String = String()
///*
- /// Ip address and port, mandatory field. Fully qualified domain name is
- /// not allowed here. Maximum number of these endpoints is 10.
- /// The first in the list is used as the Internal IP address in config.txt,
- /// the second in the list is used as the External IP address in config.txt,
- /// the rest of IP addresses are ignored for DAB phase 2.
+ /// A list of service endpoints for gossip.
+ ///
+ /// These endpoints SHALL represent the published endpoints to which other
+ /// consensus nodes may _gossip_ transactions.
+ /// These endpoints MUST specify a port.
+ /// This list MUST NOT be empty.
+ /// This list MUST NOT contain more than `10` entries.
+ /// The first two entries in this list SHALL be the endpoints published to
+ /// all consensus nodes.
+ /// All other entries SHALL be reserved for future use.
+ ///
+ /// Each network may have additional requirements for these endpoints.
+ /// A client MUST check network-specific documentation for those
+ /// details.
+ /// If the network configuration value `gossipFqdnRestricted` is set, then
+ /// all endpoints in this list MUST supply only IP address.
+ /// If the network configuration value `gossipFqdnRestricted` is _not_ set,
+ /// then endpoints in this list MAY supply either IP address or FQDN, but
+ /// MUST NOT supply both values for the same endpoint.
public var gossipEndpoint: [Proto_ServiceEndpoint] = []
///*
- /// A node's grpc service IP addresses and ports, IP:Port is mandatory,
- /// fully qualified domain name is optional. Maximum number of these endpoints is 8.
+ /// A list of service endpoints for gRPC calls.
+ ///
+ /// These endpoints SHALL represent the published gRPC endpoints to which
+ /// clients may submit transactions.
+ /// These endpoints MUST specify a port.
+ /// Endpoints in this list MAY supply either IP address or FQDN, but MUST
+ /// NOT supply both values for the same endpoint.
+ /// This list MUST NOT be empty.
+ /// This list MUST NOT contain more than `8` entries.
public var serviceEndpoint: [Proto_ServiceEndpoint] = []
///*
- /// The node's X509 certificate used to sign stream files (e.g., record stream
- /// files). Precisely, this field is the DER encoding of gossip X509 certificate.
- /// This is a mandatory field.
+ /// A certificate used to sign gossip events.
+ ///
+ /// This value MUST be a certificate of a type permitted for gossip
+ /// signatures.
+ /// This value MUST be the DER encoding of the certificate presented.
+ /// This field is REQUIRED and MUST NOT be empty.
public var gossipCaCertificate: Data = Data()
///*
- /// Hash of the node's TLS certificate. Precisely, this field is a string of
- /// hexadecimal characters which translated to binary, are the SHA-384 hash of
- /// the UTF-8 NFKD encoding of the node's TLS cert in PEM format.
- /// Its value can be used to verify the node's certificate it presents
- /// during TLS negotiations.node x509 certificate hash, optional field.
+ /// A hash of the node gRPC TLS certificate.
+ ///
+ /// This value MAY be used to verify the certificate presented by the node
+ /// during TLS negotiation for gRPC.
+ /// This value MUST be a SHA-384 hash.
+ /// The TLS certificate to be hashed MUST first be in PEM format and MUST be
+ /// encoded with UTF-8 NFKD encoding to a stream of bytes provided to
+ /// the hash algorithm.
+ /// This field is OPTIONAL.
public var grpcCertificateHash: Data = Data()
+ ///*
+ /// An administrative key controlled by the node operator.
+ ///
+ /// This key MUST sign this transaction.
+ /// The node identified MUST exist in the network address book.
+ /// The node identified MUST exist in the network address book.
+ /// If set, this SHALL replace the node account identifier.
+ /// This value, if set, MUST NOT exceed 100 bytes when encoded as UTF-8.
+ /// If set, this list MUST meet the following requirements.
+ ///
+ /// Each network may have additional requirements for these endpoints.
+ /// A client MUST check network-specific documentation for those
+ /// details.
+ /// If set, the new list SHALL replace the existing list.
public var gossipEndpoint: [Proto_ServiceEndpoint] = []
///*
- /// If set, replace the current list of service_endpoints.
+ /// A list of service endpoints for gRPC calls.
+ ///
+ /// If set, this list MUST meet the following requirements.
+ ///
+ /// Each network may have additional requirements for these endpoints.
+ /// A client MUST check network-specific documentation for those
+ /// details.
+ ///
+ /// If set, the new list SHALL replace the existing list.
public var serviceEndpoint: [Proto_ServiceEndpoint] = []
///*
- /// If set, the new X509 certificate of the gossip node.
+ /// A certificate used to sign gossip events.
+ ///
+ /// This value MUST be a certificate of a type permitted for gossip
+ /// signatures.
+ /// If set, the new value SHALL replace the existing bytes value.
public var gossipCaCertificate: SwiftProtobuf.Google_Protobuf_BytesValue {
get {return _gossipCaCertificate ?? SwiftProtobuf.Google_Protobuf_BytesValue()}
set {_gossipCaCertificate = newValue}
@@ -78,7 +150,16 @@ public struct Proto_NodeUpdateTransactionBody {
public mutating func clearGossipCaCertificate() {self._gossipCaCertificate = nil}
///*
- /// If set, the new grpc x509 certificate hash.
+ /// A hash of the node gRPC TLS certificate.
+ ///
+ /// This value MAY be used to verify the certificate presented by the node
+ /// during TLS negotiation for gRPC.
+ /// If set, the new value SHALL replace the existing hash value.
public var grpcCertificateHash: SwiftProtobuf.Google_Protobuf_BytesValue {
get {return _grpcCertificateHash ?? SwiftProtobuf.Google_Protobuf_BytesValue()}
set {_grpcCertificateHash = newValue}
@@ -88,6 +169,24 @@ public struct Proto_NodeUpdateTransactionBody {
/// Clears the value of `grpcCertificateHash`. Subsequent reads from it will return its default value.
public mutating func clearGrpcCertificateHash() {self._grpcCertificateHash = nil}
+ ///*
+ /// An administrative key controlled by the node operator.
+ ///
+ /// This field is OPTIONAL.
+ /// Each transfer MUST be one of the following:
+ ///
+ /// Each transfer MUST be one of the following:
+ ///
+ /// Node identifiers SHALL be unique _within_ a shard and realm,
+ /// but a node SHALL NOT, ever, serve multiple shards or realms,
+ /// therefore the node identifier MAY be repeated _between_ shards and realms.
public var nodeID: UInt64 = 0
///*
- /// The account is charged for transactions submitted by the node that fail due diligence
+ /// An account identifier.
+ ///
+ /// This account SHALL be owned by the entity responsible for the node.
+ /// This value, if set, SHALL NOT exceed 100 bytes when encoded as UTF-8.
public var description_p: String = String()
///*
- /// Node Gossip Endpoints, ip address or FQDN and port
+ /// A list of service endpoints for gossip.
+ ///
+ /// These endpoints SHALL represent the published endpoints to which other
+ /// consensus nodes may _gossip_ transactions.
+ /// These endpoints SHALL represent the published endpoints to which clients
+ /// may submit transactions.
+ /// This value SHALL be a certificate of a type permitted for gossip
+ /// signatures.
+ /// This value MAY be used to verify the certificate presented by the node
+ /// during TLS negotiation for gRPC.
+ /// Each node SHALL have a weight in consensus calculations.
+ /// If this field is set, then this node SHALL NOT be included in the next
+ /// update of the network address book.
+ /// This key MUST sign each transaction to update this node.
+ /// This transaction SHALL create a new consensus node record and add
+ /// that record to the network address book.
+ public var nodeCreate: Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody {
get {
if case .nodeCreate(let v)? = _storage._data {return v}
- return Proto_NodeCreateTransactionBody()
+ return Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody()
}
set {_uniqueStorage()._data = .nodeCreate(newValue)}
}
///*
/// A transaction body for an `updateNode` request.
- public var nodeUpdate: Proto_NodeUpdateTransactionBody {
+ ///
+ /// This transaction SHALL update an existing consensus node record in
+ /// the network address book.
+ public var nodeUpdate: Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody {
get {
if case .nodeUpdate(let v)? = _storage._data {return v}
- return Proto_NodeUpdateTransactionBody()
+ return Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody()
}
set {_uniqueStorage()._data = .nodeUpdate(newValue)}
}
///*
/// A transaction body for a `deleteNode` request.
- public var nodeDelete: Proto_NodeDeleteTransactionBody {
+ ///
+ /// This transaction SHALL remove an existing consensus node record from
+ /// the network address book.
+ public var nodeDelete: Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody {
get {
if case .nodeDelete(let v)? = _storage._data {return v}
- return Proto_NodeDeleteTransactionBody()
+ return Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody()
}
set {_uniqueStorage()._data = .nodeDelete(newValue)}
}
+ ///*
+ /// A transaction body to "reject" undesired tokens.
+ /// Each transfer MUST be one of the following:
+ ///
+ /// This transaction SHALL create a new consensus node record and add
+ /// that record to the network address book.
+ case nodeCreate(Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody)
///*
/// A transaction body for an `updateNode` request.
- case nodeUpdate(Proto_NodeUpdateTransactionBody)
+ ///
+ /// This transaction SHALL update an existing consensus node record in
+ /// the network address book.
+ case nodeUpdate(Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody)
///*
/// A transaction body for a `deleteNode` request.
- case nodeDelete(Proto_NodeDeleteTransactionBody)
+ ///
+ /// This transaction SHALL remove an existing consensus node record from
+ /// the network address book.
+ case nodeDelete(Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody)
+ ///*
+ /// A transaction body to "reject" undesired tokens.
+ /// Each transfer MUST be one of the following:
+ ///
+ ///
+ /// This key MUST sign each transaction to update this node.
+ /// This field MUST contain a valid `Key` value.
+ /// This field is REQUIRED and MUST NOT be set to an empty `KeyList`.
+ public var adminKey: Proto_Key {
+ get {return _adminKey ?? Proto_Key()}
+ set {_adminKey = newValue}
+ }
+ /// Returns true if `adminKey` has been explicitly set.
+ public var hasAdminKey: Bool {return self._adminKey != nil}
+ /// Clears the value of `adminKey`. Subsequent reads from it will return its default value.
+ public mutating func clearAdminKey() {self._adminKey = nil}
+
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _accountID: Proto_AccountID? = nil
+ fileprivate var _adminKey: Proto_Key? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
-extension Proto_NodeCreateTransactionBody: @unchecked Sendable {}
+extension Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
-fileprivate let _protobuf_package = "proto"
+fileprivate let _protobuf_package = "com.hedera.hapi.node.addressbook"
-extension Proto_NodeCreateTransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
+extension Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".NodeCreateTransactionBody"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "account_id"),
@@ -107,6 +169,7 @@ extension Proto_NodeCreateTransactionBody: SwiftProtobuf.Message, SwiftProtobuf.
4: .standard(proto: "service_endpoint"),
5: .standard(proto: "gossip_ca_certificate"),
6: .standard(proto: "grpc_certificate_hash"),
+ 7: .standard(proto: "admin_key"),
]
public mutating func decodeMessage
+/// - A deleted address book node SHALL be removed entirely from network state.
+/// - A deleted address book node identifier SHALL NOT be reused.
+///
+/// ### Record Stream Effects
+/// Upon completion the "deleted" `node_id` SHALL be in the transaction
+/// receipt.
+public struct Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
///*
- /// The unique id of the node to be deleted. If invalid node is specified, transaction will
- /// result in INVALID_NODE_ID.
+ /// A consensus node identifier in the network state.
+ ///
+ /// The node identified MUST NOT be deleted.
+ /// This value is REQUIRED.
public var nodeID: UInt64 = 0
public var unknownFields = SwiftProtobuf.UnknownStorage()
@@ -44,14 +56,14 @@ public struct Proto_NodeDeleteTransactionBody {
}
#if swift(>=5.5) && canImport(_Concurrency)
-extension Proto_NodeDeleteTransactionBody: @unchecked Sendable {}
+extension Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
-fileprivate let _protobuf_package = "proto"
+fileprivate let _protobuf_package = "com.hedera.hapi.node.addressbook"
-extension Proto_NodeDeleteTransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
+extension Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".NodeDeleteTransactionBody"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "node_id"),
@@ -76,7 +88,7 @@ extension Proto_NodeDeleteTransactionBody: SwiftProtobuf.Message, SwiftProtobuf.
try unknownFields.traverse(visitor: &visitor)
}
- public static func ==(lhs: Proto_NodeDeleteTransactionBody, rhs: Proto_NodeDeleteTransactionBody) -> Bool {
+ public static func ==(lhs: Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody, rhs: Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody) -> Bool {
if lhs.nodeID != rhs.nodeID {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
diff --git a/Sources/HederaProtobufs/Services/node_update.pb.swift b/Sources/HederaProtobufs/Services/node_update.pb.swift
index 93c6af04..6924cbfb 100644
--- a/Sources/HederaProtobufs/Services/node_update.pb.swift
+++ b/Sources/HederaProtobufs/Services/node_update.pb.swift
@@ -21,23 +21,43 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
}
///*
-/// Modify the attribute of a node. If a field is not set in the transaction body, the
-/// corresponding node attribute will be unchanged.
-/// For phase 2, this marks node to be updated in the merkle tree and will be used to write config.txt and
-/// a-pulbic-NodeAlias.pem file per each node during prepare freeze.
-/// The node will not be updated until the network is upgraded.
-/// Original node account ID has to sign the transaction.
-public struct Proto_NodeUpdateTransactionBody {
+/// Transaction body to modify address book node attributes.
+///
+/// - This transaction SHALL enable the node operator, as identified by the
+/// `admin_key`, to modify operational attributes of the node.
+/// - This transaction MUST be signed by the active `admin_key` for the node.
+/// - If this transaction sets a new value for the `admin_key`, then both the
+/// current `admin_key`, and the new `admin_key` MUST sign this transaction.
+/// - This transaction SHALL NOT change any field that is not set (is null) in
+/// this transaction body.
+/// - This SHALL create a pending update to the node, but the change SHALL NOT
+/// be immediately applied to the active configuration.
+/// - All pending node updates SHALL be applied to the active network
+/// configuration during the next `freeze` transaction with the field
+/// `freeze_type` set to `PREPARE_UPGRADE`.
+///
+/// ### Record Stream Effects
+/// Upon completion the `node_id` for the updated entry SHALL be in the
+/// transaction receipt.
+public struct Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
///*
- /// The unique id of the Node to be updated. This must refer to an existing, non-deleted node.
+ /// A consensus node identifier in the network state.
+ ///
+ /// The node identified MUST NOT be deleted.
+ /// This value is REQUIRED.
public var nodeID: UInt64 = 0
///*
- /// If set, the new node account_id.
+ /// An account identifier.
+ ///
+ /// If set, this transaction MUST be signed by the active `key` for _both_
+ /// the current node account _and_ the identified new node account.
public var accountID: Proto_AccountID {
get {return _accountID ?? Proto_AccountID()}
set {_accountID = newValue}
@@ -48,7 +68,10 @@ public struct Proto_NodeUpdateTransactionBody {
public mutating func clearAccountID() {self._accountID = nil}
///*
- /// If set, the new description to be associated with the node.
+ /// A short description of the node.
+ ///
+ /// If set, this value SHALL replace the previous value.
public var description_p: SwiftProtobuf.Google_Protobuf_StringValue {
get {return _description_p ?? SwiftProtobuf.Google_Protobuf_StringValue()}
set {_description_p = newValue}
@@ -59,15 +82,64 @@ public struct Proto_NodeUpdateTransactionBody {
public mutating func clearDescription_p() {self._description_p = nil}
///*
- /// If set, the new ip address and port.
+ /// A list of service endpoints for gossip.
+ ///
+ /// These endpoints SHALL represent the published endpoints to which other
+ /// consensus nodes may _gossip_ transactions.
+ /// These endpoints SHOULD NOT specify both address and DNS name.
+ /// This list MUST NOT be empty.
+ /// This list MUST NOT contain more than `10` entries.
+ /// The first two entries in this list SHALL be the endpoints published to
+ /// all consensus nodes.
+ /// All other entries SHALL be reserved for future use.
+ ///
+ /// Example
+ ///
+ /// Hedera Mainnet _requires_ that address be specified, and does not
+ /// permit DNS name (FQDN) to be specified.
+ ///
+ /// Mainnet also requires that the first entry be an "internal" IP
+ /// address and the second entry be an "external" IP address.
+ ///
+ /// Solo, however, _requires_ DNS name (FQDN) but also permits
+ /// address.
+ ///
+ /// These endpoints SHALL represent the published endpoints to which clients
+ /// may submit transactions.
+ /// These endpoints SHOULD specify address and port.
+ /// These endpoints MAY specify a DNS name.
+ /// These endpoints SHOULD NOT specify both address and DNS name.
+ /// This list MUST NOT be empty.
+ /// This list MUST NOT contain more than `8` entries.
+ ///
+ /// This value MUST be the DER encoding of the certificate presented.
+ ///
+ /// This value MUST be a SHA-384 hash.
+ /// The TLS certificate to be hashed MUST first be in PEM format and MUST be
+ /// encoded with UTF-8 NFKD encoding to a stream of bytes provided to
+ /// the hash algorithm.
+ ///
+ /// If set, this key MUST sign this transaction.
+ /// If set, this key MUST sign each subsequent transaction to
+ /// update this node.
+ /// If set, this field MUST contain a valid `Key` value.
+ /// If set, this field MUST NOT be set to an empty `KeyList`.
+ public var adminKey: Proto_Key {
+ get {return _adminKey ?? Proto_Key()}
+ set {_adminKey = newValue}
+ }
+ /// Returns true if `adminKey` has been explicitly set.
+ public var hasAdminKey: Bool {return self._adminKey != nil}
+ /// Clears the value of `adminKey`. Subsequent reads from it will return its default value.
+ public mutating func clearAdminKey() {self._adminKey = nil}
+
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
@@ -96,17 +195,18 @@ public struct Proto_NodeUpdateTransactionBody {
fileprivate var _description_p: SwiftProtobuf.Google_Protobuf_StringValue? = nil
fileprivate var _gossipCaCertificate: SwiftProtobuf.Google_Protobuf_BytesValue? = nil
fileprivate var _grpcCertificateHash: SwiftProtobuf.Google_Protobuf_BytesValue? = nil
+ fileprivate var _adminKey: Proto_Key? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
-extension Proto_NodeUpdateTransactionBody: @unchecked Sendable {}
+extension Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
-fileprivate let _protobuf_package = "proto"
+fileprivate let _protobuf_package = "com.hedera.hapi.node.addressbook"
-extension Proto_NodeUpdateTransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
+extension Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".NodeUpdateTransactionBody"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "node_id"),
@@ -116,6 +216,7 @@ extension Proto_NodeUpdateTransactionBody: SwiftProtobuf.Message, SwiftProtobuf.
5: .standard(proto: "service_endpoint"),
6: .standard(proto: "gossip_ca_certificate"),
7: .standard(proto: "grpc_certificate_hash"),
+ 8: .standard(proto: "admin_key"),
]
public mutating func decodeMessage
+ /// The most common cause for this response is a service endpoint that has
+ /// the domain name (DNS) set rather than address and port.
case invalidGossipEndpoint // = 340
///*
- /// The node account_id is invalid
+ /// A transaction failed because the node account identifier provided
+ /// does not exist or is not valid.
+ /// One common source of this error is providing a node account identifier
+ /// using the "alias" form rather than "numeric" form.
case invalidNodeAccountID // = 341
///*
- /// The node description is invalid
+ /// A transaction failed because the description field cannot be encoded
+ /// as UTF-8 or is more than 100 bytes when encoded.
case invalidNodeDescription // = 342
///*
- /// service_endpoint is invalid
+ /// A transaction failed because one or more entries in the list of
+ /// service endpoints for the `service_endpoint` field is invalid.
+ /// The most common cause for this response is a service endpoint that has
+ /// the domain name (DNS) set rather than address and port.
case invalidServiceEndpoint // = 343
///*
- /// gossip_ca_certificate is invalid
- case invalidGossipCaeCertificate // = 344
+ /// A transaction failed because the TLS certificate provided for the
+ /// node is missing or invalid.
+ /// The certificate MUST be a TLS certificate of a type permitted for gossip
+ /// signatures.
+ /// The value presented MUST be a UTF-8 NFKD encoding of the TLS
+ /// certificate.
+ /// The certificate encoded MUST be in PEM format.
+ /// The `gossip_ca_certificate` field is REQUIRED and MUST NOT be empty.
+ case invalidGossipCaCertificate // = 344
///*
- /// grpc_certificate_hash is invalid
+ /// A transaction failed because the hash provided for the gRPC certificate
+ /// is present but invalid.
+ /// The `grpc_certificate_hash` MUST be a SHA-384 hash.
+ /// The input hashed MUST be a UTF-8 NFKD encoding of the actual TLS
+ /// certificate.
+ /// The certificate to be encoded MUST be in PEM format.
case invalidGrpcCertificate // = 345
+
+ ///*
+ /// The maximum automatic associations value is not valid.
+ /// The most common cause for this error is a value less than `-1`.
+ case invalidMaxAutoAssociations // = 346
+
+ ///*
+ /// The maximum number of nodes allowed in the address book have been created.
+ case maxNodesCreated // = 347
+
+ ///*
+ /// In ServiceEndpoint, domain_name and ipAddressV4 are mutually exclusive
+ case ipFqdnCannotBeSetForSameEndpoint // = 348
+
+ ///*
+ /// Fully qualified domain name is not allowed in gossip_endpoint
+ case gossipEndpointCannotHaveFqdn // = 349
+
+ ///*
+ /// In ServiceEndpoint, domain_name size too large
+ case fqdnSizeTooLarge // = 350
+
+ ///*
+ /// ServiceEndpoint is invalid
+ case invalidEndpoint // = 351
+
+ ///*
+ /// The number of gossip endpoints exceeds the limit
+ case gossipEndpointsExceededLimit // = 352
+
+ ///*
+ /// The transaction attempted to use duplicate `TokenReference`.
+ /// This affects `TokenReject` attempting to reject same token reference more than once.
+ case tokenReferenceRepeated // = 353
+
+ ///*
+ /// The account id specified as the owner in `TokenReject` is invalid or does not exist.
+ case invalidOwnerID // = 354
+
+ ///*
+ /// The transaction attempted to use more than the allowed number of `TokenReference`.
+ case tokenReferenceListSizeLimitExceeded // = 355
+
+ ///*
+ /// The number of service endpoints exceeds the limit
+ case serviceEndpointsExceededLimit // = 356
+
+ ///
+ /// The IPv4 address is invalid
+ case invalidIpv4Address // = 357
+
+ ///*
+ /// The transaction attempted to use empty `TokenReference` list.
+ case emptyTokenReferenceList // = 358
+
+ ///
+ /// The node account is not allowed to be updated
+ case updateNodeAccountNotAllowed // = 359
case UNRECOGNIZED(Int)
public init() {
@@ -1552,8 +1634,22 @@ public enum Proto_ResponseCodeEnum: SwiftProtobuf.Enum {
case 341: self = .invalidNodeAccountID
case 342: self = .invalidNodeDescription
case 343: self = .invalidServiceEndpoint
- case 344: self = .invalidGossipCaeCertificate
+ case 344: self = .invalidGossipCaCertificate
case 345: self = .invalidGrpcCertificate
+ case 346: self = .invalidMaxAutoAssociations
+ case 347: self = .maxNodesCreated
+ case 348: self = .ipFqdnCannotBeSetForSameEndpoint
+ case 349: self = .gossipEndpointCannotHaveFqdn
+ case 350: self = .fqdnSizeTooLarge
+ case 351: self = .invalidEndpoint
+ case 352: self = .gossipEndpointsExceededLimit
+ case 353: self = .tokenReferenceRepeated
+ case 354: self = .invalidOwnerID
+ case 355: self = .tokenReferenceListSizeLimitExceeded
+ case 356: self = .serviceEndpointsExceededLimit
+ case 357: self = .invalidIpv4Address
+ case 358: self = .emptyTokenReferenceList
+ case 359: self = .updateNodeAccountNotAllowed
default: self = .UNRECOGNIZED(rawValue)
}
}
@@ -1862,8 +1958,22 @@ public enum Proto_ResponseCodeEnum: SwiftProtobuf.Enum {
case .invalidNodeAccountID: return 341
case .invalidNodeDescription: return 342
case .invalidServiceEndpoint: return 343
- case .invalidGossipCaeCertificate: return 344
+ case .invalidGossipCaCertificate: return 344
case .invalidGrpcCertificate: return 345
+ case .invalidMaxAutoAssociations: return 346
+ case .maxNodesCreated: return 347
+ case .ipFqdnCannotBeSetForSameEndpoint: return 348
+ case .gossipEndpointCannotHaveFqdn: return 349
+ case .fqdnSizeTooLarge: return 350
+ case .invalidEndpoint: return 351
+ case .gossipEndpointsExceededLimit: return 352
+ case .tokenReferenceRepeated: return 353
+ case .invalidOwnerID: return 354
+ case .tokenReferenceListSizeLimitExceeded: return 355
+ case .serviceEndpointsExceededLimit: return 356
+ case .invalidIpv4Address: return 357
+ case .emptyTokenReferenceList: return 358
+ case .updateNodeAccountNotAllowed: return 359
case .UNRECOGNIZED(let i): return i
}
}
@@ -2177,8 +2287,22 @@ extension Proto_ResponseCodeEnum: CaseIterable {
.invalidNodeAccountID,
.invalidNodeDescription,
.invalidServiceEndpoint,
- .invalidGossipCaeCertificate,
+ .invalidGossipCaCertificate,
.invalidGrpcCertificate,
+ .invalidMaxAutoAssociations,
+ .maxNodesCreated,
+ .ipFqdnCannotBeSetForSameEndpoint,
+ .gossipEndpointCannotHaveFqdn,
+ .fqdnSizeTooLarge,
+ .invalidEndpoint,
+ .gossipEndpointsExceededLimit,
+ .tokenReferenceRepeated,
+ .invalidOwnerID,
+ .tokenReferenceListSizeLimitExceeded,
+ .serviceEndpointsExceededLimit,
+ .invalidIpv4Address,
+ .emptyTokenReferenceList,
+ .updateNodeAccountNotAllowed,
]
}
@@ -2494,7 +2618,21 @@ extension Proto_ResponseCodeEnum: SwiftProtobuf._ProtoNameProviding {
341: .same(proto: "INVALID_NODE_ACCOUNT_ID"),
342: .same(proto: "INVALID_NODE_DESCRIPTION"),
343: .same(proto: "INVALID_SERVICE_ENDPOINT"),
- 344: .same(proto: "INVALID_GOSSIP_CAE_CERTIFICATE"),
+ 344: .same(proto: "INVALID_GOSSIP_CA_CERTIFICATE"),
345: .same(proto: "INVALID_GRPC_CERTIFICATE"),
+ 346: .same(proto: "INVALID_MAX_AUTO_ASSOCIATIONS"),
+ 347: .same(proto: "MAX_NODES_CREATED"),
+ 348: .same(proto: "IP_FQDN_CANNOT_BE_SET_FOR_SAME_ENDPOINT"),
+ 349: .same(proto: "GOSSIP_ENDPOINT_CANNOT_HAVE_FQDN"),
+ 350: .same(proto: "FQDN_SIZE_TOO_LARGE"),
+ 351: .same(proto: "INVALID_ENDPOINT"),
+ 352: .same(proto: "GOSSIP_ENDPOINTS_EXCEEDED_LIMIT"),
+ 353: .same(proto: "TOKEN_REFERENCE_REPEATED"),
+ 354: .same(proto: "INVALID_OWNER_ID"),
+ 355: .same(proto: "TOKEN_REFERENCE_LIST_SIZE_LIMIT_EXCEEDED"),
+ 356: .same(proto: "SERVICE_ENDPOINTS_EXCEEDED_LIMIT"),
+ 357: .same(proto: "INVALID_IPV4_ADDRESS"),
+ 358: .same(proto: "EMPTY_TOKEN_REFERENCE_LIST"),
+ 359: .same(proto: "UPDATE_NODE_ACCOUNT_NOT_ALLOWED"),
]
}
diff --git a/Sources/HederaProtobufs/Services/schedulable_transaction_body.pb.swift b/Sources/HederaProtobufs/Services/schedulable_transaction_body.pb.swift
index abff0feb..6c153361 100644
--- a/Sources/HederaProtobufs/Services/schedulable_transaction_body.pb.swift
+++ b/Sources/HederaProtobufs/Services/schedulable_transaction_body.pb.swift
@@ -444,34 +444,58 @@ public struct Proto_SchedulableTransactionBody {
///*
/// Transaction body for a scheduled transaction to create a new node.
- public var nodeCreate: Proto_NodeCreateTransactionBody {
+ public var nodeCreate: Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody {
get {
if case .nodeCreate(let v)? = _storage._data {return v}
- return Proto_NodeCreateTransactionBody()
+ return Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody()
}
set {_uniqueStorage()._data = .nodeCreate(newValue)}
}
///*
/// Transaction body for a scheduled transaction to modify an existing node.
- public var nodeUpdate: Proto_NodeUpdateTransactionBody {
+ public var nodeUpdate: Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody {
get {
if case .nodeUpdate(let v)? = _storage._data {return v}
- return Proto_NodeUpdateTransactionBody()
+ return Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody()
}
set {_uniqueStorage()._data = .nodeUpdate(newValue)}
}
///*
/// Transaction body for a scheduled transaction to remove a node.
- public var nodeDelete: Proto_NodeDeleteTransactionBody {
+ public var nodeDelete: Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody {
get {
if case .nodeDelete(let v)? = _storage._data {return v}
- return Proto_NodeDeleteTransactionBody()
+ return Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody()
}
set {_uniqueStorage()._data = .nodeDelete(newValue)}
}
+ ///*
+ /// A transaction body to "reject" undesired tokens.
+ /// This transaction will transfer one or more tokens or token
+ /// balances held by the requesting account to the treasury
+ /// for each token type.
+ ///
+ ///
+ /// When complete, the requesting account SHALL NOT hold the
+ /// rejected tokens.
+ /// Custom fees and royalties defined for the tokens rejected
+ /// SHALL NOT be charged for this transaction.
+ public var tokenReject: Proto_TokenRejectTransactionBody {
+ get {
+ if case .tokenReject(let v)? = _storage._data {return v}
+ return Proto_TokenRejectTransactionBody()
+ }
+ set {_uniqueStorage()._data = .tokenReject(newValue)}
+ }
+
public var unknownFields = SwiftProtobuf.UnknownStorage()
///*
@@ -596,13 +620,30 @@ public struct Proto_SchedulableTransactionBody {
case tokenUpdateNfts(Proto_TokenUpdateNftsTransactionBody)
///*
/// Transaction body for a scheduled transaction to create a new node.
- case nodeCreate(Proto_NodeCreateTransactionBody)
+ case nodeCreate(Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody)
///*
/// Transaction body for a scheduled transaction to modify an existing node.
- case nodeUpdate(Proto_NodeUpdateTransactionBody)
+ case nodeUpdate(Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody)
///*
/// Transaction body for a scheduled transaction to remove a node.
- case nodeDelete(Proto_NodeDeleteTransactionBody)
+ case nodeDelete(Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody)
+ ///*
+ /// A transaction body to "reject" undesired tokens.
+ /// This transaction will transfer one or more tokens or token
+ /// balances held by the requesting account to the treasury
+ /// for each token type.
+ ///
+ ///
+ /// When complete, the requesting account SHALL NOT hold the
+ /// rejected tokens.
+ /// Custom fees and royalties defined for the tokens rejected
+ /// SHALL NOT be charged for this transaction.
+ case tokenReject(Proto_TokenRejectTransactionBody)
#if !swift(>=4.1)
public static func ==(lhs: Proto_SchedulableTransactionBody.OneOf_Data, rhs: Proto_SchedulableTransactionBody.OneOf_Data) -> Bool {
@@ -778,6 +819,10 @@ public struct Proto_SchedulableTransactionBody {
guard case .nodeDelete(let l) = lhs, case .nodeDelete(let r) = rhs else { preconditionFailure() }
return l == r
}()
+ case (.tokenReject, .tokenReject): return {
+ guard case .tokenReject(let l) = lhs, case .tokenReject(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
default: return false
}
}
@@ -845,6 +890,7 @@ extension Proto_SchedulableTransactionBody: SwiftProtobuf.Message, SwiftProtobuf
42: .same(proto: "nodeCreate"),
43: .same(proto: "nodeUpdate"),
44: .same(proto: "nodeDelete"),
+ 45: .same(proto: "tokenReject"),
]
fileprivate class _StorageClass {
@@ -1396,7 +1442,7 @@ extension Proto_SchedulableTransactionBody: SwiftProtobuf.Message, SwiftProtobuf
}
}()
case 42: try {
- var v: Proto_NodeCreateTransactionBody?
+ var v: Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody?
var hadOneofValue = false
if let current = _storage._data {
hadOneofValue = true
@@ -1409,7 +1455,7 @@ extension Proto_SchedulableTransactionBody: SwiftProtobuf.Message, SwiftProtobuf
}
}()
case 43: try {
- var v: Proto_NodeUpdateTransactionBody?
+ var v: Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody?
var hadOneofValue = false
if let current = _storage._data {
hadOneofValue = true
@@ -1422,7 +1468,7 @@ extension Proto_SchedulableTransactionBody: SwiftProtobuf.Message, SwiftProtobuf
}
}()
case 44: try {
- var v: Proto_NodeDeleteTransactionBody?
+ var v: Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody?
var hadOneofValue = false
if let current = _storage._data {
hadOneofValue = true
@@ -1434,6 +1480,19 @@ extension Proto_SchedulableTransactionBody: SwiftProtobuf.Message, SwiftProtobuf
_storage._data = .nodeDelete(v)
}
}()
+ case 45: try {
+ var v: Proto_TokenRejectTransactionBody?
+ var hadOneofValue = false
+ if let current = _storage._data {
+ hadOneofValue = true
+ if case .tokenReject(let m) = current {v = m}
+ }
+ try decoder.decodeSingularMessageField(value: &v)
+ if let v = v {
+ if hadOneofValue {try decoder.handleConflictingOneOf()}
+ _storage._data = .tokenReject(v)
+ }
+ }()
default: break
}
}
@@ -1621,6 +1680,10 @@ extension Proto_SchedulableTransactionBody: SwiftProtobuf.Message, SwiftProtobuf
guard case .nodeDelete(let v)? = _storage._data else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 44)
}()
+ case .tokenReject?: try {
+ guard case .tokenReject(let v)? = _storage._data else { preconditionFailure() }
+ try visitor.visitSingularMessageField(value: v, fieldNumber: 45)
+ }()
case nil: break
}
}
diff --git a/Sources/HederaProtobufs/Services/state_addressbook_node.pb.swift b/Sources/HederaProtobufs/Services/state_addressbook_node.pb.swift
index 6b6242c9..c49e519e 100644
--- a/Sources/HederaProtobufs/Services/state_addressbook_node.pb.swift
+++ b/Sources/HederaProtobufs/Services/state_addressbook_node.pb.swift
@@ -20,82 +20,35 @@ fileprivate struct _GeneratedWithProtocGenSwiftVersion: SwiftProtobuf.ProtobufAP
typealias Version = _2
}
-public enum Proto_NodeStatus: SwiftProtobuf.Enum {
- public typealias RawValue = Int
-
- ///*
- /// node in this state is deleted
- case deleted // = 0
-
- ///*
- /// node in this state is waiting to be added by consensus roster
- case pendingAddition // = 1
-
- ///*
- /// node in this state is waiting to be deleted by consensus roster
- case pendingDeletion // = 2
-
- ///*
- /// node in this state is active on the network and participating
- /// in network consensus.
- case inConsensus // = 3
- case UNRECOGNIZED(Int)
-
- public init() {
- self = .deleted
- }
-
- public init?(rawValue: Int) {
- switch rawValue {
- case 0: self = .deleted
- case 1: self = .pendingAddition
- case 2: self = .pendingDeletion
- case 3: self = .inConsensus
- default: self = .UNRECOGNIZED(rawValue)
- }
- }
-
- public var rawValue: Int {
- switch self {
- case .deleted: return 0
- case .pendingAddition: return 1
- case .pendingDeletion: return 2
- case .inConsensus: return 3
- case .UNRECOGNIZED(let i): return i
- }
- }
-
-}
-
-#if swift(>=4.2)
-
-extension Proto_NodeStatus: CaseIterable {
- // The compiler won't synthesize support with the UNRECOGNIZED case.
- public static let allCases: [Proto_NodeStatus] = [
- .deleted,
- .pendingAddition,
- .pendingDeletion,
- .inConsensus,
- ]
-}
-
-#endif // swift(>=4.2)
-
///*
-/// Representation of a Node in the network Merkle tree
+/// A single address book node in the network state.
+///
+/// Each node in the network address book SHALL represent a single actual
+/// consensus node that is eligible to participate in network consensus.
///
-/// A Node is identified by a single uint64 number, which is unique among all nodes.
-public struct Proto_Node {
+/// Address book nodes SHALL NOT be _globally_ uniquely identified. A given node
+/// is only valid within a single realm and shard combination, so the identifier
+/// for a network node SHALL only be unique within a single realm and shard
+/// combination.
+public struct Com_Hedera_Hapi_Node_State_Addressbook_Node {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
// methods supported on all messages.
///*
- /// The unique id of the Node.
+ /// A consensus node identifier.
+ ///
+ /// This account SHALL be charged transaction fees for any transactions that
+ /// are submitted to the network by this node and fail due diligence checks.
public var accountID: Proto_AccountID {
get {return _accountID ?? Proto_AccountID()}
set {_accountID = newValue}
@@ -106,59 +59,114 @@ public struct Proto_Node {
public mutating func clearAccountID() {self._accountID = nil}
///*
- /// A description of the node, with UTF-8 encoding up to 100 bytes
+ /// A short description of the node.
+ ///
+ /// If the network configuration value `gossipFqdnRestricted` is set, then
+ /// all endpoints in this list SHALL supply only IP address.
+ /// If the network configuration value `gossipFqdnRestricted` is _not_ set,
+ /// then endpoints in this list MAY supply either IP address or FQDN, but
+ /// SHALL NOT supply both values for the same endpoint.
+ /// This list SHALL NOT be empty.
+ /// This list SHALL NOT contain more than `10` entries.
+ /// The first two entries in this list SHALL be the endpoints published to
+ /// all consensus nodes.
+ /// All other entries SHALL be reserved for future use.
public var gossipEndpoint: [Proto_ServiceEndpoint] = []
///*
- /// A node's service Endpoints, ip address or FQDN and port
+ /// A list of service endpoints for gRPC calls.
+ ///
+ /// These endpoints SHALL specify a port.
+ /// Endpoints in this list MAY supply either IP address or FQDN, but SHALL
+ /// NOT supply both values for the same endpoint.
+ /// This list SHALL NOT be empty.
+ /// This list SHALL NOT contain more than `8` entries.
public var serviceEndpoint: [Proto_ServiceEndpoint] = []
///*
- /// The node's X509 certificate used to sign stream files (e.g., record stream
- /// files). Precisely, this field is the DER encoding of gossip X509 certificate.
+ /// A certificate used to sign gossip events.
+ ///
+ /// This value SHALL be the DER encoding of the certificate presented.
+ /// This field is REQUIRED and MUST NOT be empty.
public var gossipCaCertificate: Data = Data()
///*
- /// node x509 certificate hash. Hash of the node's TLS certificate. Precisely, this field is a string of
- /// hexadecimal characters which, translated to binary, are the SHA-384 hash of
- /// the UTF-8 NFKD encoding of the node's TLS cert in PEM format. Its value can be
- /// used to verify the node's certificate it presents during TLS negotiations.
+ /// A hash of the node gRPC certificate.
+ ///
+ /// This value SHALL be a SHA-384 hash.
+ /// The TLS certificate to be hashed SHALL first be in PEM format and SHALL
+ /// be encoded with UTF-8 NFKD encoding to a stream of bytes provided to
+ /// the hash algorithm.
+ /// This field is OPTIONAL.
public var grpcCertificateHash: Data = Data()
///*
- /// The consensus weight of this node in the network.
+ /// A consensus weight.
+ ///
+ /// The consensus weight of a node SHALL be calculated based on the amount
+ /// of HBAR staked to that node.
+ /// Consensus SHALL be calculated based on agreement of greater than `2/3`
+ /// of the total `weight` value of all nodes on the network.
public var weight: UInt64 = 0
+ ///*
+ /// A flag indicating this node is deleted.
+ ///
+ /// If this field is set, then this node SHALL be immutable and SHALL NOT
+ /// be modified.
+ /// If this field is set, then any `nodeUpdate` transaction to modify this
+ /// node SHALL fail.
+ public var deleted: Bool = false
+
+ ///*
+ /// An administrative key controlled by the node operator.
+ ///
+ /// This field MUST contain a valid `Key` value.
+ /// This field is REQUIRED and MUST NOT be set to an empty `KeyList`.
+ public var adminKey: Proto_Key {
+ get {return _adminKey ?? Proto_Key()}
+ set {_adminKey = newValue}
+ }
+ /// Returns true if `adminKey` has been explicitly set.
+ public var hasAdminKey: Bool {return self._adminKey != nil}
+ /// Clears the value of `adminKey`. Subsequent reads from it will return its default value.
+ public mutating func clearAdminKey() {self._adminKey = nil}
+
public var unknownFields = SwiftProtobuf.UnknownStorage()
public init() {}
fileprivate var _accountID: Proto_AccountID? = nil
+ fileprivate var _adminKey: Proto_Key? = nil
}
#if swift(>=5.5) && canImport(_Concurrency)
-extension Proto_NodeStatus: @unchecked Sendable {}
-extension Proto_Node: @unchecked Sendable {}
+extension Com_Hedera_Hapi_Node_State_Addressbook_Node: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
-fileprivate let _protobuf_package = "proto"
+fileprivate let _protobuf_package = "com.hedera.hapi.node.state.addressbook"
-extension Proto_NodeStatus: SwiftProtobuf._ProtoNameProviding {
- public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
- 0: .same(proto: "DELETED"),
- 1: .same(proto: "PENDING_ADDITION"),
- 2: .same(proto: "PENDING_DELETION"),
- 3: .same(proto: "IN_CONSENSUS"),
- ]
-}
-
-extension Proto_Node: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
+extension Com_Hedera_Hapi_Node_State_Addressbook_Node: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
public static let protoMessageName: String = _protobuf_package + ".Node"
public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .standard(proto: "node_id"),
@@ -169,6 +177,8 @@ extension Proto_Node: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
6: .standard(proto: "gossip_ca_certificate"),
7: .standard(proto: "grpc_certificate_hash"),
8: .same(proto: "weight"),
+ 9: .same(proto: "deleted"),
+ 10: .standard(proto: "admin_key"),
]
public mutating func decodeMessage
+/// Transfer one or more token balances held by the requesting account to the treasury for each
+/// token type.
+/// Each transfer SHALL be one of the following
+/// - A single non-fungible/unique token.
+/// - The full balance held for a fungible/common token type.
+///
+/// A single tokenReject transaction SHALL support a maximum of 10 transfers.
+///
+/// ### Transaction Record Effects
+/// - Each successful transfer from `payer` to `treasury` SHALL be recorded in `token_transfer_list` for the transaction record.
+public struct Proto_TokenRejectTransactionBody {
+ // SwiftProtobuf.Message conformance is added in an extension below. See the
+ // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
+ // methods supported on all messages.
+
+ ///*
+ /// An account holding the tokens to be rejected.
+ /// If set, this account MUST sign this transaction.
+ /// If not set, the payer for this transaction SHALL be the account rejecting tokens.
+ public var owner: Proto_AccountID {
+ get {return _owner ?? Proto_AccountID()}
+ set {_owner = newValue}
+ }
+ /// Returns true if `owner` has been explicitly set.
+ public var hasOwner: Bool {return self._owner != nil}
+ /// Clears the value of `owner`. Subsequent reads from it will return its default value.
+ public mutating func clearOwner() {self._owner = nil}
+
+ ///*
+ /// A list of one or more token rejections.
+ /// On success each rejected token serial number or balance SHALL be transferred from
+ /// the requesting account to the treasury account for that token type.
+ /// After rejection the requesting account SHALL continue to be associated with the token.
+ /// if dissociation is desired then a separate TokenDissociate transaction MUST be submitted to remove the association.
+ public var rejections: [Proto_TokenReference] = []
+
+ public var unknownFields = SwiftProtobuf.UnknownStorage()
+
+ public init() {}
+
+ fileprivate var _owner: Proto_AccountID? = nil
+}
+
+///*
+/// A union token identifier.
+///
+/// Identify a fungible/common token type, or a single non-fungible/unique token serial.
+public struct Proto_TokenReference {
+ // SwiftProtobuf.Message conformance is added in an extension below. See the
+ // `Message` and `Message+*Additions` files in the SwiftProtobuf library for
+ // methods supported on all messages.
+
+ public var tokenIdentifier: Proto_TokenReference.OneOf_TokenIdentifier? = nil
+
+ ///*
+ /// A fungible/common token type.
+ public var fungibleToken: Proto_TokenID {
+ get {
+ if case .fungibleToken(let v)? = tokenIdentifier {return v}
+ return Proto_TokenID()
+ }
+ set {tokenIdentifier = .fungibleToken(newValue)}
+ }
+
+ ///*
+ /// A single specific serialized non-fungible/unique token.
+ public var nft: Proto_NftID {
+ get {
+ if case .nft(let v)? = tokenIdentifier {return v}
+ return Proto_NftID()
+ }
+ set {tokenIdentifier = .nft(newValue)}
+ }
+
+ public var unknownFields = SwiftProtobuf.UnknownStorage()
+
+ public enum OneOf_TokenIdentifier: Equatable {
+ ///*
+ /// A fungible/common token type.
+ case fungibleToken(Proto_TokenID)
+ ///*
+ /// A single specific serialized non-fungible/unique token.
+ case nft(Proto_NftID)
+
+ #if !swift(>=4.1)
+ public static func ==(lhs: Proto_TokenReference.OneOf_TokenIdentifier, rhs: Proto_TokenReference.OneOf_TokenIdentifier) -> Bool {
+ // The use of inline closures is to circumvent an issue where the compiler
+ // allocates stack space for every case branch when no optimizations are
+ // enabled. https://github.com/apple/swift-protobuf/issues/1034
+ switch (lhs, rhs) {
+ case (.fungibleToken, .fungibleToken): return {
+ guard case .fungibleToken(let l) = lhs, case .fungibleToken(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
+ case (.nft, .nft): return {
+ guard case .nft(let l) = lhs, case .nft(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
+ default: return false
+ }
+ }
+ #endif
+ }
+
+ public init() {}
+}
+
+#if swift(>=5.5) && canImport(_Concurrency)
+extension Proto_TokenRejectTransactionBody: @unchecked Sendable {}
+extension Proto_TokenReference: @unchecked Sendable {}
+extension Proto_TokenReference.OneOf_TokenIdentifier: @unchecked Sendable {}
+#endif // swift(>=5.5) && canImport(_Concurrency)
+
+// MARK: - Code below here is support for the SwiftProtobuf runtime.
+
+fileprivate let _protobuf_package = "proto"
+
+extension Proto_TokenRejectTransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
+ public static let protoMessageName: String = _protobuf_package + ".TokenRejectTransactionBody"
+ public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
+ 1: .same(proto: "owner"),
+ 2: .same(proto: "rejections"),
+ ]
+
+ public mutating func decodeMessage
+ /// This transaction will transfer one or more tokens or token
+ /// balances held by the requesting account to the treasury
+ /// for each token type.
+ ///
+ ///
+ /// When complete, the requesting account SHALL NOT hold the
+ /// rejected tokens.
+ /// Custom fees and royalties defined for the tokens rejected
+ /// SHALL NOT be charged for this transaction.
+ public var tokenReject: Proto_TokenRejectTransactionBody {
+ get {
+ if case .tokenReject(let v)? = _storage._data {return v}
+ return Proto_TokenRejectTransactionBody()
+ }
+ set {_uniqueStorage()._data = .tokenReject(newValue)}
+ }
+
public var unknownFields = SwiftProtobuf.UnknownStorage()
///*
@@ -597,21 +630,9 @@ public struct Proto_TransactionBody {
/// Updates a contract
case contractUpdateInstance(Proto_ContractUpdateTransactionBody)
///*
- /// Delete contract and transfer remaining balance into specified account
- case contractDeleteInstance(Proto_ContractDeleteTransactionBody)
- ///*
- /// An Ethereum encoded transaction.
- case ethereumTransaction(Proto_EthereumTransactionBody)
- ///*
/// Attach a new livehash to an account
case cryptoAddLiveHash(Proto_CryptoAddLiveHashTransactionBody)
///*
- /// Adds one or more approved allowances for spenders to transfer the paying account's hbar or tokens.
- case cryptoApproveAllowance(Proto_CryptoApproveAllowanceTransactionBody)
- ///*
- /// Deletes one or more of the specific approved NFT serial numbers on an owner account.
- case cryptoDeleteAllowance(Proto_CryptoDeleteAllowanceTransactionBody)
- ///*
/// Create a new cryptocurrency account
case cryptoCreateAccount(Proto_CryptoCreateTransactionBody)
///*
@@ -645,6 +666,9 @@ public struct Proto_TransactionBody {
/// To undelete an entity deleted by SystemDelete
case systemUndelete(Proto_SystemUndeleteTransactionBody)
///*
+ /// Delete contract and transfer remaining balance into specified account
+ case contractDeleteInstance(Proto_ContractDeleteTransactionBody)
+ ///*
/// Freeze the nodes
case freeze(Proto_FreezeTransactionBody)
///*
@@ -699,6 +723,15 @@ public struct Proto_TransactionBody {
/// Dissociate tokens from an account
case tokenDissociate(Proto_TokenDissociateTransactionBody)
///*
+ /// Creates a schedule in the network's action queue
+ case scheduleCreate(Proto_ScheduleCreateTransactionBody)
+ ///*
+ /// Deletes a schedule from the network's action queue
+ case scheduleDelete(Proto_ScheduleDeleteTransactionBody)
+ ///*
+ /// Adds one or more Ed25519 keys to the affirmed signers of a scheduled transaction
+ case scheduleSign(Proto_ScheduleSignTransactionBody)
+ ///*
/// Updates a token's custom fee schedule
case tokenFeeScheduleUpdate(Proto_TokenFeeScheduleUpdateTransactionBody)
///*
@@ -708,14 +741,14 @@ public struct Proto_TransactionBody {
/// Unpauses the Token
case tokenUnpause(Proto_TokenUnpauseTransactionBody)
///*
- /// Creates a schedule in the network's action queue
- case scheduleCreate(Proto_ScheduleCreateTransactionBody)
+ /// Adds one or more approved allowances for spenders to transfer the paying account's hbar or tokens.
+ case cryptoApproveAllowance(Proto_CryptoApproveAllowanceTransactionBody)
///*
- /// Deletes a schedule from the network's action queue
- case scheduleDelete(Proto_ScheduleDeleteTransactionBody)
+ /// Deletes one or more of the specific approved NFT serial numbers on an owner account.
+ case cryptoDeleteAllowance(Proto_CryptoDeleteAllowanceTransactionBody)
///*
- /// Adds one or more Ed25519 keys to the affirmed signers of a scheduled transaction
- case scheduleSign(Proto_ScheduleSignTransactionBody)
+ /// An Ethereum encoded transaction.
+ case ethereumTransaction(Proto_EthereumTransactionBody)
///*
/// Updates the staking info at the end of staking period to indicate new staking period has started.
case nodeStakeUpdate(Proto_NodeStakeUpdateTransactionBody)
@@ -727,13 +760,39 @@ public struct Proto_TransactionBody {
case tokenUpdateNfts(Proto_TokenUpdateNftsTransactionBody)
///*
/// A transaction body for a `createNode` request.
- case nodeCreate(Proto_NodeCreateTransactionBody)
+ ///
+ /// This transaction will transfer one or more tokens or token
+ /// balances held by the requesting account to the treasury
+ /// for each token type.
+ ///
+ ///
+ /// When complete, the requesting account SHALL NOT hold the
+ /// rejected tokens.
+ /// Custom fees and royalties defined for the tokens rejected
+ /// SHALL NOT be charged for this transaction.
+ case tokenReject(Proto_TokenRejectTransactionBody)
#if !swift(>=4.1)
public static func ==(lhs: Proto_TransactionBody.OneOf_Data, rhs: Proto_TransactionBody.OneOf_Data) -> Bool {
@@ -753,26 +812,10 @@ public struct Proto_TransactionBody {
guard case .contractUpdateInstance(let l) = lhs, case .contractUpdateInstance(let r) = rhs else { preconditionFailure() }
return l == r
}()
- case (.contractDeleteInstance, .contractDeleteInstance): return {
- guard case .contractDeleteInstance(let l) = lhs, case .contractDeleteInstance(let r) = rhs else { preconditionFailure() }
- return l == r
- }()
- case (.ethereumTransaction, .ethereumTransaction): return {
- guard case .ethereumTransaction(let l) = lhs, case .ethereumTransaction(let r) = rhs else { preconditionFailure() }
- return l == r
- }()
case (.cryptoAddLiveHash, .cryptoAddLiveHash): return {
guard case .cryptoAddLiveHash(let l) = lhs, case .cryptoAddLiveHash(let r) = rhs else { preconditionFailure() }
return l == r
}()
- case (.cryptoApproveAllowance, .cryptoApproveAllowance): return {
- guard case .cryptoApproveAllowance(let l) = lhs, case .cryptoApproveAllowance(let r) = rhs else { preconditionFailure() }
- return l == r
- }()
- case (.cryptoDeleteAllowance, .cryptoDeleteAllowance): return {
- guard case .cryptoDeleteAllowance(let l) = lhs, case .cryptoDeleteAllowance(let r) = rhs else { preconditionFailure() }
- return l == r
- }()
case (.cryptoCreateAccount, .cryptoCreateAccount): return {
guard case .cryptoCreateAccount(let l) = lhs, case .cryptoCreateAccount(let r) = rhs else { preconditionFailure() }
return l == r
@@ -817,6 +860,10 @@ public struct Proto_TransactionBody {
guard case .systemUndelete(let l) = lhs, case .systemUndelete(let r) = rhs else { preconditionFailure() }
return l == r
}()
+ case (.contractDeleteInstance, .contractDeleteInstance): return {
+ guard case .contractDeleteInstance(let l) = lhs, case .contractDeleteInstance(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
case (.freeze, .freeze): return {
guard case .freeze(let l) = lhs, case .freeze(let r) = rhs else { preconditionFailure() }
return l == r
@@ -889,6 +936,18 @@ public struct Proto_TransactionBody {
guard case .tokenDissociate(let l) = lhs, case .tokenDissociate(let r) = rhs else { preconditionFailure() }
return l == r
}()
+ case (.scheduleCreate, .scheduleCreate): return {
+ guard case .scheduleCreate(let l) = lhs, case .scheduleCreate(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
+ case (.scheduleDelete, .scheduleDelete): return {
+ guard case .scheduleDelete(let l) = lhs, case .scheduleDelete(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
+ case (.scheduleSign, .scheduleSign): return {
+ guard case .scheduleSign(let l) = lhs, case .scheduleSign(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
case (.tokenFeeScheduleUpdate, .tokenFeeScheduleUpdate): return {
guard case .tokenFeeScheduleUpdate(let l) = lhs, case .tokenFeeScheduleUpdate(let r) = rhs else { preconditionFailure() }
return l == r
@@ -901,16 +960,16 @@ public struct Proto_TransactionBody {
guard case .tokenUnpause(let l) = lhs, case .tokenUnpause(let r) = rhs else { preconditionFailure() }
return l == r
}()
- case (.scheduleCreate, .scheduleCreate): return {
- guard case .scheduleCreate(let l) = lhs, case .scheduleCreate(let r) = rhs else { preconditionFailure() }
+ case (.cryptoApproveAllowance, .cryptoApproveAllowance): return {
+ guard case .cryptoApproveAllowance(let l) = lhs, case .cryptoApproveAllowance(let r) = rhs else { preconditionFailure() }
return l == r
}()
- case (.scheduleDelete, .scheduleDelete): return {
- guard case .scheduleDelete(let l) = lhs, case .scheduleDelete(let r) = rhs else { preconditionFailure() }
+ case (.cryptoDeleteAllowance, .cryptoDeleteAllowance): return {
+ guard case .cryptoDeleteAllowance(let l) = lhs, case .cryptoDeleteAllowance(let r) = rhs else { preconditionFailure() }
return l == r
}()
- case (.scheduleSign, .scheduleSign): return {
- guard case .scheduleSign(let l) = lhs, case .scheduleSign(let r) = rhs else { preconditionFailure() }
+ case (.ethereumTransaction, .ethereumTransaction): return {
+ guard case .ethereumTransaction(let l) = lhs, case .ethereumTransaction(let r) = rhs else { preconditionFailure() }
return l == r
}()
case (.nodeStakeUpdate, .nodeStakeUpdate): return {
@@ -937,6 +996,10 @@ public struct Proto_TransactionBody {
guard case .nodeDelete(let l) = lhs, case .nodeDelete(let r) = rhs else { preconditionFailure() }
return l == r
}()
+ case (.tokenReject, .tokenReject): return {
+ guard case .tokenReject(let l) = lhs, case .tokenReject(let r) = rhs else { preconditionFailure() }
+ return l == r
+ }()
default: return false
}
}
@@ -969,11 +1032,7 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
7: .same(proto: "contractCall"),
8: .same(proto: "contractCreateInstance"),
9: .same(proto: "contractUpdateInstance"),
- 22: .same(proto: "contractDeleteInstance"),
- 50: .same(proto: "ethereumTransaction"),
10: .same(proto: "cryptoAddLiveHash"),
- 48: .same(proto: "cryptoApproveAllowance"),
- 49: .same(proto: "cryptoDeleteAllowance"),
11: .same(proto: "cryptoCreateAccount"),
12: .same(proto: "cryptoDelete"),
13: .same(proto: "cryptoDeleteLiveHash"),
@@ -985,6 +1044,7 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
19: .same(proto: "fileUpdate"),
20: .same(proto: "systemDelete"),
21: .same(proto: "systemUndelete"),
+ 22: .same(proto: "contractDeleteInstance"),
23: .same(proto: "freeze"),
24: .same(proto: "consensusCreateTopic"),
25: .same(proto: "consensusUpdateTopic"),
@@ -1003,18 +1063,22 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
39: .same(proto: "tokenWipe"),
40: .same(proto: "tokenAssociate"),
41: .same(proto: "tokenDissociate"),
- 45: .standard(proto: "token_fee_schedule_update"),
- 46: .standard(proto: "token_pause"),
- 47: .standard(proto: "token_unpause"),
42: .same(proto: "scheduleCreate"),
43: .same(proto: "scheduleDelete"),
44: .same(proto: "scheduleSign"),
+ 45: .standard(proto: "token_fee_schedule_update"),
+ 46: .standard(proto: "token_pause"),
+ 47: .standard(proto: "token_unpause"),
+ 48: .same(proto: "cryptoApproveAllowance"),
+ 49: .same(proto: "cryptoDeleteAllowance"),
+ 50: .same(proto: "ethereumTransaction"),
51: .standard(proto: "node_stake_update"),
52: .standard(proto: "util_prng"),
53: .standard(proto: "token_update_nfts"),
54: .same(proto: "nodeCreate"),
55: .same(proto: "nodeUpdate"),
56: .same(proto: "nodeDelete"),
+ 57: .same(proto: "tokenReject"),
]
fileprivate class _StorageClass {
@@ -1669,7 +1733,7 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
}
}()
case 54: try {
- var v: Proto_NodeCreateTransactionBody?
+ var v: Com_Hedera_Hapi_Node_Addressbook_NodeCreateTransactionBody?
var hadOneofValue = false
if let current = _storage._data {
hadOneofValue = true
@@ -1682,7 +1746,7 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
}
}()
case 55: try {
- var v: Proto_NodeUpdateTransactionBody?
+ var v: Com_Hedera_Hapi_Node_Addressbook_NodeUpdateTransactionBody?
var hadOneofValue = false
if let current = _storage._data {
hadOneofValue = true
@@ -1695,7 +1759,7 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
}
}()
case 56: try {
- var v: Proto_NodeDeleteTransactionBody?
+ var v: Com_Hedera_Hapi_Node_Addressbook_NodeDeleteTransactionBody?
var hadOneofValue = false
if let current = _storage._data {
hadOneofValue = true
@@ -1707,6 +1771,19 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
_storage._data = .nodeDelete(v)
}
}()
+ case 57: try {
+ var v: Proto_TokenRejectTransactionBody?
+ var hadOneofValue = false
+ if let current = _storage._data {
+ hadOneofValue = true
+ if case .tokenReject(let m) = current {v = m}
+ }
+ try decoder.decodeSingularMessageField(value: &v)
+ if let v = v {
+ if hadOneofValue {try decoder.handleConflictingOneOf()}
+ _storage._data = .tokenReject(v)
+ }
+ }()
default: break
}
}
@@ -1934,6 +2011,10 @@ extension Proto_TransactionBody: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
guard case .nodeDelete(let v)? = _storage._data else { preconditionFailure() }
try visitor.visitSingularMessageField(value: v, fieldNumber: 56)
}()
+ case .tokenReject?: try {
+ guard case .tokenReject(let v)? = _storage._data else { preconditionFailure() }
+ try visitor.visitSingularMessageField(value: v, fieldNumber: 57)
+ }()
case nil: break
}
}
diff --git a/Sources/HederaProtobufs/Services/transaction_receipt.pb.swift b/Sources/HederaProtobufs/Services/transaction_receipt.pb.swift
index 8abf6d8d..fc098927 100644
--- a/Sources/HederaProtobufs/Services/transaction_receipt.pb.swift
+++ b/Sources/HederaProtobufs/Services/transaction_receipt.pb.swift
@@ -100,59 +100,65 @@ public struct Proto_TransactionReceipt {
}
///*
- /// In the receipt of a ConsensusSubmitMessage, the new running hash of the topic that received
- /// the message. This 48-byte field is the output of a particular SHA-384 digest whose input
- /// data are determined by the value of the topicRunningHashVersion below. The bytes of each
- /// uint64 or uint32 are to be in Big-Endian format.
- ///
- /// IF the topicRunningHashVersion is '0' or '1', then the input data to the SHA-384 digest are,
+ /// In the receipt of a `ConsensusSubmitMessage`, the new running hash of the topic that
+ /// received the message.
+ /// This 48-byte field is the output of a SHA-384 digest with input data determined by the
+ /// value of the `topicRunningHashVersion` field.
+ /// All new transactions SHALL use `topicRunningHashVersion` `3`.
+ /// The bytes of each uint64 or uint32 encoded for the hash input MUST be in Big-Endian format.
+ ///
+ /// If the `topicRunningHashVersion` is '0' or '1', then the input data to the SHA-384 digest are,
/// in order:
- /// ---
- /// 1. The previous running hash of the topic (48 bytes)
- /// 2. The topic's shard (8 bytes)
- /// 3. The topic's realm (8 bytes)
- /// 4. The topic's number (8 bytes)
- /// 5. The number of seconds since the epoch before the ConsensusSubmitMessage reached
- /// consensus (8 bytes)
- /// 6. The number of nanoseconds since 5. before the ConsensusSubmitMessage reached
- /// consensus (4 bytes)
- /// 7. The topicSequenceNumber from above (8 bytes)
- /// 8. The message bytes from the ConsensusSubmitMessage (variable).
- ///
- /// IF the topicRunningHashVersion is '2', then the input data to the SHA-384 digest are, in
+ ///
+ ///
+ ///
+ /// If the `topicRunningHashVersion` is '2', then the input data to the SHA-384 digest are, in
/// order:
- /// ---
- /// 1. The previous running hash of the topic (48 bytes)
- /// 2. The topicRunningHashVersion below (8 bytes)
- /// 3. The topic's shard (8 bytes)
- /// 4. The topic's realm (8 bytes)
- /// 5. The topic's number (8 bytes)
- /// 6. The number of seconds since the epoch before the ConsensusSubmitMessage reached
- /// consensus (8 bytes)
- /// 7. The number of nanoseconds since 6. before the ConsensusSubmitMessage reached
- /// consensus (4 bytes)
- /// 8. The topicSequenceNumber from above (8 bytes)
- /// 9. The output of the SHA-384 digest of the message bytes from the
- /// consensusSubmitMessage (48 bytes)
- ///
- /// Otherwise, IF the topicRunningHashVersion is '3', then the input data to the SHA-384 digest
+ ///
+ ///
+ ///
+ /// If the `topicRunningHashVersion` is '3', then the input data to the SHA-384 digest
/// are, in order:
- /// ---
- /// 1. The previous running hash of the topic (48 bytes)
- /// 2. The topicRunningHashVersion below (8 bytes)
- /// 3. The payer account's shard (8 bytes)
- /// 4. The payer account's realm (8 bytes)
- /// 5. The payer account's number (8 bytes)
- /// 6. The topic's shard (8 bytes)
- /// 7. The topic's realm (8 bytes)
- /// 8. The topic's number (8 bytes)
- /// 9. The number of seconds since the epoch before the ConsensusSubmitMessage reached
- /// consensus (8 bytes)
- /// 10. The number of nanoseconds since 9. before the ConsensusSubmitMessage reached
- /// consensus (4 bytes)
- /// 11. The topicSequenceNumber from above (8 bytes)
- /// 12. The output of the SHA-384 digest of the message bytes from the
- /// consensusSubmitMessage (48 bytes)
+ ///
+ ///
public var topicRunningHash: Data {
get {return _storage._topicRunningHash}
set {_uniqueStorage()._topicRunningHash = newValue}
@@ -220,6 +226,11 @@ public struct Proto_TransactionReceipt {
///*
/// In the receipt of a NodeCreate, NodeUpdate, NodeDelete, the id of the newly created node.
+ /// An affected node identifier.
+ /// This value SHALL be set following a `createNode` transaction.
+ /// This value SHALL be set following a `updateNode` transaction.
+ /// This value SHALL be set following a `deleteNode` transaction.
+ /// This value SHALL NOT be set following any other transaction.
public var nodeID: UInt64 {
get {return _storage._nodeID}
set {_uniqueStorage()._nodeID = newValue}
diff --git a/Tests/HederaE2ETests/Account/Account.swift b/Tests/HederaE2ETests/Account/Account.swift
index a5f41a7e..5fd875ff 100644
--- a/Tests/HederaE2ETests/Account/Account.swift
+++ b/Tests/HederaE2ETests/Account/Account.swift
@@ -39,6 +39,25 @@ internal struct Account {
return Self(id: id, key: key)
}
+ internal static func create(
+ _ testEnv: NonfreeTestEnvironment, _ accountKey: Key, _ maxAutomaticTokenAssociations: Int32
+ ) async throws -> Self {
+ let key = PrivateKey.generateEd25519()
+
+ try await testEnv.ratelimits.accountCreate()
+
+ let receipt = try await AccountCreateTransaction()
+ .key(accountKey)
+ .initialBalance(Hbar(1))
+ .maxAutomaticTokenAssociations(maxAutomaticTokenAssociations)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let id = try XCTUnwrap(receipt.accountId)
+
+ return Self(id: id, key: key)
+ }
+
internal func delete(_ testEnv: NonfreeTestEnvironment) async throws {
_ = try await AccountDeleteTransaction()
.accountId(id)
diff --git a/Tests/HederaE2ETests/Account/AccountUpdate.swift b/Tests/HederaE2ETests/Account/AccountUpdate.swift
index 1ed07182..dee2a561 100644
--- a/Tests/HederaE2ETests/Account/AccountUpdate.swift
+++ b/Tests/HederaE2ETests/Account/AccountUpdate.swift
@@ -88,4 +88,56 @@ internal final class AccountUpdate: XCTestCase {
XCTAssertEqual(status, .accountIDDoesNotExist)
}
}
+
+ internal func testCannotUpdateTokenMaxAssociationToLowerValueFails() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let accountKey = PrivateKey.generateEd25519()
+
+ // Create account with max token associations of 1
+ let accountCreateReceipt = try await AccountCreateTransaction()
+ .key(.single(accountKey.publicKey))
+ .maxAutomaticTokenAssociations(1)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let accountId = try XCTUnwrap(accountCreateReceipt.accountId)
+
+ // Create token
+ let tokenCreateReceipt = try await TokenCreateTransaction()
+ .name("ffff")
+ .symbol("F")
+ .initialSupply(100_000)
+ .treasuryAccountId(testEnv.operator.accountId)
+ .adminKey(.single(testEnv.operator.privateKey.publicKey))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let tokenId = try XCTUnwrap(tokenCreateReceipt.tokenId)
+
+ // Associate token with account
+ let _ = try await TransferTransaction()
+ .tokenTransfer(tokenId, testEnv.operator.accountId, -10)
+ .tokenTransfer(tokenId, accountId, 10)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ // Update account max token associations to 0
+ try await AccountUpdateTransaction()
+ .accountId(accountId)
+ .maxAutomaticTokenAssociations(0)
+ .freezeWith(testEnv.client)
+ .sign(accountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .existingAutomaticAssociationsExceedGivenLimit)
+ }
+ }
}
diff --git a/Tests/HederaE2ETests/Contract/ContractCreate.swift b/Tests/HederaE2ETests/Contract/ContractCreate.swift
index 1f32ce5b..3efd1ccf 100644
--- a/Tests/HederaE2ETests/Contract/ContractCreate.swift
+++ b/Tests/HederaE2ETests/Contract/ContractCreate.swift
@@ -92,12 +92,11 @@ internal final class ContractCreate: XCTestCase {
.constructorParameters(ContractFunctionParameters().addString("Hello from Hedera."))
.bytecodeFileId(bytecode.fileId)
.contractMemo("[e2e::ContractCreateTransaction]")
- .execute(testEnv.client)
- .getReceipt(testEnv.client),
+ .execute(testEnv.client),
"expected error creating contract"
) { error in
- guard case .receiptStatus(let status, transactionId: _) = error.kind else {
- XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ guard case .transactionPreCheckStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.transactionPreCheckStatus`")
return
}
diff --git a/Tests/HederaE2ETests/Token/FungibleToken.swift b/Tests/HederaE2ETests/Token/FungibleToken.swift
index 0465989f..b22d0c2d 100644
--- a/Tests/HederaE2ETests/Token/FungibleToken.swift
+++ b/Tests/HederaE2ETests/Token/FungibleToken.swift
@@ -27,31 +27,63 @@ internal struct FungibleToken {
internal static func create(
_ testEnv: NonfreeTestEnvironment,
- owner: Account,
+ owner: Account? = nil,
initialSupply: UInt64 = 0
) async throws -> Self {
- let metadataKey = PrivateKey.generateEd25519()
- let ownerKey = Key.single(owner.key.publicKey)
- let receipt = try await TokenCreateTransaction(
- name: "ffff",
- symbol: "f",
- decimals: 3,
- initialSupply: initialSupply,
- treasuryAccountId: owner.id,
- adminKey: ownerKey,
- kycKey: ownerKey,
- freezeKey: ownerKey,
- wipeKey: ownerKey,
- supplyKey: ownerKey,
- freezeDefault: false,
- expirationTime: .now + .minutes(5),
- feeScheduleKey: ownerKey,
- pauseKey: ownerKey,
- metadataKey: Key.single(metadataKey.publicKey)
- )
- .sign(owner.key)
- .execute(testEnv.client)
- .getReceipt(testEnv.client)
+ let privateKey = owner?.key ?? testEnv.operator.privateKey
+ let owner = owner ?? Account(id: testEnv.operator.accountId, key: testEnv.operator.privateKey)
+
+ let receipt = try await TokenCreateTransaction()
+ .name("ffff")
+ .symbol("f")
+ .tokenMemo("e2e test")
+ .expirationTime(.now + .minutes(5))
+ .decimals(3)
+ .initialSupply(initialSupply)
+ .treasuryAccountId(owner.id)
+ .adminKey(.single(privateKey.publicKey))
+ .freezeKey(.single(privateKey.publicKey))
+ .wipeKey(.single(privateKey.publicKey))
+ .supplyKey(.single(privateKey.publicKey))
+ .metadataKey(.single(privateKey.publicKey))
+ .pauseKey(.single(privateKey.publicKey))
+ .kycKey(.single(privateKey.publicKey))
+ .feeScheduleKey(.single(privateKey.publicKey))
+ .freezeDefault(false)
+ .freezeWith(testEnv.client)
+ .sign(privateKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let id = try XCTUnwrap(receipt.tokenId)
+
+ return Self(id: id, owner: owner)
+ }
+
+ internal static func create(
+ _ testEnv: NonfreeTestEnvironment,
+ decimals: UInt32
+ ) async throws -> Self {
+ let owner = Account(id: testEnv.operator.accountId, key: testEnv.operator.privateKey)
+
+ let receipt = try await TokenCreateTransaction()
+ .name("ffff")
+ .symbol("f")
+ .tokenMemo("e2e test")
+ .expirationTime(.now + .minutes(5))
+ .decimals(decimals)
+ .initialSupply(1_000_000)
+ .maxSupply(1_000_000)
+ .treasuryAccountId(testEnv.operator.accountId)
+ .tokenSupplyType(.finite)
+ .adminKey(.single(testEnv.operator.privateKey.publicKey))
+ .freezeKey(.single(testEnv.operator.privateKey.publicKey))
+ .wipeKey(.single(testEnv.operator.privateKey.publicKey))
+ .supplyKey(.single(testEnv.operator.privateKey.publicKey))
+ .metadataKey(.single(testEnv.operator.privateKey.publicKey))
+ .pauseKey(.single(testEnv.operator.privateKey.publicKey))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
let id = try XCTUnwrap(receipt.tokenId)
diff --git a/Tests/HederaE2ETests/Token/Nft.swift b/Tests/HederaE2ETests/Token/Nft.swift
index 4efe68af..88c515c0 100644
--- a/Tests/HederaE2ETests/Token/Nft.swift
+++ b/Tests/HederaE2ETests/Token/Nft.swift
@@ -25,20 +25,23 @@ internal struct Nft {
internal let id: TokenId
internal let owner: Account
- internal static func create(_ testEnv: NonfreeTestEnvironment, owner: Account) async throws -> Self {
- let ownerKey = Key.single(owner.key.publicKey)
+ internal static func create(_ testEnv: NonfreeTestEnvironment, owner: Account? = nil) async throws -> Self {
+ let owner = owner ?? Account(id: testEnv.operator.accountId, key: testEnv.operator.privateKey)
+
let receipt = try await TokenCreateTransaction(
name: "ffff",
symbol: "f",
treasuryAccountId: owner.id,
- adminKey: ownerKey,
- freezeKey: ownerKey,
- wipeKey: ownerKey,
- supplyKey: ownerKey,
+ adminKey: Key.single(owner.key.publicKey),
+ freezeKey: Key.single(owner.key.publicKey),
+ wipeKey: Key.single(owner.key.publicKey),
+ supplyKey: Key.single(owner.key.publicKey),
freezeDefault: false,
expirationTime: .now + .minutes(5),
tokenType: .nonFungibleUnique,
- feeScheduleKey: ownerKey
+ feeScheduleKey: Key.single(owner.key.publicKey),
+ pauseKey: Key.single(owner.key.publicKey),
+ metadataKey: Key.single(owner.key.publicKey)
)
.sign(owner.key)
.execute(testEnv.client)
diff --git a/Tests/HederaE2ETests/Token/TokenReject.swift b/Tests/HederaE2ETests/Token/TokenReject.swift
new file mode 100644
index 00000000..7e66d478
--- /dev/null
+++ b/Tests/HederaE2ETests/Token/TokenReject.swift
@@ -0,0 +1,721 @@
+/*
+ *
+ * Hedera Swift SDK
+ *
+ * Copyright (C) 2022 - 2024 Hedera Hashgraph, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import Hedera
+import XCTest
+
+internal class TokenReject: XCTestCase {
+ internal func testBasicFtReject() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft1 = try await FungibleToken.create(testEnv, decimals: 3)
+ let ft2 = try await FungibleToken.create(testEnv, decimals: 3)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let _ = try await TransferTransaction()
+ .tokenTransfer(ft1.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft1.id, receiverAccount.id, 10)
+ .tokenTransfer(ft2.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft2.id, receiverAccount.id, 10)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .tokenIds([ft1.id, ft2.id])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let receiverBalance = try await AccountBalanceQuery()
+ .accountId(receiverAccount.id)
+ .execute(testEnv.client)
+
+ XCTAssertEqual(receiverBalance.tokenBalances[ft1.id], 0)
+ XCTAssertEqual(receiverBalance.tokenBalances[ft2.id], 0)
+
+ let treasuryAccountBalance = try await AccountBalanceQuery()
+ .accountId(testEnv.operator.accountId)
+ .execute(testEnv.client)
+
+ XCTAssertEqual(treasuryAccountBalance.tokenBalances[ft1.id], 1_000_000)
+ XCTAssertEqual(treasuryAccountBalance.tokenBalances[ft2.id], 1_000_000)
+
+ addTeardownBlock {
+ try await ft1.delete(testEnv)
+ try await ft2.delete(testEnv)
+ }
+ }
+
+ internal func testBasicNftReject() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let nft1 = try await Nft.create(testEnv)
+ let nft2 = try await Nft.create(testEnv)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let _ = try await TokenMintTransaction()
+ .tokenId(nft1.id)
+ .metadata(Array(repeating: Data([9, 1, 6]), count: 5))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftMintReceipt2 = try await TokenMintTransaction()
+ .tokenId(nft2.id)
+ .metadata(Array(repeating: Data([3, 6, 9]), count: 5))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(nftMintReceipt2.serials)
+
+ let _ = try await TransferTransaction()
+ .nftTransfer(nft1.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft1.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft2.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft2.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .nftIds([nft1.id.nft(nftSerials[1]), nft2.id.nft(nftSerials[1])])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nft1Info = try await TokenNftInfoQuery()
+ .nftId(nft1.id.nft(nftSerials[1]))
+ .execute(testEnv.client)
+
+ XCTAssertEqual(nft1Info.accountId, testEnv.operator.accountId)
+
+ let nft2Info = try await TokenNftInfoQuery()
+ .nftId(nft2.id.nft(nftSerials[1]))
+ .execute(testEnv.client)
+
+ XCTAssertEqual(nft2Info.accountId, testEnv.operator.accountId)
+
+ addTeardownBlock {
+ try await nft1.delete(testEnv)
+ try await nft2.delete(testEnv)
+ }
+ }
+
+ internal func testFtAndNftReject() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft1 = try await FungibleToken.create(testEnv, decimals: 3)
+ let ft2 = try await FungibleToken.create(testEnv, decimals: 3)
+ let nft1 = try await Nft.create(testEnv)
+ let nft2 = try await Nft.create(testEnv)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let _ = try await TokenMintTransaction()
+ .tokenId(nft1.id)
+ .metadata(Array(repeating: Data([9, 1, 6]), count: 5))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftMintReceipt2 = try await TokenMintTransaction()
+ .tokenId(nft2.id)
+ .metadata(Array(repeating: Data([3, 6, 9]), count: 5))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(nftMintReceipt2.serials)
+
+ let _ = try await TransferTransaction()
+ .tokenTransfer(ft1.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft1.id, receiverAccount.id, 10)
+ .tokenTransfer(ft2.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft2.id, receiverAccount.id, 10)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TransferTransaction()
+ .nftTransfer(nft1.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft1.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft2.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft2.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .tokenIds([ft1.id, ft2.id])
+ .nftIds([nft1.id.nft(nftSerials[1]), nft2.id.nft(nftSerials[1])])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let receiverAccountBalance = try await AccountBalanceQuery()
+ .accountId(receiverAccount.id)
+ .execute(testEnv.client)
+
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[ft1.id], 0)
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[ft2.id], 0)
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[nft1.id], 1)
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[nft2.id], 1)
+
+ let treasuryAccountBalance = try await AccountBalanceQuery()
+ .accountId(testEnv.operator.accountId)
+ .execute(testEnv.client)
+
+ XCTAssertEqual(treasuryAccountBalance.tokenBalances[ft1.id], 1_000_000)
+ XCTAssertEqual(treasuryAccountBalance.tokenBalances[ft2.id], 1_000_000)
+
+ let nft1Info = try await TokenNftInfoQuery()
+ .nftId(nft1.id.nft(nftSerials[1]))
+ .execute(testEnv.client)
+
+ XCTAssertEqual(nft1Info.accountId, testEnv.operator.accountId)
+
+ let nft2Info = try await TokenNftInfoQuery()
+ .nftId(nft2.id.nft(nftSerials[1]))
+ .execute(testEnv.client)
+
+ XCTAssertEqual(nft2Info.accountId, testEnv.operator.accountId)
+
+ addTeardownBlock {
+ try await ft1.delete(testEnv)
+ try await ft2.delete(testEnv)
+ try await nft1.delete(testEnv)
+ try await nft2.delete(testEnv)
+ }
+ }
+
+ internal func testFtAndNftFreeze() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft1 = try await FungibleToken.create(testEnv, decimals: 3)
+ let ft2 = try await FungibleToken.create(testEnv, decimals: 3)
+ let nft1 = try await Nft.create(testEnv)
+ let nft2 = try await Nft.create(testEnv)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let _ = try await TokenMintTransaction()
+ .tokenId(nft1.id)
+ .metadata(Array(repeating: Data([9, 1, 6]), count: 5))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftMintReceipt2 = try await TokenMintTransaction()
+ .tokenId(nft2.id)
+ .metadata(Array(repeating: Data([3, 6, 9]), count: 5))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(nftMintReceipt2.serials)
+
+ let _ = try await TransferTransaction()
+ .tokenTransfer(ft1.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft1.id, receiverAccount.id, 10)
+ .tokenTransfer(ft2.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft2.id, receiverAccount.id, 10)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TransferTransaction()
+ .nftTransfer(nft1.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft1.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft2.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft2.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .tokenIds([ft1.id, ft2.id])
+ .nftIds([nft1.id.nft(nftSerials[1]), nft2.id.nft(nftSerials[1])])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let receiverAccountBalance = try await AccountBalanceQuery()
+ .accountId(receiverAccount.id)
+ .execute(testEnv.client)
+
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[ft1.id], 0)
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[ft2.id], 0)
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[nft1.id], 1)
+ XCTAssertEqual(receiverAccountBalance.tokenBalances[nft2.id], 1)
+
+ let treasuryAccountBalance = try await AccountBalanceQuery()
+ .accountId(testEnv.operator.accountId)
+ .execute(testEnv.client)
+
+ XCTAssertEqual(treasuryAccountBalance.tokenBalances[ft1.id], 1_000_000)
+ XCTAssertEqual(treasuryAccountBalance.tokenBalances[ft2.id], 1_000_000)
+
+ let nft1Info = try await TokenNftInfoQuery()
+ .nftId(nft1.id.nft(nftSerials[1]))
+ .execute(testEnv.client)
+
+ XCTAssertEqual(nft1Info.accountId, testEnv.operator.accountId)
+
+ let nft2Info = try await TokenNftInfoQuery()
+ .nftId(nft2.id.nft(nftSerials[1]))
+ .execute(testEnv.client)
+
+ XCTAssertEqual(nft2Info.accountId, testEnv.operator.accountId)
+
+ addTeardownBlock {
+ try await ft1.delete(testEnv)
+ try await ft2.delete(testEnv)
+ try await nft1.delete(testEnv)
+ try await nft2.delete(testEnv)
+ }
+ }
+
+ internal func testFtAndNftPaused() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft = try await FungibleToken.create(testEnv, decimals: 3)
+ let nft = try await Nft.create(testEnv)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let _ = try await TransferTransaction()
+ .tokenTransfer(ft.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft.id, receiverAccount.id, 10)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenPauseTransaction()
+ .tokenId(ft.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .addTokenId(ft.id)
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .tokenIsPaused)
+ }
+
+ let mintReceipt = try await TokenMintTransaction()
+ .tokenId(nft.id)
+ .metadata(Array(repeating: Data([9, 1, 6]), count: 5))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(mintReceipt.serials)
+
+ let _ = try await TransferTransaction()
+ .nftTransfer(nft.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenPauseTransaction()
+ .tokenId(nft.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .addNftId(nft.id.nft(nftSerials[1]))
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .tokenIsPaused)
+ }
+ }
+
+ internal func testRemoveAllowance() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft = try await FungibleToken.create(testEnv, decimals: 3)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let spenderAccountKey = PrivateKey.generateEd25519()
+ let spenderCreateReceipt = try await AccountCreateTransaction()
+ .key(.single(spenderAccountKey.publicKey))
+ .initialBalance(Hbar(1))
+ .maxAutomaticTokenAssociations(-1)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let spenderAccountId = try XCTUnwrap(spenderCreateReceipt.accountId)
+
+ let _ = try await TransferTransaction()
+ .tokenTransfer(ft.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft.id, receiverAccount.id, 10)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await AccountAllowanceApproveTransaction()
+ .approveTokenAllowance(ft.id, receiverAccount.id, spenderAccountId, 10)
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TransferTransaction()
+ .approvedTokenTransfer(ft.id, receiverAccount.id, -5)
+ .tokenTransfer(ft.id, spenderAccountId, 5)
+ .transactionId(TransactionId.generateFrom(spenderAccountId))
+ .freezeWith(testEnv.client)
+ .sign(spenderAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .addTokenId(ft.id)
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ try await TransferTransaction()
+ .approvedTokenTransfer(ft.id, receiverAccount.id, -5)
+ .tokenTransfer(ft.id, spenderAccountId, 5)
+ .transactionId(TransactionId.generateFrom(spenderAccountId))
+ .freezeWith(testEnv.client)
+ .sign(spenderAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .spenderDoesNotHaveAllowance)
+ }
+
+ let nft = try await Nft.create(testEnv)
+
+ let mintReceipt = try await TokenMintTransaction()
+ .tokenId(nft.id)
+ .metadata(Array(repeating: Data([4, 2, 0]), count: 4))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(mintReceipt.serials)
+
+ let _ = try await TransferTransaction()
+ .nftTransfer(nft.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[2]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[3]), testEnv.operator.accountId, receiverAccount.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await AccountAllowanceApproveTransaction()
+ .approveTokenNftAllowance(nft.id.nft(nftSerials[0]), receiverAccount.id, spenderAccountId)
+ .approveTokenNftAllowance(nft.id.nft(nftSerials[1]), receiverAccount.id, spenderAccountId)
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TransferTransaction()
+ .approvedNftTransfer(nft.id.nft(nftSerials[0]), receiverAccount.id, spenderAccountId)
+ .transactionId(TransactionId.generateFrom(spenderAccountId))
+ .freezeWith(testEnv.client)
+ .sign(spenderAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let _ = try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .nftIds([nft.id.nft(nftSerials[1]), nft.id.nft(nftSerials[2])])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ try await TransferTransaction()
+ .approvedNftTransfer(nft.id.nft(nftSerials[1]), receiverAccount.id, spenderAccountId)
+ .approvedNftTransfer(nft.id.nft(nftSerials[2]), receiverAccount.id, spenderAccountId)
+ .transactionId(TransactionId.generateFrom(spenderAccountId))
+ .freezeWith(testEnv.client)
+ .sign(spenderAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .spenderDoesNotHaveAllowance)
+ }
+
+ addTeardownBlock {
+ try await ft.delete(testEnv)
+ try await nft.delete(testEnv)
+ }
+ }
+
+ internal func testAddOrSetNftTokenIdFail() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let nft = try await Nft.create(testEnv)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let mintReceipt = try await TokenMintTransaction()
+ .tokenId(nft.id)
+ .metadata(Array(repeating: Data([4, 2, 0]), count: 4))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(mintReceipt.serials)
+
+ let _ = try await TransferTransaction()
+ .nftTransfer(nft.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[2]), testEnv.operator.accountId, receiverAccount.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .addTokenId(nft.id)
+ .nftIds([nft.id.nft(nftSerials[1]), nft.id.nft(nftSerials[2])])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .accountAmountTransfersOnlyAllowedForFungibleCommon)
+ }
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .tokenIds([nft.id])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .accountAmountTransfersOnlyAllowedForFungibleCommon)
+ }
+
+ addTeardownBlock {
+ try await nft.delete(testEnv)
+ }
+ }
+
+ internal func testTreasuryFail() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft = try await FungibleToken.create(testEnv, decimals: 3)
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(testEnv.operator.accountId)
+ .addTokenId(ft.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .accountIsTreasury)
+ }
+
+ let nft = try await Nft.create(testEnv)
+
+ let mintReceipt = try await TokenMintTransaction()
+ .tokenId(nft.id)
+ .metadata(Array(repeating: Data([4, 2, 0]), count: 4))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(mintReceipt.serials)
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(testEnv.operator.accountId)
+ .addNftId(nft.id.nft(nftSerials[0]))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .accountIsTreasury)
+ }
+ }
+
+ internal func testInvalidSigFail() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft = try await FungibleToken.create(testEnv, decimals: 3)
+ let randomKey = PrivateKey.generateEd25519()
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), 100)
+
+ let _ = try await TransferTransaction()
+ .tokenTransfer(ft.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft.id, receiverAccount.id, 10)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .addTokenId(ft.id)
+ .freezeWith(testEnv.client)
+ .sign(randomKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .invalidSignature)
+ }
+
+ addTeardownBlock {
+ try await ft.delete(testEnv)
+ }
+ }
+
+ internal func testMissingTokenFail() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(testEnv.operator.accountId)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .transactionPreCheckStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.transactionPreCheckStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .emptyTokenReferenceList)
+ }
+ }
+
+ internal func testTokenReferenceListSizeExceededFail() async throws {
+ let testEnv = try TestEnvironment.nonFree
+
+ let ft = try await FungibleToken.create(testEnv, decimals: 3)
+ let nft = try await Nft.create(testEnv)
+ let receiverAccountKey = PrivateKey.generateEd25519()
+ let receiverAccount = try await Account.create(testEnv, Key.single(receiverAccountKey.publicKey), -1)
+
+ let mintReceipt = try await TokenMintTransaction()
+ .tokenId(nft.id)
+ .metadata(Array(repeating: Data([9, 1, 6]), count: 10))
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ let nftSerials = try XCTUnwrap(mintReceipt.serials)
+
+ let _ = try await TransferTransaction()
+ .tokenTransfer(ft.id, testEnv.operator.accountId, -10)
+ .tokenTransfer(ft.id, receiverAccount.id, 10)
+ .nftTransfer(nft.id.nft(nftSerials[0]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[1]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[2]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[3]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[4]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[5]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[6]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[7]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[8]), testEnv.operator.accountId, receiverAccount.id)
+ .nftTransfer(nft.id.nft(nftSerials[9]), testEnv.operator.accountId, receiverAccount.id)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+
+ await assertThrowsHErrorAsync(
+ try await TokenRejectTransaction()
+ .owner(receiverAccount.id)
+ .addTokenId(ft.id)
+ .nftIds([
+ nft.id.nft(nftSerials[0]), nft.id.nft(nftSerials[1]), nft.id.nft(nftSerials[2]),
+ nft.id.nft(nftSerials[3]), nft.id.nft(nftSerials[4]), nft.id.nft(nftSerials[5]),
+ nft.id.nft(nftSerials[6]), nft.id.nft(nftSerials[7]), nft.id.nft(nftSerials[8]),
+ nft.id.nft(nftSerials[9]),
+ ])
+ .freezeWith(testEnv.client)
+ .sign(receiverAccountKey)
+ .execute(testEnv.client)
+ .getReceipt(testEnv.client)
+ ) { error in
+ guard case .receiptStatus(let status, transactionId: _) = error.kind else {
+ XCTFail("`\(error.kind)` is not `.receiptStatus`")
+ return
+ }
+
+ XCTAssertEqual(status, .tokenReferenceListSizeLimitExceeded)
+ }
+
+ addTeardownBlock {
+ try await nft.delete(testEnv)
+ try await ft.delete(testEnv)
+ }
+ }
+}
diff --git a/Tests/HederaTests/AccountCreateTransactionTests.swift b/Tests/HederaTests/AccountCreateTransactionTests.swift
index cd6666a3..29fdfeea 100644
--- a/Tests/HederaTests/AccountCreateTransactionTests.swift
+++ b/Tests/HederaTests/AccountCreateTransactionTests.swift
@@ -26,7 +26,7 @@ import XCTest
internal class AccountCreateTransactionTests: XCTestCase {
private static let testKey = Key.single(Resources.publicKey)
- private static let testMaxAutomaticTokenAssociations: UInt32 = 101
+ private static let testMaxAutomaticTokenAssociations: Int32 = 101
private static let testAutoRenewPeriod = Duration.hours(10)
private static let testAutoRenewAccountId: AccountId = 30
private static let testStakedAccountId: AccountId = 3
@@ -126,7 +126,7 @@ internal class AccountCreateTransactionTests: XCTestCase {
proto.key = Self.testKey.toProtobuf()
proto.stakedNodeID = Int64(Self.testStakedNodeId)
proto.stakedAccountID = Self.testStakedAccountId.toProtobuf()
- proto.maxAutomaticTokenAssociations = Int32(Self.testMaxAutomaticTokenAssociations)
+ proto.maxAutomaticTokenAssociations = Self.testMaxAutomaticTokenAssociations
}
let protoBody = Proto_TransactionBody.with { proto in
diff --git a/Tests/HederaTests/ContractCreateTransactionTests.swift b/Tests/HederaTests/ContractCreateTransactionTests.swift
index 1d744c96..abf32565 100644
--- a/Tests/HederaTests/ContractCreateTransactionTests.swift
+++ b/Tests/HederaTests/ContractCreateTransactionTests.swift
@@ -29,7 +29,7 @@ internal class ContractCreateTransactionTests: XCTestCase {
private static let adminKey = Key.single(Resources.publicKey)
private static let gas: UInt64 = 0
private static let initialBalance = Hbar.fromTinybars(1000)
- private static let maxAutomaticTokenAssociations: UInt32 = 101
+ private static let maxAutomaticTokenAssociations: Int32 = 101
private static let autoRenewPeriod = Duration.hours(10)
private static let constructorParameters = Data([10, 11, 12, 13, 25])
private static let autoRenewAccountId: AccountId = 30
@@ -104,7 +104,7 @@ internal class ContractCreateTransactionTests: XCTestCase {
proto.adminKey = Self.adminKey.toProtobuf()
proto.gas = Int64(Self.gas)
proto.initialBalance = Self.initialBalance.toTinybars()
- proto.maxAutomaticTokenAssociations = Int32(Self.maxAutomaticTokenAssociations)
+ proto.maxAutomaticTokenAssociations = Self.maxAutomaticTokenAssociations
proto.autoRenewPeriod = Self.autoRenewPeriod.toProtobuf()
proto.constructorParameters = Self.constructorParameters
proto.autoRenewAccountID = Self.autoRenewAccountId.toProtobuf()
diff --git a/Tests/HederaTests/ContractUpdateTransactionTests.swift b/Tests/HederaTests/ContractUpdateTransactionTests.swift
index 9634b3ce..8d685ac6 100644
--- a/Tests/HederaTests/ContractUpdateTransactionTests.swift
+++ b/Tests/HederaTests/ContractUpdateTransactionTests.swift
@@ -27,7 +27,7 @@ import XCTest
internal final class ContractUpdateTransactionTests: XCTestCase {
private static let contractId: ContractId = "0.0.5007"
private static let adminKey = Key.single(Resources.publicKey)
- private static let maxAutomaticTokenAssociations: UInt32 = 101
+ private static let maxAutomaticTokenAssociations: Int32 = 101
private static let autoRenewPeriod = Duration.days(1)
private static let contractMemo = "3"
private static let expirationTime = Timestamp(seconds: 1_554_158_543, subSecondNanos: 0)
@@ -102,7 +102,7 @@ internal final class ContractUpdateTransactionTests: XCTestCase {
let protoData = Proto_ContractUpdateTransactionBody.with { proto in
proto.contractID = Self.contractId.toProtobuf()
proto.adminKey = Self.adminKey.toProtobuf()
- proto.maxAutomaticTokenAssociations = .init(Int32(Self.maxAutomaticTokenAssociations))
+ proto.maxAutomaticTokenAssociations = .init(Self.maxAutomaticTokenAssociations)
proto.autoRenewPeriod = Self.autoRenewPeriod.toProtobuf()
proto.memoWrapper = .init(Self.contractMemo)
proto.expirationTime = Self.expirationTime.toProtobuf()
diff --git a/Tests/HederaTests/TokenRejectTransaction.swift b/Tests/HederaTests/TokenRejectTransaction.swift
new file mode 100644
index 00000000..9a777c9f
--- /dev/null
+++ b/Tests/HederaTests/TokenRejectTransaction.swift
@@ -0,0 +1,127 @@
+/*
+ *
+ * Hedera Swift SDK
+ *
+ * Copyright (C) 2022 - 2024 Hedera Hashgraph, LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import HederaProtobufs
+import SnapshotTesting
+import XCTest
+
+@testable import Hedera
+
+internal final class TokenRejectTransactionTests: XCTestCase {
+ private static let testPrivateKey = PrivateKey(
+ "302e020100300506032b657004220420db484b828e64b2d8f12ce3c0a0e93a0b8cce7af1bb8f39c97732394482538e10")
+ private static let testOwnerId = AccountId("0.0.12345")
+
+ private static let testTokenIds: [TokenId] = [TokenId("4.2.0"), TokenId("4.2.1"), TokenId("4.2.2")]
+
+ private static let testNftIds: [NftId] = [NftId("4.2.3/1"), NftId("4.2.4/2"), NftId("4.2.5/3")]
+
+ private static func makeTransaction() throws -> TokenRejectTransaction {
+ try TokenRejectTransaction()
+ .nodeAccountIds(Resources.nodeAccountIds)
+ .transactionId(Resources.txId)
+ .owner(testOwnerId)
+ .tokenIds(testTokenIds)
+ .nftIds(testNftIds)
+ .freeze()
+ .sign(testPrivateKey)
+ }
+
+ internal func testSerialize() throws {
+ let tx = try Self.makeTransaction().makeProtoBody()
+
+ assertSnapshot(matching: tx, as: .description)
+ }
+
+ internal func testToFromBytes() throws {
+ let tx = try Self.makeTransaction()
+
+ let tx2 = try Transaction.fromBytes(tx.toBytes())
+
+ XCTAssertEqual(try tx.makeProtoBody(), try tx2.makeProtoBody())
+ }
+
+ internal func testFromProtoBody() throws {
+ var protoTokenReferences: [Proto_TokenReference] = []
+
+ for tokenId in Self.testTokenIds {
+ protoTokenReferences.append(.with { $0.fungibleToken = tokenId.toProtobuf() })
+ }
+
+ for nftId in Self.testNftIds {
+ protoTokenReferences.append(.with { $0.nft = nftId.toProtobuf() })
+ }
+
+ let protoData = Proto_TokenRejectTransactionBody.with { proto in
+ proto.owner = Self.testOwnerId.toProtobuf()
+ proto.rejections = protoTokenReferences
+ }
+
+ let protoBody = Proto_TransactionBody.with { proto in
+ proto.tokenReject = protoData
+ proto.transactionID = Resources.txId.toProtobuf()
+ }
+
+ let tx = try TokenRejectTransaction(protobuf: protoBody, protoData)
+
+ XCTAssertEqual(tx.owner, Self.testOwnerId)
+ XCTAssertEqual(tx.tokenIds, Self.testTokenIds)
+ XCTAssertEqual(tx.nftIds, Self.testNftIds)
+ }
+
+ internal func testGetSetOwner() {
+ let tx = TokenRejectTransaction()
+ tx.owner(Self.testOwnerId)
+
+ XCTAssertEqual(tx.owner, Self.testOwnerId)
+ }
+
+ internal func testGetSetTokenIds() {
+ let tx = TokenRejectTransaction()
+ tx.tokenIds(Self.testTokenIds)
+
+ XCTAssertEqual(tx.tokenIds, Self.testTokenIds)
+ }
+
+ internal func testGetSetNftIds() {
+ let tx = TokenRejectTransaction()
+ tx.nftIds(Self.testNftIds)
+
+ XCTAssertEqual(tx.nftIds, Self.testNftIds)
+ }
+
+ internal func testGetSetAddTokenId() {
+ let tx = TokenRejectTransaction()
+ tx.addTokenId(Self.testTokenIds[0])
+ tx.addTokenId(Self.testTokenIds[1])
+
+ XCTAssertEqual(tx.tokenIds[0], Self.testTokenIds[0])
+ XCTAssertEqual(tx.tokenIds[1], Self.testTokenIds[1])
+ }
+
+ internal func testGetSetAddNftId() {
+ let tx = TokenRejectTransaction()
+ tx.addNftId(Self.testNftIds[0])
+ tx.addNftId(Self.testNftIds[1])
+
+ XCTAssertEqual(tx.nftIds[0], Self.testNftIds[0])
+ XCTAssertEqual(tx.nftIds[1], Self.testNftIds[1])
+ }
+}
diff --git a/Tests/HederaTests/__Snapshots__/TokenRejectTransaction/testSerialize.1.txt b/Tests/HederaTests/__Snapshots__/TokenRejectTransaction/testSerialize.1.txt
new file mode 100644
index 00000000..b4892b77
--- /dev/null
+++ b/Tests/HederaTests/__Snapshots__/TokenRejectTransaction/testSerialize.1.txt
@@ -0,0 +1,71 @@
+HederaProtobufs.Proto_TransactionBody:
+transactionID {
+ transactionValidStart {
+ seconds: 1554158542
+ }
+ accountID {
+ accountNum: 5006
+ }
+}
+nodeAccountID {
+ accountNum: 5005
+}
+transactionFee: 200000000
+transactionValidDuration {
+ seconds: 120
+}
+tokenReject {
+ owner {
+ accountNum: 12345
+ }
+ rejections {
+ fungible_token {
+ shardNum: 4
+ realmNum: 2
+ }
+ }
+ rejections {
+ fungible_token {
+ shardNum: 4
+ realmNum: 2
+ tokenNum: 1
+ }
+ }
+ rejections {
+ fungible_token {
+ shardNum: 4
+ realmNum: 2
+ tokenNum: 2
+ }
+ }
+ rejections {
+ nft {
+ token_ID {
+ shardNum: 4
+ realmNum: 2
+ tokenNum: 3
+ }
+ serial_number: 1
+ }
+ }
+ rejections {
+ nft {
+ token_ID {
+ shardNum: 4
+ realmNum: 2
+ tokenNum: 4
+ }
+ serial_number: 2
+ }
+ }
+ rejections {
+ nft {
+ token_ID {
+ shardNum: 4
+ realmNum: 2
+ tokenNum: 5
+ }
+ serial_number: 3
+ }
+ }
+}
diff --git a/protobufs b/protobufs
index 17fb1486..f3ebaed1 160000
--- a/protobufs
+++ b/protobufs
@@ -1 +1 @@
-Subproject commit 17fb148652b1e2badda1c5cdff531f0fcf7f4c55
+Subproject commit f3ebaed10173a074931650a546dd89dbc3d87cd8