Skip to content

Commit 35ae8b5

Browse files
committed
WIP: modify responses to use tokenRelationships
Signed-off-by: Ricky Saechao <ricky@launchbadge.com>
1 parent 230e5f4 commit 35ae8b5

File tree

10 files changed

+186
-43
lines changed

10 files changed

+186
-43
lines changed

Sources/Hedera/Account/AccountInfo.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public struct AccountInfo: Sendable {
4747
maxAutomaticTokenAssociations: UInt32,
4848
aliasKey: PublicKey?,
4949
ethereumNonce: UInt64,
50+
tokenRelationships: [TokenId: TokenRelationship],
5051
ledgerId: LedgerId,
5152
staking: StakingInfo?
5253
) {
@@ -66,6 +67,7 @@ public struct AccountInfo: Sendable {
6667
self.ethereumNonce = ethereumNonce
6768
self.ledgerId = ledgerId
6869
self.staking = staking
70+
self.tokenRelationships = tokenRelationships
6971
self.guts = DeprecatedGuts(
7072
proxyAccountId: proxyAccountId,
7173
sendRecordThreshold: sendRecordThreshold,
@@ -154,6 +156,9 @@ public struct AccountInfo: Sendable {
154156
/// Staking metadata for this account.
155157
public let staking: StakingInfo?
156158

159+
/// Staking metadata for this account.
160+
public let tokenRelationships: [TokenId: TokenRelationship]
161+
157162
/// Decode `Self` from protobuf-encoded `bytes`.
158163
///
159164
/// - Throws: ``HError/ErrorKind/fromProtobuf`` if:
@@ -178,6 +183,11 @@ extension AccountInfo: TryProtobufCodable {
178183
let staking = proto.hasStakingInfo ? proto.stakingInfo : nil
179184
let proxyAccountId = proto.hasProxyAccountID ? proto.proxyAccountID : nil
180185

186+
var tokenRelationships: [TokenId: TokenRelationship] = [:]
187+
for relationship in proto.tokenRelationships {
188+
tokenRelationships[.fromProtobuf(relationship.tokenID)] = try TokenRelationship.fromProtobuf(relationship)
189+
}
190+
181191
self.init(
182192
accountId: try .fromProtobuf(proto.accountID),
183193
contractAccountId: proto.contractAccountID,
@@ -196,6 +206,7 @@ extension AccountInfo: TryProtobufCodable {
196206
maxAutomaticTokenAssociations: UInt32(proto.maxAutomaticTokenAssociations),
197207
aliasKey: try .fromAliasBytes(proto.alias),
198208
ethereumNonce: UInt64(proto.ethereumNonce),
209+
tokenRelationships: tokenRelationships,
199210
ledgerId: .fromBytes(proto.ledgerID),
200211
staking: try .fromProtobuf(staking)
201212
)

Sources/Hedera/Account/AccountInfoQuery.swift

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,49 @@ public final class AccountInfoQuery: Query<AccountInfo> {
5959
try await Proto_CryptoServiceAsyncClient(channel: channel).getAccountInfo(request)
6060
}
6161

62-
internal override func makeQueryResponse(_ context: Context, _ response: Proto_Response.OneOf_Response) throws
62+
internal override func makeQueryResponse(_ context: Context, _ response: Proto_Response.OneOf_Response) async throws
6363
-> Response
6464
{
65+
let mirrorNodeGateway = try MirrorNodeGateway.forNetwork(context.mirrorNetworkNodes, context.ledgerId)
66+
let mirrorNodeService = MirrorNodeService.init(mirrorNodeGateway)
67+
6568
guard case .cryptoGetInfo(let proto) = response else {
6669
throw HError.fromProtobuf("unexpected \(response) received, expected `cryptoGetInfo`")
6770
}
6871

69-
return try .fromProtobuf(proto.accountInfo)
72+
let accountInfoProto = proto.accountInfo
73+
let accountId = try AccountId.fromProtobuf(accountInfoProto.accountID)
74+
let tokenRelationshipsProto = try await mirrorNodeService.getTokenRelationshipsForAccount(
75+
String(describing: accountId.num))
76+
77+
var tokenRelationships: [TokenId: TokenRelationship] = [:]
78+
79+
for relationship in tokenRelationshipsProto {
80+
tokenRelationships[.fromProtobuf(relationship.tokenID)] = try TokenRelationship.fromProtobuf(relationship)
81+
}
82+
83+
return AccountInfo(
84+
accountId: try AccountId.fromProtobuf(accountInfoProto.accountID),
85+
contractAccountId: accountInfoProto.contractAccountID,
86+
isDeleted: accountInfoProto.deleted,
87+
proxyAccountId: try .fromProtobuf(accountInfoProto.proxyAccountID),
88+
proxyReceived: Hbar.fromTinybars(accountInfoProto.proxyReceived),
89+
key: try .fromProtobuf(accountInfoProto.key),
90+
balance: .fromTinybars(Int64(accountInfoProto.balance)),
91+
sendRecordThreshold: Hbar.fromTinybars(Int64(accountInfoProto.generateSendRecordThreshold)),
92+
receiveRecordThreshold: Hbar.fromTinybars(Int64(accountInfoProto.generateReceiveRecordThreshold)),
93+
isReceiverSignatureRequired: accountInfoProto.receiverSigRequired,
94+
expirationTime: .fromProtobuf(accountInfoProto.expirationTime),
95+
autoRenewPeriod: .fromProtobuf(accountInfoProto.autoRenewPeriod),
96+
accountMemo: accountInfoProto.memo,
97+
ownedNfts: UInt64(accountInfoProto.ownedNfts),
98+
maxAutomaticTokenAssociations: UInt32(accountInfoProto.maxAutomaticTokenAssociations),
99+
aliasKey: try .fromAliasBytes(accountInfoProto.alias),
100+
ethereumNonce: UInt64(accountInfoProto.ethereumNonce),
101+
tokenRelationships: tokenRelationships,
102+
ledgerId: .fromBytes(accountInfoProto.ledgerID),
103+
staking: try .fromProtobuf(accountInfoProto.stakingInfo)
104+
)
70105
}
71106

72107
internal override func validateChecksums(on ledgerId: LedgerId) throws {

Sources/Hedera/Contract/ContractId.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ public struct ContractId: EntityId {
119119
public func toBytes() -> Data {
120120
toProtobufBytes()
121121
}
122+
123+
public func populateContractNum(_ client: Client) async throws -> Self {
124+
let address = try EvmAddress.fromBytes(self.evmAddress!)
125+
126+
let mirrorNodeGateway = try MirrorNodeGateway.forClient(client)
127+
let mirrorNodeService = MirrorNodeService(mirrorNodeGateway)
128+
129+
let contractNum = try await mirrorNodeService.getContractNum(address.toString())
130+
131+
return Self(shard: shard, realm: realm, num: contractNum)
132+
}
133+
122134
}
123135

124136
#if compiler(>=5.7)

Sources/Hedera/Contract/ContractInfo.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ public struct ContractInfo {
6161
/// The maximum number of tokens that a contract can be implicitly associated with.
6262
public let maxAutomaticTokenAssociations: UInt32
6363

64+
/// The tokens associated to the contract
65+
///
66+
/// Query mirror node
67+
public let tokenRelationships: [TokenId: TokenRelationship]
68+
6469
/// Ledger ID for the network the response was returned from.
6570
public let ledgerId: LedgerId
6671

@@ -91,6 +96,12 @@ extension ContractInfo: TryProtobufCodable {
9196
let autoRenewPeriod = proto.hasAutoRenewPeriod ? proto.autoRenewPeriod : nil
9297
let autoRenewAccountId = proto.hasAutoRenewAccountID ? proto.autoRenewAccountID : nil
9398

99+
var tokenRelationships: [TokenId: TokenRelationship] = [:]
100+
101+
for relationship in proto.tokenRelationships {
102+
tokenRelationships[.fromProtobuf(relationship.tokenID)] = try TokenRelationship.fromProtobuf(relationship)
103+
}
104+
94105
self.init(
95106
contractId: try .fromProtobuf(proto.contractID),
96107
accountId: try .fromProtobuf(proto.accountID),
@@ -104,6 +115,7 @@ extension ContractInfo: TryProtobufCodable {
104115
isDeleted: proto.deleted,
105116
autoRenewAccountId: try .fromProtobuf(autoRenewAccountId),
106117
maxAutomaticTokenAssociations: UInt32(proto.maxAutomaticTokenAssociations),
118+
tokenRelationships: tokenRelationships,
107119
ledgerId: .fromBytes(proto.ledgerID),
108120
stakingInfo: try .fromProtobuf(proto.stakingInfo)
109121
)

Sources/Hedera/Contract/ContractInfoQuery.swift

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,30 +55,47 @@ public final class ContractInfoQuery: Query<ContractInfo> {
5555
try await Proto_SmartContractServiceAsyncClient(channel: channel).getContractInfo(request)
5656
}
5757

58-
internal override func makeQueryResponse(_ context: MirrorNetworkContext, _ response: Proto_Response.OneOf_Response) async throws
58+
internal override func makeQueryResponse(_ context: MirrorNetworkContext, _ response: Proto_Response.OneOf_Response)
59+
async throws
5960
-> Response
6061
{
6162
let mirrorNodeGateway = try MirrorNodeGateway.forNetwork(context.mirrorNetworkNodes, context.ledgerId)
6263
let mirrorNodeService = MirrorNodeService.init(mirrorNodeGateway)
63-
64-
switch response {
65-
case .contractGetInfo(let proto):
66-
let contractId = try ContractId(protobuf: proto.contractInfo.contractID)
67-
let tokenRelationships = try await mirrorNodeService.getTokenRelationshipsForAccount(String(describing: contractId.num))
68-
69-
let consensusProto = proto.contractInfo
70-
let updatedProto = consensusProto.
71-
72-
default:
64+
65+
guard case .contractGetInfo(let proto) = response else {
7366
throw HError.fromProtobuf("unexpected \(response) received, expected `contractGetInfo`")
7467
}
68+
let contractInfoProto = proto.contractInfo
69+
let contractId = try ContractId.fromProtobuf(contractInfoProto.contractID)
70+
let tokenRelationshipsProto = try await mirrorNodeService.getTokenRelationshipsForAccount(
71+
String(describing: contractId.num))
72+
73+
var tokenRelationships: [TokenId: TokenRelationship] = [:]
7574

76-
return try .fromProtobuf(proto.contractInfo)
75+
for relationship in tokenRelationshipsProto {
76+
tokenRelationships[.fromProtobuf(relationship.tokenID)] = try TokenRelationship.fromProtobuf(relationship)
77+
}
78+
79+
return ContractInfo(
80+
contractId: try ContractId.fromProtobuf(contractInfoProto.contractID),
81+
accountId: try AccountId.fromProtobuf(contractInfoProto.accountID),
82+
contractAccountId: contractInfoProto.contractAccountID,
83+
adminKey: try .fromProtobuf(contractInfoProto.adminKey),
84+
expirationTime: .fromProtobuf(contractInfoProto.expirationTime),
85+
autoRenewPeriod: .fromProtobuf(contractInfoProto.autoRenewPeriod),
86+
storage: UInt64(contractInfoProto.storage),
87+
contractMemo: contractInfoProto.memo,
88+
balance: .fromTinybars(Int64(contractInfoProto.balance)),
89+
isDeleted: contractInfoProto.deleted,
90+
autoRenewAccountId: try .fromProtobuf(contractInfoProto.autoRenewAccountID),
91+
maxAutomaticTokenAssociations: UInt32(contractInfoProto.maxAutomaticTokenAssociations),
92+
tokenRelationships: tokenRelationships,
93+
ledgerId: .fromBytes(contractInfoProto.ledgerID),
94+
stakingInfo: try .fromProtobuf(contractInfoProto.stakingInfo))
7795
}
7896

7997
internal override func validateChecksums(on ledgerId: LedgerId) throws {
8098
try contractId?.validateChecksums(on: ledgerId)
8199
try super.validateChecksums(on: ledgerId)
82100
}
83101
}
84-

Sources/Hedera/MirrorNodeGateway.swift

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal struct MirrorNodeGateway {
3131
self.mirrorNodeUrl = mirrorNodeUrl
3232
}
3333

34-
internal static func forClient(client: Client) throws -> MirrorNodeGateway {
34+
internal static func forClient(_ client: Client) throws -> MirrorNodeGateway {
3535
let mirrorNodeUrl = try MirrorNodeRouter.getMirrorNodeUrl(client.mirrorNetwork, client.ledgerId)
3636

3737
return .init(mirrorNodeUrl: mirrorNodeUrl)
@@ -45,7 +45,7 @@ internal struct MirrorNodeGateway {
4545

4646
internal func getAccountInfo(_ idOrAliasOrEvmAddress: String) async throws -> [String: Any] {
4747
let fullApiUrl = MirrorNodeRouter.buildApiUrl(
48-
self.mirrorNodeUrl, MirrorNodeRouter.ACCOUNTS_ROUTE, idOrAliasOrEvmAddress)
48+
self.mirrorNodeUrl, MirrorNodeRouter.accountsRoute, idOrAliasOrEvmAddress)
4949

5050
let responseBody = try await queryFromMirrorNode(fullApiUrl)
5151

@@ -66,7 +66,9 @@ internal struct MirrorNodeGateway {
6666

6767
internal func getContractInfo(_ idOrAliasOrEvmAddress: String) async throws -> [String: Any] {
6868
let fullApiUrl = MirrorNodeRouter.buildApiUrl(
69-
self.mirrorNodeUrl, MirrorNodeRouter.CONTRACTS_ROUTE, idOrAliasOrEvmAddress)
69+
self.mirrorNodeUrl, MirrorNodeRouter.contractsRoute, idOrAliasOrEvmAddress)
70+
71+
print("ContractfullApiUrl: \(fullApiUrl)")
7072

7173
let responseBody = try await queryFromMirrorNode(fullApiUrl)
7274

@@ -75,7 +77,6 @@ internal struct MirrorNodeGateway {
7577
domain: "InvalidResponseError", code: -1,
7678
userInfo: [NSLocalizedDescriptionKey: "Response body is not valid UTF-8"])
7779
}
78-
7980
guard let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] else {
8081
throw NSError(
8182
domain: "InvalidResponseError", code: -1,
@@ -87,10 +88,10 @@ internal struct MirrorNodeGateway {
8788

8889
internal func getAccountTokens(_ idOrAliasOrEvmAddress: String) async throws -> [String: Any] {
8990
let fullApiUrl = MirrorNodeRouter.buildApiUrl(
90-
self.mirrorNodeUrl, MirrorNodeRouter.ACCOUNTS_ROUTE, idOrAliasOrEvmAddress)
91-
91+
self.mirrorNodeUrl, MirrorNodeRouter.accountTokensRoute, idOrAliasOrEvmAddress)
92+
9293
let responseBody = try await queryFromMirrorNode(fullApiUrl)
93-
94+
9495
guard let jsonData = responseBody.data(using: .utf8) else {
9596
throw NSError(
9697
domain: "InvalidResponseError", code: -1,

Sources/Hedera/MirrorNodeRouter.swift

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,46 +26,43 @@ import HederaProtobufs
2626
import NIOCore
2727

2828
internal struct MirrorNodeRouter {
29-
static let API_VERSION: String = "/api/v1"
29+
static let apiVersion: String = "/api/v1"
3030

31-
static let LOCAL_NODE_PORT = "5551"
31+
static let localNodePort = "5551"
3232

33-
public static let ACCOUNTS_ROUTE = "accounts"
34-
public static let CONTRACTS_ROUTE = "contracts"
35-
public static let ACCOUNT_TOKENS_ROUTE = "accounts_tokens"
33+
public static let accountsRoute = "accounts"
34+
public static let contractsRoute = "contracts"
35+
public static let accountTokensRoute = "account_tokens"
3636

3737
static let routes: [String: String] = [
38-
ACCOUNTS_ROUTE: "/accounts/%@",
39-
CONTRACTS_ROUTE: "/contracts/%@",
40-
ACCOUNT_TOKENS_ROUTE: "/accounts/%@/tokens",
38+
accountsRoute: "/accounts/%@",
39+
contractsRoute: "/contracts/%@",
40+
accountTokensRoute: "/accounts/%@/tokens",
4141
]
4242

4343
private func MirrorNodeRouter() {}
4444

4545
static func getMirrorNodeUrl(_ mirrorNetwork: [String], _ ledgerId: LedgerId?) throws -> String {
46-
let mirrorNodeAddress: String? =
47-
mirrorNetwork
46+
var mirrorNodeAddress: String = ""
47+
48+
mirrorNetwork
4849
.map { address in
4950
address.prefix { $0 != ":" }
5051
}
51-
.first.map { String($0) }
52-
53-
if mirrorNodeAddress == nil {
54-
fatalError("Mirror address not found")
55-
}
52+
.first.map { mirrorNodeAddress = String($0) }!
5653

5754
var fullMirrorNodeUrl: String
5855

5956
if ledgerId != nil {
60-
fullMirrorNodeUrl = String("http://\(mirrorNodeAddress)")
57+
fullMirrorNodeUrl = String("https://\(mirrorNodeAddress)")
6158
} else {
62-
fullMirrorNodeUrl = String("http://\(mirrorNodeAddress):\(LOCAL_NODE_PORT)")
59+
fullMirrorNodeUrl = String("http://\(mirrorNodeAddress):\(localNodePort)")
6360
}
6461

6562
return fullMirrorNodeUrl
6663
}
6764

6865
static func buildApiUrl(_ mirrorNodeUrl: String, _ route: String, _ id: String) -> String {
69-
return String("\(mirrorNodeUrl)\(API_VERSION)\(String(format: "\(String(describing: routes[route]))", id))")
66+
return String("\(mirrorNodeUrl)\(apiVersion)\(String(format: "\(String(describing: routes[route]))", id))!")
7067
}
7168
}

Sources/Hedera/MirrorNodeService.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ internal final class MirrorNodeService {
6464

6565
let contractIdNum = ContractId(String(describing: contractId))?.num
6666

67+
fatalError("contract id: \(contractIdNum)")
68+
6769
return contractIdNum!
6870
}
6971

@@ -104,8 +106,7 @@ internal final class MirrorNodeService {
104106
let accountTokensResponse = try await self.mirrorNodeGateway.getAccountTokens(evmAddress)
105107

106108
guard let tokens = accountTokensResponse["tokens"] else {
107-
fatalError("Error while processing getTokenRelationshipsForAccount mirror node query")
108-
109+
fatalError("Error while processing getTokenRelationshipsForAccount mirror node query: \(accountTokensResponse)")
109110
}
110111

111112
var tokenBalances: [Proto_TokenRelationship] = []

0 commit comments

Comments
 (0)